【发布时间】:2012-12-08 05:44:36
【问题描述】:
我有一个静态链接到 libc 的 elf 二进制文件。 我无权访问它的 C 代码。 我想使用 OpenOnload 库,它在用户空间中实现了套接字,因此与标准 libc 版本相比提供了更低的延迟。 OpenOnload 实现标准套接字 api,并使用 LD_PRELOAD 覆盖 libc 版本。 但是,由于这个 elf 二进制文件是静态链接的,它不能使用 OpenOnload 版本的套接字 API。
我相信可以通过以下步骤将此二进制文件转换为与 OpenOnload 动态链接:
- 添加新的程序头:PT_INTERP、PT_DYNAMIC 和 PT_LOAD。
- 在 PT_DYNAMIC 中添加条目以列出与 libc 的依赖关系。
- 在新的 PT_LOAD 部分中为所需的 libc 函数添加 PLT 存根。
- 修改现有的 libc 函数二进制代码以跳转到相应的 PLT 存根。
作为第一次剪辑,我尝试只添加 3 个 PT_LOAD 段。在现有的 PT_LOAD 段标头之后添加了新的段标头。此外,未修改现有段的 vm_addr。基于 p_align 将现有段的文件偏移量移至下一个对齐地址。 在文件末尾添加了新的 PT_LOAD 段。
重写文件后,当我运行它时,它被内核正确加载,但立即出现seg-faulted。
我的问题是:
- 如果我只是移动 elf 二进制文件中的文件偏移量,而不修改 vm_addresses,它会在运行二进制文件时导致任何错误吗?
- 是否可以做我正在尝试的事情?有人尝试过吗?
【问题讨论】:
-
理论上这可以工作,但我认为你几乎肯定会看到无限数量的错误——你甚至还没有遇到的大问题是,glibc 预计会有在任何给定的地址空间中只有一个自身的副本,如果违反该期望,重要的事情(如
malloc)将无法预测地崩溃。您最好通过反汇编程序运行整个二进制文件,手动删除所有 libc,然后重新组装和重新链接它。 -
我可能只是为库写一个薄包装器..
-
我同意扎克的观点。你会花费不合理的时间来做这件事,而且它可能不会像你想要的那样工作(魔鬼在细节中)。所以不要那样做!
-
扎克,glibc 是希望只加载一份副本还是只使用一份副本?我的意思是,如果我将所有对 glibc 函数的调用从静态链接的 glibc 重定向到动态加载的调用,它可以工作吗?
-
Zack,你能详细说明一下反汇编程序吗?我该怎么做呢?我的意思是我可以在 Linux 上使用哪个反汇编程序?
标签: c linux elf openonload