mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-23 13:19:54 +00:00
55 lines
1.7 KiB
Python
55 lines
1.7 KiB
Python
# https://gist.github.com/thestr4ng3r/403fecffc081a899618b1500ba6d1156
|
|
# https://github.com/radareorg/radare2/issues/12070
|
|
|
|
import r2pipe
|
|
|
|
r = r2pipe.open()
|
|
ptr_size = int(r.cmd("e asm.bits").strip()) // 8
|
|
|
|
addr_stackptr = {}
|
|
|
|
blocks = r.cmdj("afbj")
|
|
|
|
def sp_delta_for_fcn_call(fcn):
|
|
cc = fcn["calltype"]
|
|
if cc == "stdcall":
|
|
nargs = fcn["nargs"]
|
|
return -nargs * ptr_size
|
|
return 0
|
|
|
|
def sp_delta_for_instr(instr):
|
|
if instr["type"] == "call" or instr["type"] == "ucall":
|
|
if "jump" in instr:
|
|
call_fcn = r.cmdj("afij@{}".format(instr["jump"]))
|
|
if len(call_fcn) > 0:
|
|
return sp_delta_for_fcn_call(call_fcn[0])
|
|
else:
|
|
print("WARNING: Target not known for jump at {:#x}!".format(instr["addr"]))
|
|
return 0 if "stackptr" not in instr else instr["stackptr"]
|
|
|
|
def block_at(addr):
|
|
for block in blocks:
|
|
if block["addr"] == addr:
|
|
return block
|
|
return None
|
|
|
|
def trace_block(block, stackptr):
|
|
instrs = r.cmdj("aoj {}@{}".format(block["ninstr"], block["addr"]))
|
|
for instr in instrs:
|
|
addr = instr["addr"]
|
|
if addr in addr_stackptr:
|
|
if addr_stackptr[addr] != stackptr:
|
|
print("WARNING: mismatch at {:#x}: {} != {}".format(addr, stackptr, addr_stackptr[addr]))
|
|
return
|
|
addr_stackptr[addr] = stackptr
|
|
stackptr -= sp_delta_for_instr(instr)
|
|
if "jump" in block:
|
|
trace_block(block_at(block["jump"]), stackptr)
|
|
if "fail" in block:
|
|
trace_block(block_at(block["fail"]), stackptr)
|
|
|
|
trace_block(blocks[0], 0)
|
|
|
|
for addr, stackptr in addr_stackptr.items():
|
|
r.cmd("CC sp: {}@{}".format(stackptr, addr))
|