Quote:
Originally Posted by Apdo God
As far as I'm aware they are.
To make sure you can use wireshark: 1. Filter the game's server IP. 2. Look at the UDP payload section. 3. Check for any human readable patterns like player names or anything repeatable. If you can't see anything like that - the data is 100% encrypted.
|
I did that, I didn't see any username in there however there was some stuff that was repeated between packets at the start like 0x4c, 0xcc. Don't have access to the game anymore to do more tests but I have a program that captures packets from open UDP ports of any process if anyone is interested in doing more tests:
main.go
Code:
package main
import (
"encoding/hex"
"errors"
"fmt"
"slices"
"strconv"
"unsafe"
"github.com/google/gopacket/pcap"
"golang.org/x/sys/windows"
)
func findArcRaidersProcess() (proc windows.ProcessEntry32) {
if snapshot, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPPROCESS, 0); err != nil {
panic(err)
} else {
var procEntry windows.ProcessEntry32
procEntry.Size = uint32(unsafe.Sizeof(procEntry))
var err error
for err = windows.Process32First(snapshot, &procEntry); err == nil; err = windows.Process32Next(snapshot, &procEntry) {
exeName := windows.UTF16ToString(procEntry.ExeFile[:])
if exeName == "PioneerGame.exe" {
return procEntry
}
}
}
return proc
}
type ip_header struct {
ver_ihl byte // Version (4 bits) + Internet header length (4 bits)
tos byte // Type of service
tlen int16 // Total length
identification int16 // Identification
flags_fo uint16 // Flags (3 bits) + Fragment offset (13 bits)
ttl byte // Time to live
proto byte // Protocol
crc uint16 // Header checksum
saddr uint32 // Source address
daddr uint32 // Destination address
op_pad uint32 // Option + Padding
}
func decodeIPH(data *byte) ip_header {
iph := *(*ip_header)(unsafe.Pointer(data))
iph.tlen = int16(NetToHostShort(uint16(iph.tlen)))
// [MENTION=670966]ToDo[/MENTION]: Complete
return iph
}
func main() {
// Get Arc ports
arcProcEntry := findArcRaidersProcess()
fmt.Printf("ARC Raiders PID: %d\n", int(arcProcEntry.ProcessID))
ports := getProcessPortsUDP(arcProcEntry.ProcessID)
slices.Sort(ports)
// Build BPF filter string
filter := "udp"
if len(ports) > 0 {
portsExpr := ""
for i, port := range ports {
if i != 0 {
portsExpr += " or "
}
portsExpr += strconv.FormatUint(uint64(port), 10)
}
filter += " dst port " + portsExpr
}
fmt.Printf("BPF filter: \"%s\"\n", filter)
ifs, err := pcap.FindAllDevs()
if err != nil {
panic(err)
}
for i, iface := range ifs {
fmt.Printf("[%d] - %s\n", i, iface.Description)
}
adapterIndex := 0
fmt.Scanf("%d", &adapterIndex)
if adapterIndex <= 0 || adapterIndex > len(ifs) {
panic(errors.New("adapterIndex out of bounds"))
}
if handle, err := pcap.OpenLive(ifs[adapterIndex].Name, 1600, true, pcap.BlockForever); err != nil {
panic(err)
} else if err := handle.SetBPFFilter(filter); err != nil {
panic(err)
} else {
fmt.Println("No errors")
handle.SetDirection(pcap.DirectionInOut)
for {
packetBytes, ci, err := handle.ReadPacketData()
if err != nil {
break
}
fmt.Println(ci)
fmt.Printf("len(packetBytes): %d\n", len(packetBytes))
fmt.Printf("packetBytes:\n%+v\n", hex.EncodeToString(packetBytes))
}
handle.Close()
}
}
udpPorts.go
Code:
package main
import (
"unsafe"
"golang.org/x/sys/windows"
)
type UDP_TABLE_CLASS = uintptr
const (
UdpTableBasic UDP_TABLE_CLASS = iota
UdpTableOwnerPid
UdpTableOwnerModule
)
type _MIB_UDPROW_OWNER_PID struct {
dwLocalAddr uint32
dwLocalPort uint32
dwOwningPid uint32
}
func getProcessPortsUDP(pid uint32) (ports []uint16) {
ipHlpApi := windows.NewLazySystemDLL("Iphlpapi.dll")
procGetExtendedUdpTable := ipHlpApi.NewProc("GetExtendedUdpTable")
// First get the required buffer size
var bufferSize uint32
var udpConnectionCount uint32
procGetExtendedUdpTable.Call(0, uintptr(unsafe.Pointer(&bufferSize)), 0, windows.AF_INET, UdpTableOwnerPid, 0)
buffer := make([]byte, bufferSize)
// Get the actual UDP table
if r1, _, err := procGetExtendedUdpTable.Call(uintptr(unsafe.Pointer(&buffer[0])), uintptr(unsafe.Pointer(&bufferSize)), 0, windows.AF_INET, UdpTableOwnerPid, 0); err != windows.ERROR_SUCCESS {
panic(err)
} else if r1 != windows.NO_ERROR {
panic(r1)
} else {
// Cast the buffer to the correct type
udpTable := (*_MIB_UDPROW_OWNER_PID)(unsafe.Pointer(&buffer[4]))
udpConnectionCount = (bufferSize - 4) / uint32(unsafe.Sizeof(*udpTable))
udpConnections := unsafe.Slice(udpTable, udpConnectionCount)
// Filter connections by PID
for _, udpRow := range udpConnections {
if pid == udpRow.dwOwningPid {
ports = append(ports, NetToHostShort(uint16(udpRow.dwLocalPort)))
}
}
}
return ports
}
ntoh.go
Code:
package main
import "encoding/binary"
func NetToHostLong(i uint32) uint32 {
bytes := make([]byte, 4)
binary.BigEndian.PutUint32(bytes, i)
return binary.LittleEndian.Uint32(bytes)
}
func NetToHostShort(i uint16) uint16 {
bytes := make([]byte, 2)
binary.BigEndian.PutUint16(bytes, i)
return binary.LittleEndian.Uint16(bytes)
}