【问题标题】:ELF patching, binding issueELF补丁,绑定问题
【发布时间】:2020-10-15 14:11:31
【问题描述】:

目前我正在尝试修补 ELF 可执行对象文件。

我正在使用原始的 hello-world 应用程序测试我的实用程序。打补丁后一切似乎都很好,但在执行时,应用程序出现了段错误。

修补时,我还插入了一个新的共享对象依赖项。为了了解出了什么问题,我同时设法将共享对象链接到我的测试应用程序中。这样我就会收到格式正确的g++-made 结果,我可以将其与我的算法结果(或多或少)进行比较。

我遇到的问题是,在执行期间,我修改后的 hello-world 应用程序无法调用 std::cout 例程,因为 std::ostream::sentry::sentry(std::ostream&) ctor 失败;我设法使用gdb 解决了这个问题。在调试并与格式良好的结果进行比较时,我设法找出了问题所在。看来std::cout / _ZSt4cout 重定位绑定符号有点被滥用。尽管两个结果在.dynamic 部分中具有完全相同的DT_NEEDED 条目(顺序也相同),并且尽管它们在.dynsym 部分中都有一个std::cout 的导入符号条目,并相应地修改了@ 987654331@ 和 .gnu.hash 内容, - 尽管有这些, - std::ios_base::Init::Init() 函数在解析 std::cout 对象时,对这两个结果的操作不同。对于格式良好的结果 - 在 hello-world 应用程序的 .bss 部分中的正确条目上,而对于我的算法结果 - 在 @987654338 中的 std::cout 条目上(如 readelf 实用程序验证) libstdc++ 共享库的 @ 部分。

最后但并非最不重要的一点是,当使用 LD_DEBUG=bindings 选项执行时,我收到以下格式正确结果的输出(添加 std::cin / _ZSt3cin 以进行对比):

...
     10067: binding file /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0] to ./hello_world_wellformed [0]: normal symbol `_ZSt4cout' [GLIBCXX_3.4]
     10067: binding file /home/user/Documents/Test/libmyexternal.so [0] to ./hello_world_wellformed [0]: normal symbol `_ZSt4cout' [GLIBCXX_3.4]
     10067: binding file ./hello_world_wellformed [0] to /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0]: normal symbol `_ZSt4cout' [GLIBCXX_3.4]
...
     10067: binding file /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0] to ./hello_world_wellformed [0]: normal symbol `_ZSt3cin' [GLIBCXX_3.4]
     10067: binding file ./hello_world_wellformed [0] to /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0]: normal symbol `_ZSt3cin' [GLIBCXX_3.4]
...

而对于算法修改的结果:

...
     10027: binding file /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0] to /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0]: normal symbol `_ZSt4cout' [GLIBCXX_3.4]
     10027: binding file /home/user/Documents/Test/libmyexternal.so [0] to /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0]: normal symbol `_ZSt4cout' [GLIBCXX_3.4]
     10027: binding file ./hello_world_algotest  [0] to /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0]: normal symbol `_ZSt4cout' [GLIBCXX_3.4]
...
     10027: binding file /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0] to /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0]: normal symbol `_ZSt3cin' [GLIBCXX_3.4]
     10027: binding file ./hello_world_algotest [0] to /usr/lib/x86_64-linux-gnu/libstdc++.so.6 [0]: normal symbol `_ZSt3cin' [GLIBCXX_3.4]
...

我该如何解决这个问题,或者出现这种行为的原因是什么? glibclibstdc++ 如何处理这种情况以及经过算法修改的应用程序的 std::cout 条目如何对库变得“不可见”(尽管 readelfobjdumpnm 实用程序表明一切都正确)?

当然,glibclibstdc++ 版本和相同,两个 hello-world 应用程序都在相同的g++ 版本下编译。 .bss 部分正确驻留,所有部分和段都设置了正确的标志。

【问题讨论】:

    标签: linux gcc binding g++ elf


    【解决方案1】:

    glibc 源中挖掘,使用gdb(并且丢失了几天),我到达了_dl_lookup_symbol_xdo_lookup_x 函数,在dl-lookup.c 中定义;通过的参数向我展示了差异(格式良好的结果和算法派生的结果之间)在于哈希值。好吧,我忘记了 GNU 哈希表被错误地修改了。添加导入功能后,您必须更改 GNU 哈希表索引(幸运的是,您不必重建整个哈希表,只需更新索引;不要忘记,添加导入功能时,您仍然需要更改.dynsym 和 GNU 版本表内容)(对整个 GNU 散列概念的一个非常酷的解释可以在这里看到:https://flapenguin.me/elf-dt-gnu-hash)。顺便说一句,我发现并修复了一个带有过时 .bss 部分编号的错误(由于部分重建而发生)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-18
      • 1970-01-01
      • 2010-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-21
      相关资源
      最近更新 更多