#!/usr/bin/env python3 """disasm_func.py — full-function disassembler with resolved RIP constants. Usage: disasm_func.py [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(' 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()