-
-
Save nirizr/fe0ce9948b3db05555da42bbfe0e5a1e to your computer and use it in GitHub Desktop.
import idc, idaapi, idautils, ida_xref | |
def find_stack_members(func_ea): | |
members = {} | |
base = None | |
frame = idc.GetFrame(func_ea) | |
for frame_member in idautils.StructMembers(frame): | |
member_offset, member_name, _ = frame_member | |
members[member_offset] = member_name | |
if member_name == ' r': | |
base = member_offset | |
if not base: | |
raise ValueError("Failed identifying the stack's base address using the return address hidden stack member") | |
return members, base | |
def find_stack_xrefs(func_offset): | |
func_ea = ida_funcs.get_func(func_offset).startEA | |
members, stack_base = find_stack_members(func_ea) | |
for func_item in FuncItems(func_ea): | |
flags = idc.GetFlags(ea) | |
stkvar = 0 if idc.isStkvar0(flags) else 1 if idc.isStkvar1(flags) else None | |
if not stkvar: | |
continue | |
ida_ua.decode_insn(func_item) | |
op = ida_ua.cmd.Operands[stkvar] | |
stack_offset = op.addr + idc.GetSpd(func_item) + stack_base | |
member = members[stack_offset] | |
print("At offset {:x} stack member {} is referenced by operand number {}".format(func_item, member, stkvar)) | |
if __name__ == "__main__": | |
find_stack_xrefs(idc.ScreenEA()) |
This code doesn't work: it's outdated, it has multiple bugs and the algorithm is simply wrong. Don't anyone use it, and if you try, you won't be able to, anyway. I'll give you just a few examples: flags = idc.GetFlags(ea) is just wrong, there is no ea variable in this script. Meaning this code never actually worked. The idc.GetSpd(func_item) call is again wrong: GetSpd takes past-the-end address, not the address of the current instruction.
And even after you supply a proper argument for GetSpd, the formula op.addr + idc.GetSpd(func_item) + stack_base is still wrong. The GetSpd gets the difference between the initial and current values of ESP and doesn't help to determine which stack variable is referenced and on what offset. For example, I have instruction mov [rbp+0F0h+var_18], rax at address 0x14001242A. var_18 is at offset 0x18 respectively. The past-the-end address is 0x140012431, so I do idc.GetSpd(0x140012431), and get -0x118.
Then formula: op.addr + idc.GetSpd(func_item) + stack_base turns into: 0x14001242A + (-0x118) + 0x118, which equals to 0x14001242A, which is the instruction address, not the stack offset. Which makes this answer completely wrong. If you want a working solution, check out the accepted answer in the question: https://reverseengineering.stackexchange.com/a/16095/33592
I wrote this to answer the following RE.SO question:
https://reverseengineering.stackexchange.com/q/16055/2147