Files
soothe2-re/scripts/disasm_func.py
T

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()