59 lines
1.9 KiB
Python
59 lines
1.9 KiB
Python
#!/usr/bin/env python3
|
|
"""disasm_func.py — full-function disassembler with resolved RIP constants.
|
|
Usage: disasm_func.py <VA> [max_bytes]
|
|
Stops on int3-run after a ret. Prints resolved [rip+X] targets inline.
|
|
"""
|
|
import sys
|
|
import struct
|
|
from capstone import Cs, CS_ARCH_X86, CS_MODE_64
|
|
from capstone.x86 import X86_OP_MEM, X86_REG_RIP
|
|
|
|
BASE = 0x180000000
|
|
_data = open('/home/m/re-tools/soothe_mem.bin', 'rb').read()
|
|
|
|
def rd(va, n):
|
|
return _data[va - BASE: va - BASE + n]
|
|
|
|
def main():
|
|
va = int(sys.argv[1], 16)
|
|
maxb = int(sys.argv[2], 16) if len(sys.argv) > 2 else 0x4000
|
|
code = rd(va, maxb)
|
|
md = Cs(CS_ARCH_X86, CS_MODE_64)
|
|
md.detail = True
|
|
out = []
|
|
run_int3 = 0
|
|
seen_ret = False
|
|
for ins in md.disasm(code, va):
|
|
line = '%08x %-22s %s %s' % (ins.address, ins.bytes.hex(), ins.mnemonic, ins.op_str)
|
|
note = ''
|
|
for op in ins.operands:
|
|
if op.type == X86_OP_MEM and op.mem.base == X86_REG_RIP:
|
|
tgt = ins.address + ins.size + op.mem.disp
|
|
note += ' ; ->%x' % tgt
|
|
b4 = rd(tgt, 8)
|
|
f32v = struct.unpack('<f', b4[:4])[0]
|
|
f64v = struct.unpack('<d', b4[:8])[0]
|
|
u64v = struct.unpack('<Q', b4[:8])[0]
|
|
if abs(f32v) > 1e-6 and abs(f32v) < 1e8:
|
|
note += ' f32=%.6g' % f32v
|
|
elif abs(f64v) > 1e-6 and abs(f64v) < 1e12:
|
|
note += ' f64=%.6g' % f64v
|
|
else:
|
|
note += ' u64=%x' % u64v
|
|
line += note
|
|
out.append(line)
|
|
if ins.mnemonic == 'ret':
|
|
seen_ret = True
|
|
run_int3 = 0
|
|
elif ins.mnemonic == 'int3':
|
|
if seen_ret:
|
|
run_int3 += 1
|
|
if run_int3 >= 4:
|
|
break
|
|
else:
|
|
run_int3 = 0
|
|
print('\n'.join(out))
|
|
|
|
if __name__ == '__main__':
|
|
main()
|