Skip to content

Instantly share code, notes, and snippets.

@GXTX
Last active February 14, 2022 23:49
Show Gist options
  • Save GXTX/0ba2d5a69afde3a859e45f2252e78f01 to your computer and use it in GitHub Desktop.
Save GXTX/0ba2d5a69afde3a859e45f2252e78f01 to your computer and use it in GitHub Desktop.
package main
import (
"bytes"
"encoding/binary"
"fmt"
"os"
"strings"
"time"
"unsafe"
)
const MAGIC_OFFSET = 0x600;
const NETWORK_SETTINGS_OFFSET = 0x1000;
const MACHINE_OFFSET = 0x1200;
type MainConfig struct {
Magic [4]byte
NumberOfBoots uint32
FormatDate [8]byte
}
type XLiveAccount struct {
XUID [0x10]byte
UNK1 uint64
Gamertag [0x10]byte
Flags uint32
Passcode [0x4]byte
Domain [0x14]byte
Realm [0x18]byte
Confounder [0x14]byte
Verification [0x10]byte
}
type NetworkSettings struct {
SectionBeginSignature [0x04]byte // Present at the start of new sections in the config sectors
UNK1 [0x04]byte // Always 1?
UNK2 [0x04]byte // Always 1?
UNK3 [0x40]byte
Flags [0x02]byte // Maybe only takes 1 byte? How are setting derived from it?
MACAddress [0x06]byte
Static IPv4AddressBlock
PrimaryDNS IPv4
SecondaryDNS IPv4
HostName [0x28]byte
PPPOEUserName [0x40]byte
PPPOEPassword [0x40]byte
UNK4 [0x28]byte
PPPOEServiceName [0x28]byte
UNK5 [0x94]byte // Padding? Might contain DHCP IP, server, DNS?
NetworkEndSignature [0x04]byte // Always contains "XBCP"
UNK6 [0x04]byte
SecionEndSignature [0x02]byte // Always 0x55 0xAA
}
type IPv4 [4]byte
type IPv4AddressBlock struct {
Address IPv4
Subnet IPv4
Gateway IPv4
PrimaryDNS IPv4
SecondaryDNS IPv4
}
type Filetime struct {
LowDateTime uint32
HighDateTime uint32
}
func main() {
file, err := os.OpenFile("/home/dev/Desktop/Files/disk.bin", os.O_RDONLY, 0666)
if err != nil {
panic(err)
}
readHeader(file)
readAccounts(file)
readNetworkSettings(file)
}
func readHeader(f *os.File) MainConfig {
var config MainConfig
buf := make([]byte, unsafe.Sizeof(config))
l, err := f.ReadAt(buf, MAGIC_OFFSET)
if err != nil || l != len(buf) {
panic(err)
}
r := bytes.NewReader(buf)
err = binary.Read(r, binary.LittleEndian, &config)
if err != nil {
panic(err)
}
if string(config.Magic[:]) != "BRFR" {
panic("Missing magic bytes!")
}
fmt.Printf("Magic: %v, NumberOfBoots: %v, HDDFormatDate: %v\n",
string(config.Magic[:]),
config.NumberOfBoots,
time.Unix(0, filetimeToNano(config.FormatDate)).UTC())
return config
}
func readAccounts(f *os.File) []XLiveAccount {
var accountsBuffer XLiveAccount
var LiveAccounts []XLiveAccount
buf := make([]byte, unsafe.Sizeof(accountsBuffer))
offset := MACHINE_OFFSET
for i := 0; i <= 8; i++ {
if i == 1 {
offset += 0x600
} else if i != 0 {
offset += 0x200
}
_, err := f.ReadAt(buf, int64(offset))
if err != nil {
panic(err)
}
r := bytes.NewReader(buf)
err = binary.Read(r, binary.LittleEndian, &accountsBuffer)
if err != nil {
panic(err)
}
if strings.Count(string(accountsBuffer.Gamertag[:]), string(0x0)) != 16 {
LiveAccounts = append(LiveAccounts, accountsBuffer)
fmt.Printf("Account Name: %v, Domain: %v, Realm: %v, XUID: %x\n",
string(accountsBuffer.Gamertag[:]),
string(accountsBuffer.Domain[:]),
string(accountsBuffer.Realm[:]),
accountsBuffer.XUID)
}
}
return LiveAccounts
}
func readNetworkSettings (f *os.File) NetworkSettings {
var networksettings NetworkSettings
buf := make([]byte, unsafe.Sizeof(networksettings))
l, err := f.ReadAt(buf, NETWORK_SETTINGS_OFFSET)
if err != nil || l != len(buf) {
panic(err)
}
r := bytes.NewReader(buf)
err = binary.Read(r, binary.LittleEndian, &networksettings)
if err != nil {
panic(err)
}
return networksettings
}
// Helper
func filetimeToNano(t [8]byte) int64 {
ft := Filetime{
LowDateTime: binary.LittleEndian.Uint32(t[:4]),
HighDateTime: binary.LittleEndian.Uint32(t[4:]),
}
nsec := int64(ft.HighDateTime)<<32 + int64(ft.LowDateTime)
nsec -= 116444736000000000
nsec *= 100
return nsec
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment