如何找到ELF符号表参考?

逆向工程 艾达 小精灵 符号
2021-06-26 22:50:16

在一个巨大的 ELF 二进制文件中,我发现了一些使用某种(字符串)常量的函数。常量本身似乎存储在二进制文件本身中,但我不知道如何解决 IDA 的反汇编结果:

.text:096B3D58 lea     eax, (stru_8199A2C.st_shndx+1 - 96B3D47h)[ebx]
.text:096B3D5E push    eax             ; char *
.text:096B3D5F push    edx             ; this
.text:096B3D60 call    _ZN11NameDB7resolveEPKc ; NameDB::resolve(char const*)

我的问题是了解 LEA 指令的来源。对我来说,它读起来像“符号表索引之前 0x96B3D47 字节处的符号”。奇怪的是,位置 096B3D47 只是上面摘录的几行......

1个回答

奇怪的是,位置 096B3D47 只是上面摘录的几行......

...并且该地址之前的指令是一条call指令。对?

这种指令用于与位置无关的代码:该代码可以加载到另一个地址中,并且无需修改即可以相同的方式工作。通常它是这样工作的:

    call some_address                         ; 1
some_address:
    pop ebx                                   ; 2
    lea eax, (some_text - some_address)[ebx]  ; 3
    ...
some_text:
    ...
  1. call指令之后,指令之后的指令地址call将被压入堆栈。这意味着地址some_address现在在堆栈上。
  2. 使用pop我们some_address从堆栈中读取的地址(并从那里删除它)。
  3. 此指令将进行计算,some_text - some_address + someaddress因此该指令与 具有相同的效果lea eax, [some_text]

some_text - some_address当可执行文件加载到不同的内存地址时,距离总是相同的。因此,lea指令将在执行程序的位置(地址)上独立工作。

call指令也是如此,因为指令的参数call是相对于 PC 存储的。

lea eax, [some_text]然而,指令的参数将是一个绝对(不是 PC 相关的)地址,因此在另一个地址执行程序时必须交换它。

对我来说,它读起来像“符号表索引之前 0x96B3D47 字节处的符号”。

如果lea指令有重定位表条目,反汇编器可以从重定位表中获取信息。

在您的情况下,这似乎有所不同:

您的反汇编程序似乎也足够智能,可以看到此时ebx包含地址 096B3D47。因此,就知道该指令lea eax, XYZ[ebx]将导致一个值096B3D47+XYZeax寄存器。

因此,它会将指令反汇编为lea eax, ((XYZ+096B3D47)-096B3D47)[ebx]并尝试找出地址XYZ+096B3D47什么符号

然而,我知道的许多反汇编程序只是在这里猜测;他们假设地址属于该地址之前的最后一个符号。在你的情况下,符号stru_8199A2C.st_shndx似乎就是那个符号。

显然,您的反汇编器不仅会评估符号,还会评估调试信息,例如“Dwarf”调试数据(其中包含调试器使用的信息)。