m1n1/proxyclient/xnutools.py

113 lines
3.1 KiB
Python
Raw Normal View History

# SPDX-License-Identifier: MIT
import re
from construct import *
DebuggerState = Struct(
"panic_options" / Hex(Int64ul),
"current_op" / Hex(Int32ul),
"proceed_on_sync_failre" / Int32ul,
"message" / Hex(Int64ul),
"panic_str" / Hex(Int64ul),
"panic_args" / Hex(Int64ul),
"panic_data_ptr" / Hex(Int64ul),
"panic_caller" / Hex(Int64ul),
"entry_count" / Hex(Int32ul),
"kern_return" / Hex(Int32sl)
)
# Darwin va_list is just a stack pointer...
VaList = Struct(
"stack" / Hex(Int64ul),
)
def decode_debugger_state(u, ctx):
p = u.proxy
iface = u.iface
def hv_readmem(addr, size):
addr = p.hv_translate(addr, False, False)
assert addr != 0
return iface.readmem(addr, size)
p_state = p.hv_translate(ctx.regs[23], False, False)
assert p_state != 0
di = iface.readstruct(p_state, DebuggerState)
print(di)
message = hv_readmem(di.message, 1024).split(b"\x00")[0].decode("ascii")
print()
print(f"Message: {message}")
print("===== Panic string =====")
decode_panic(u, di.panic_str, di.panic_args)
print("========================")
def decode_panic_call(u, ctx):
decode_panic(u, ctx.regs[0], ctx.regs[1])
def decode_panic(u, p_string, p_args):
p = u.proxy
iface = u.iface
def hv_readmem(addr, size):
addr = p.hv_translate(addr, False, False)
assert addr != 0
return iface.readmem(addr, size)
string = hv_readmem(p_string, 1024).split(b"\x00")[0].decode("ascii")
p_args = p.hv_translate(p_args, False, False)
args = iface.readstruct(p_args, VaList)
stack = hv_readmem(args.stack, 504)
def va_arg(t):
nonlocal stack
d, stack = stack[:8], stack[8:]
return t.parse(d)
utypes = {
"hh": Int8ul,
"h": Int16ul,
None: Int32ul,
"l": Int64ul,
"ll": Int64ul,
"q": Int64ul,
"s": Int64ul,
"t": Int64ul,
}
stypes = {
"hh": Int8sl,
"h": Int16sl,
None: Int32sl,
"l": Int64sl,
"ll": Int64sl,
"q": Int64sl,
"s": Int64sl,
"t": Int64sl,
}
#print(string)
def format_arg(match):
pat, flags, width, mod, conv = match.group(0, 1, 2, 3, 4)
if conv == "%":
return "%"
elif conv == "s":
return hv_readmem(va_arg(Int64ul), 1024).split(b"\x00")[0].decode("ascii")
elif conv in "di":
v = va_arg(stypes[mod])
return f"%{flags or ''}{width or ''}{conv or ''}" % v
elif conv in "ouxX":
v = va_arg(utypes[mod])
return f"%{flags or ''}{width or ''}{conv or ''}" % v
elif conv in "p":
return f"0x{va_arg(Int64ul):x}"
else:
return f"[{pat!r}:{va_arg(Int64ul):x}]"
string = re.sub('%([-#0 +]*)([1-9][0-9]*)?(hh|h|l|ll|q|L|j|z|Z|t)?([diouxXeEfFgGaAcsCSpnm%])',
format_arg, string)
print(string + "\n", end="")