我正在尝试编写一个IDAPython脚本,该脚本将返回对本地堆栈框架变量的引用列表。但是,我找不到能做到这一点的任何API。

我想要实现的是类似以下代码的代码: />


预先感谢。

#1 楼

有一个函数可以执行此操作:build_stkvar_xrefs,用C ++定义,但通过Python SWIG绑定公开。 IDA会在您需要时动态构建堆栈外部参照。为了使用该功能,需要进行一些设置。

您将需要使用一些功能来获得所需的功能:



get_func(ea):在func_t处检索函数的ea结构


get_frame(func_t foo):为struct_t指定的
功能框返回foo结构/>
DecodeInstruction(ea):返回代表inst_t处的指令的ea


get_stkvar(op_t op, sval_t v)op是对指令的引用,v是操作数中的立即数。通常您只使用op.addr。它返回一个元组(member_t, val)member_t是指向堆栈变量的指针,这是我们所需要的。 val与堆栈var的soff中的member_t字段具有相同的值。稍后将对此进行更多介绍。在xreflist_t()中。

xreflist:您可以使用此方法迭代框架中的所有堆栈变量以检索所有xreflist_entry_t。如果要为所有堆栈变量构建外部参照,通常会更容易。 > build_stkvar_xrefs(xreflist_t xrefs, func_t func, member_t member)不是堆栈偏移量。我认为这意味着“结构偏移”,它是框架结构的偏移,因此您可以检索其他信息。您需要此字段来使用其他与堆栈变量相关的功能,例如:SetMemberType,SetMemberName,GetMemberName,DelStrucMember等。做类似的事情:

# 0x4012d0 is the function address
# 0x4012dc is an instruction address referencing
# a stack variable. It looks like:
# mov [ebp - 4], ecx

pFunc = get_func(0x4012d0)
pFrame = get_frame(pFunc)
inst = DecodeInstruction(0x4012dc)
op = inst[0] #first operand references stack var
pMember, val = get_stkvar(op, op.addr)
xrefs = xreflist_t()
build_stkvar_xrefs(xrefs, pFunc, pMember)
for xref in xrefs:
    print hex(xref.ea) #print xref address

# Contrived member dictionary example.
dictMem = dict()
x = 0
while(x < pFrame.memqty):
    dictMem[GetMemberName(pFrame.id, pFrame.get_member(x).soff)] = pFrame.get_member(x)
    x = x+1
# given var name you can now use the
# dictionary to grab the member_t to pass
# to build_stkvar_xrefs
pMem = dictMem["var_4"]
xrefs = xreflist_t()
build_stkvar_xrefs(xrefs, pFunc, pMem)
for xref in xrefs:
    print hex(xref.ea) #print xrefs to var_4


如果您想了解有关这些功能的更多信息,建议您阅读IDA SDK文档中的以下模块(不分先后顺序): .hpp
struct.hpp

参考:https://www.hex-rays.com/products/ida/support/sdkdoc/files.html

#2 楼

TL; DR:没有简单的API可以实现此目的,代码在答案的结尾或此处。

据我所知,没有简单的方法来获取对堆栈结构的引用。似乎调用idautils.XrefsTo(sid)可以正常工作,其中sid是帧ID(使用idc.GetFrame检索到)应该可以,但是我在尝试中无法获得任何结果。该函数的指令并在遇到堆栈引用操作数时手动计算堆栈中的偏移量。

我创建了一个摘要片段来说明这一点,尽管我认为这很不言自明,

首先,我们需要将堆栈偏移量映射到参数,这由find_stack_members函数负责,该函数使用上述的idc.GetFrame API函数获取结构ID用于特定功能的堆栈。然后,它使用idautils.StructMembers API遍历堆栈变量。函数被输入),稍后在find_stack_members中将其用于基于当前堆栈增量和操作数立即值计算变量的堆栈偏移量。函数,并跳过除具有定义为引用堆栈的操作数的指令以外的任何指令(请注意,引用堆栈但未被IDA的自动分析或手动定义的参数将不被处理,因此将不视为交叉引用)。如果指令中存在堆栈偏移量操作数,则<space>r函数将继续使用堆栈的基本偏移量(先前由find_stack_xrefs检索)来计算其偏移量,即当前堆栈增量由IDA和可以使用API​​ find_stack_xrefs进行访问,并且立即数来自Operand结构。

为方便起见,我也在此处添加了代码:

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