二进制文件的变量活性分析

逆向工程 二元分析 小精灵 二进制 堆栈变量 局部变量
2021-06-30 10:08:40

我想检测所有的变量在一个二进制的任何指令/地址。对于变量,我指的是两者global以及function local变量。换句话说,给定一个 Linux ELF 和一个虚拟地址,有没有办法以编程方式知道当时所有的变量(就内存位置而言)是什么?

IDA Pro 似乎检测过程中可能变量的内存位置。IDA 是否公开任何 API 来收集此类信息?

我计划使用 DynamoRIO 在运行时动态监控程序。call-ret对应该标记一个函数的开始和结束。一旦遇到call,我就会监视由%ebp引用的堆栈位置上的所有读写访问%esp问题是尾调用,其中编译器优化了call替换为jmp,从而几乎不可能检测到函数。

1个回答

我不认为这是可能的。

让我们假设以下 C 代码:

int f1(int p1, int p2)
{
    int l1, l2, l3;
    /* some code */
    l1 = l1 + l2; // here is our virtual address
    return l1;
}

int f2(int p3, int p4)
{
    int l4, l5, l6;
    return f1(p3, p4);
}

int f3(int p5, p6)
{
    int l7, l8;
    return f2(p5, p6) + f1(p6, p5);
}

显然,在调用 f3、f2 和 f1 时,该线程整个堆栈中的局部变量集会有所不同。

例如,当 f3 调用 f2 时,f2 的局部变量在堆栈上。在 f3 调用 f1 时调用 f2 后,显然整个线程堆栈是不同的,f2 本地人不活跃,如果不知道完整的执行顺序和堆栈跟踪,就不可能恢复调用者的完整堆栈布局。

然而,确定全局变量更简单——它们始终处于活动状态,可以通过对所有数据和 bss 进行迭代来检索,例如 elf 段,例如,以下简单代码:

import idautils
import idc
seg_list = [".bss", ".data"] #insert your segment names here
seg_addrs = []
for seg in Segments():
    if idc.SegName(seg) in seg_list:
        seg_addrs.append(seg)

for seg in seg_addrs:  
    start = SegStart(seg)
    end = SegEnd(seg)
    for ea in idautils.Heads(start, end):
        gen_xrefs = XrefsTo(ea, 0)
        for xx in gen_xrefs:
            print hex(ea), hex(xx.frm)

Ida 识别为引用的所有内容都将被打印出来。然而,这些结果的准确性是有问题的,取决于 IDA 分析的准确性。

通过获取栈帧结构可以获取函数局部变量和栈布局,使用如下API:

GetFrame(ea)         #Get ID of function frame structure
GetFrameLvarSize(ea) #Get size of local variables in function frame
GetFrameRegsSize(ea) #Get size of saved registers in function frame
GetFrameArgsSize(ea) #Get size of arguments in function frame which are purged upon return
GetFrameSize(ea)     #Get full size of function frame

可以使用来自 idc 模块的以下 IDAPython API 观察框架结构:

GetMemberId(sid, member_offset)
GetStrucPrevOff(sid, offset)
GetStrucNextOff(sid, offset)
GetFirstMember(sid)
GetLastMember(sid)
GetMemberOffset(sid, member_name)
GetMemberName(sid, member_offset)
GetMemberComment(sid, member_offset, repeatable)
GetMemberSize(sid, member_offset)
GetMemberFlag(sid, member_offset)
GetMemberStrId(sid, member_offset)
IsUnion(sid)

希望能帮助到你。