Last active
January 3, 2021 19:54
-
-
Save thrimbor/537fc25382e95e62156e62d1969fd9fa to your computer and use it in GitHub Desktop.
XBL infodump GDB script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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