在反汇编/重新组装C ++程序时重用符号

时间:2015-02-06 20:47:18

标签: c assembly elf symbols undefined-symbol

是的,我又来了。我正在开发一个工具,可以反汇编/重新组合剥离的二进制文件,现在我陷入(外部)符号重用问题。

测试在32位Linux x86平台上进行。

假设我正在编写一个C ++程序,在GCC编译器生成的汇编代码中,存在一些这样的指令:

call    _ZNSt8ios_baseC2Ev
movl    _ZTTSt14basic_ifstreamIcSt11char_traitsIcEE+4, %ebx
movb    $0, 312(%esp)
movl    _ZTTSt14basic_ifstreamIcSt11char_traitsIcEE+8, %ecx
....

请特别注意符号_ZTTSt14basic_ifstreamIcSt11char_traitsIcEE

编译之后,假设我得到一个unstripped二进制文件,我检查了这个符号:

readelf -s a.out | grep "_ZTTSt14basic"
69: 080a7390    16 OBJECT  WEAK   DEFAULT   27 _ZTTSt14basic_ifstreamIcS@GLIBCXX_3.4 (3)
72: 080a7220    16 OBJECT  WEAK   DEFAULT   27 _ZTTSt14basic_ofstreamIcS@GLIBCXX_3.4 (3)
705: 080a7220    16 OBJECT  WEAK   DEFAULT   27 _ZTTSt14basic_ofstreamIcS
1033: 080a7390    16 OBJECT  WEAK   DEFAULT   27 _ZTTSt14basic_ifstreamIcS

请参阅,这是我的第一个问题,为什么符号_ZTTSt14basic_ifstreamIcSt11char_traitsIcEE的名称已修改为_ZTTSt14basic_ifstreamIcS_ZTTSt14basic_ifstreamIcS@GLIBCXX_3.4 (3)

什么是_ZTTSt14basic_ifstreamIcS@GLIBCXX_3.4 (3)

然后我剥离了二进制文件:

strip a.out
readelf -s a.out | grep "_ZTTSt14basic"
69: 080a7390    16 OBJECT  WEAK   DEFAULT   27 _ZTTSt14basic_ifstreamIcS@GLIBCXX_3.4 (3)
72: 080a7220    16 OBJECT  WEAK   DEFAULT   27 _ZTTSt14basic_ofstreamIcS@GLIBCXX_3.4 (3)

然后在我反汇编二进制文件后,相应的反汇编汇编指令是:

 8063ee7:       e8 84 54 fe ff          call   8049370 <_ZNSt8ios_baseC2Ev@plt>
 8063eec:       8b 1d 94 73 0a 08       mov    0x80a7394,%ebx
 8063ef2:       c6 84 24 38 01 00 00    movb   $0x0,0x138(%esp)
 8063ef9:       00
 8063efa:       8b 0d 98 73 0a 08       mov    0x80a7398,%ecx

此时我们可以发现0x80a7394等于_ZTTSt14basic_ifstreamIcSt11char_traitsIcEE+4

为了重用这些说明,我修改了代码:

call _ZNSt8ios_baseC2Ev
mov _ZTTSt14basic_ifstreamIcS+4,%ebx
movb $0x0,0x138(%esp)
mov _ZTTSt14basic_ifstreamIcS+8,%ecx

并进行了类似的更新(请参阅此question以供参考):

echo ""_ZTTSt14basic_ifstreamIcS@GLIBCXX_3.4 (3)" = 0x080a7390;" > symbolfile
g++ -Wl,--just-symbols=symbolfile  final.s

readelf -s a.out | grep "_ZTTSt14basic"

3001: 080a7390     0 NOTYPE  LOCAL  DEFAULT   27 _ZTTSt14basic_ifstreamIcS
8412: 080a7390     0 NOTYPE  GLOBAL DEFAULT  ABS _ZTTSt14basic_ifstreamIcS

我调试了新生成的二进制文件,令我惊讶的是,在新生成的二进制文件中,符号_ZTTSt14basic_ifstreamIcS_ZNSt8ios_baseC2Ev的函数调用后没有得到任何值,而在原始二进制文件中,函数调用_ZTTSt14basic_ifstreamIcS确实得到一些引用库部分的内存地址。这意味着:

call _ZNSt8ios_baseC2Ev
mov _ZTTSt14basic_ifstreamIcS+4,%ebx  <--- %ebx gets zero!
movb $0x0,0x138(%esp)
mov _ZTTSt14basic_ifstreamIcS+8,%ecx  <--- %ecx gets zero!

我必须说明在原始二进制文件的这些行中,寄存器%ebx和%ecx都获得了一些引用libc部分的地址。

这是我的第二个问题,为什么符号_ZTTSt14basic_ifstreamIcS在函数调用_ZNSt8ios_baseC2Ev之后没有得到任何值?我也尝试过使用符号名_ZTTSt14basic_ifstreamIcSt11char_traitsIcEE。但这也行不通。

我清楚了吗?谁能救我的屁股?谢谢!

0 个答案:

没有答案