Skip to content

Instantly share code, notes, and snippets.

@thrimbor
Last active January 3, 2021 19:54
Show Gist options
  • Save thrimbor/537fc25382e95e62156e62d1969fd9fa to your computer and use it in GitHub Desktop.
Save thrimbor/537fc25382e95e62156e62d1969fd9fa to your computer and use it in GitHub Desktop.
XBL infodump GDB script
# XBL function call info dump script for usage with xemu and gdb
#
# Usage:
# 1. Generate symbol list like this: XbSymbolDatabaseCLI default.xbe >symbols.txt
# 2. Start xemu with the "-s" parameter
# 3. Run gdb from the folder where your symbols.txt resides
# 4. Run "source insignia.py" in gdb
# 5. Done. Calls to XOnlineMatchSearchResultsLen, XOnlineMatchSearch and XOnlineMatchSessionCreate will now be logged in the gdb window.
import gdb
def read_8_hexstr(addr_str, offset):
return gdb.execute('x/1bx ' + addr_str + '+' + str(offset), to_string=True).split(':')[1].strip()
def read_8_int(addr_str, offset):
return int(read_8_hexstr(addr_str, offset), 16)
def read_32_hexstr(addr_str, offset):
return gdb.execute('x/1wx ' + addr_str + '+' + str(offset), to_string=True).split(':')[1].strip()
def read_32_int(addr_str, offset):
return int(read_32_hexstr(addr_str, offset), 16)
def read_64_hexstr(addr_str, offset):
return gdb.execute('x/1gx ' + addr_str + '+' + str(offset), to_string=True).split(':')[1].strip()
def read_64_int(addr_str, offset):
return int(read_64_hexstr(addr_str, offset), 16)
def grab_utf16_string(baseAddrStr):
raw_bytes = []
i = 0
while True:
raw_byte_0 = read_8_int(baseAddrStr, (i*2+0))
raw_byte_1 = read_8_int(baseAddrStr, (i*2+1))
if raw_byte_0 == 0 and raw_byte_1 == 0:
break
raw_bytes.append(raw_byte_0)
raw_bytes.append(raw_byte_1)
i = i + 1
raw_bytes_array = bytearray(raw_bytes)
return raw_bytes_array.decode("utf-16")
def dump_XONLINE_ATTRIBUTE_array(dwNumAttributes, pAttributes):
if dwNumAttributes > 0:
print("Attributes: ")
for i in range(dwNumAttributes):
print("[" + str(i) + "]: ", end='', flush=True)
dwAttributeId = read_32_hexstr(pAttributes, (i*16))
fChanged = read_32_int(pAttributes, (i*16+4))
print("fChanged: " + str(fChanged), end=' ', flush=True)
print("dwAttributeID: " + dwAttributeId, end='', flush=True)
if int(dwAttributeId, 16) & 0xF00000 == 0xF00000:
print("(null) ", end='', flush=True)
elif int(dwAttributeId, 16) & 0x100000 == 0x100000:
print("(string) ", end='', flush=True)
lpValue = read_32_hexstr(pAttributes, (i*16+8))
print("value: " + grab_utf16_string(lpValue), end='', flush=True)
elif int(dwAttributeId, 16) & 0x200000 == 0x200000:
print("(blob) ", end='', flush=True)
print("values: ", end='', flush=True)
pvValue = read_32_hexstr(pAttributes, (i*16+8))
dwLength = read_32_int(pAttributes, (i*16+12))
for i2 in range(dwLength):
value = read_8_hexstr(pvValue, i2)
print(value, end=' ', flush=True)
else:
print("(int) ", end='', flush=True)
qwValue = read_64_hexstr(pAttributes, (i*16+8))
print("value: " + qwValue + ' ', end='', flush=True)
print('')
return False
class XOnlineMatchSearchResultsLenBpClass(gdb.Breakpoint):
def __init__(self, arg):
super().__init__(arg)
def stop(self):
dwNumResults = read_32_int('$sp', 4)
dwNumSessionAttributes = read_32_int('$sp', 8)
pSessionAttributeSpec = read_32_hexstr('$sp', 12)
print("XOnlineMatchSearchResultsLen(dwNumResults: " + str(dwNumResults) + ", dwNumSessionAttributes: " + str(dwNumSessionAttributes) + ", pSessionAttributeSpec: " + pSessionAttributeSpec + ");")
if dwNumSessionAttributes > 0:
print("Attributes:")
for i in range(dwNumSessionAttributes):
print("[" + str(i) + "]: ", end='', flush=True)
dwType = read_32_hexstr(pSessionAttributeSpec, (i*8))
dwLength = read_32_int(pSessionAttributeSpec, (i*8+4))
print("dwType: " + dwType + " ", end='', flush=True)
print("dwLength: " + str(dwLength))
return False
class XOnlineMatchSearchBpClass(gdb.Breakpoint):
def __init__(self, arg):
super().__init__(arg)
def stop(self):
dwProcedureIndex = read_32_int('$sp', 4)
dwNumResults = read_32_int('$sp', 8)
dwNumAttributes = read_32_int('$sp', 12)
pAttributes = read_32_hexstr('$sp', 16)
dwResultsLen = read_32_int('$sp', 20)
hWorkEvent = read_32_int('$sp', 24)
phTask = read_32_int('$sp', 28)
print("XOnlineMatchSearch(dwProcedureIndex: " + str(dwProcedureIndex) + ", dwNumResults: " + str(dwNumResults) + ", dwNumAttributes: " + str(dwNumAttributes) + ", pAttributes: " + pAttributes + ", dwResultsLen: " + str(dwResultsLen) + ", hWorkEvent: " + hex(hWorkEvent) + ", phTask: " + hex(phTask) + ")")
dump_XONLINE_ATTRIBUTE_array(dwNumAttributes, pAttributes)
return False
class XOnlineMatchSessionCreateBpClass(gdb.Breakpoint):
def __init__(self, arg):
super().__init__(arg)
def stop(self):
dwPublicCurrent = read_32_int('$sp', 4)
dwPublicAvailable = read_32_int('$sp', 8)
dwPrivateCurrent = read_32_int('$sp', 12)
dwPrivateAvailable = read_32_int('$sp', 16)
dwNumAttributes = read_32_int('$sp', 20)
pAttributes = read_32_hexstr('$sp', 24)
hWorkEvent = read_32_hexstr('$sp', 28)
phTask = read_32_hexstr('$sp', 32)
print("XOnlineMatchSessionCreate(", end='', flush=True)
print("dwPublicCurrent: " + str(dwPublicCurrent), end=', ', flush=True)
print("dwPublicAvailable: " + str(dwPublicAvailable), end=', ', flush=True)
print("dwPrivateCurrent: " + str(dwPrivateCurrent), end=', ', flush=True)
print("dwPrivateAvailable: " + str(dwPrivateAvailable), end=', ', flush=True)
print("dwNumAttributes: " + str(dwNumAttributes), end=', ', flush=True)
print("pAttributes: " + pAttributes, end=', ', flush=True)
print("hWorkEvent: " + hWorkEvent, end=', ', flush=True)
print("phTask: " + phTask + ")")
dump_XONLINE_ATTRIBUTE_array(dwNumAttributes, pAttributes)
return False
class XOnlineMatchSessionUpdateBpClass(gdb.Breakpoint):
def __init__(self, arg):
super().__init__(arg)
def stop(self):
print("bp hit!")
dwPublicCurrent = read_32_int('$sp', 12)
dwPublicAvailable = read_32_int('$sp', 16)
dwPrivateCurrent = read_32_int('$sp', 20)
dwPrivateAvailable = read_32_int('$sp', 24)
dwNumAttributes = read_32_int('$sp', 28)
pAttributes = read_32_hexstr('$sp', 32)
hWorkEvent = read_32_hexstr('$sp', 36)
phTask = read_32_hexstr('$sp', 40)
print("XOnlineMatchSessionUpdate(", end='', flush=True)
print("dwPublicCurrent: " + str(dwPublicCurrent), end=', ', flush=True)
print("dwPublicAvailable: " + str(dwPublicAvailable), end=', ', flush=True)
print("dwPrivateCurrent: " + str(dwPrivateCurrent), end=', ', flush=True)
print("dwPrivateAvailable: " + str(dwPrivateAvailable), end=', ', flush=True)
print("dwNumAttributes: " + str(dwNumAttributes), end=', ', flush=True)
print("pAttributes: " + pAttributes, end=', ', flush=True)
print("hWorkEvent: " + hWorkEvent, end=', ', flush=True)
print("phTask: " + phTask + ")")
dump_XONLINE_ATTRIBUTE_array(dwNumAttributes, pAttributes)
return False
gdb.execute('set arch i386')
gdb.execute('target remote 127.0.0.1:1234')
XOnlineMatchSearchResultsLenBp = None
XOnlineMatchSearchBp = None
XOnlineMatchSessionCreateBp = None
XOnlineMatchSessionUpdateBp = None
bp_addrs = {}
f = open("symbols.txt", "r")
for l in f:
prefixed_name, addr = l.split(' = ')
name = prefixed_name.split('__')[1]
if name in ['XOnlineMatchSearchResultsLen', 'XOnlineMatchSearch', 'XOnlineMatchSessionCreate', 'XOnlineMatchSessionUpdate']:
bp_addrs[name] = addr
if bp_addrs['XOnlineMatchSearchResultsLen'] != None:
XOnlineMatchSearchResultsLenBp = XOnlineMatchSearchResultsLenBpClass('*' + bp_addrs['XOnlineMatchSearchResultsLen'])
if bp_addrs['XOnlineMatchSearch'] != None:
XOnlineMatchSearchBp = XOnlineMatchSearchBpClass('*' + bp_addrs['XOnlineMatchSearch'])
if bp_addrs['XOnlineMatchSessionCreate'] != None:
XOnlineMatchSessionCreateBp = XOnlineMatchSessionCreateBpClass('*' + bp_addrs['XOnlineMatchSessionCreate'])
if bp_addrs['XOnlineMatchSessionUpdate'] != None:
XOnlineMatchSessionUpdateBp = XOnlineMatchSessionUpdateBpClass('*' + bp_addrs['XOnlineMatchSessionUpdate'])
certAddr = read_32_hexstr('0x00010000', 0x0118)
titleIDhex = read_32_hexstr(certAddr, 0x0008)
titleID = int(titleIDhex, 16)
print("Found title ID: " + titleIDhex + ' (' + chr((titleID & 0xFF000000) >> 24) + chr((titleID & 0x00FF0000) >> 16) + '-' + str(titleID & 0x0000FFFF) + ')')
gdb.execute('c')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment