ELF的代理共享库(sharedlib,shlib,so)?

时间:2012-01-20 02:37:31

标签: c dll proxy shared-libraries elf

在Windows上,创建“代理DLL”或多或少是常见的,代替原始DLL并将调用转发给它(在需要时执行任何其他操作之后)。例如,您可以阅读herehere

但是,Linux下的shlib munging文化是完全不同的。首先,LD_PRELOAD是Linux下的ld.so的内置功能,它只是将单独的shlib注入进程并使用它定义为覆盖的任何符号。而这种“注入”技术似乎定义了整个思维方向 - 这里是a typical ELF hacking toolthis question,其中绅士似乎与我有相同的用法,但首先要问他如何修补现有的二进制文件。 / p>

不,谢谢。我不想注入或修改那些也不是我的东西。我想要做的就是创建一个独立的代理shlib,它将调用原始代理。理想情况下,会有一个工具可以用原始的.so提供,并创建一个C源代码,它只会重定向到原始的函数,同时让我轻松覆盖我想要的任何东西。那么,这样的工具在哪里? ;-)谢谢。

2 个答案:

答案 0 :(得分:1)

使用LD_PRELOAD并没有真正涉及修改不是您自己的东西,并且注入与正常的动态库加载没有什么不同。 ERESI项目中的“典型的ELF黑客工具”与LD_PRELOAD无关。您不必担心。 here是编写LD_PRELOAD的“代理”的一个很好的介绍。

话虽如此,如果您想为某个库创建系统范围的代理,则可能会认为全局设置LD_PRELOAD(从而将代理加载到系统上运行的每个二进制文件中)是不受欢迎的。它通常用于通过libeatmydatasocksify之类的工具覆盖glibc中的函数,但是如果要覆盖比glibc大和/或不那么广泛的库中的函数,则是有意义的试图找到另一种方法,真正为那个库创建一个代理。

一种这样的方法是使用patchelf --replace-needed--add-needed硬编码原始库的完整路径名,然后通过设置LD_LIBRARY_PATH¹确保首先找到代理库。因此,完整的过程是:

  1. 创建一个支持LD_PRELOAD的库,该库将覆盖原始库的某些功能(在继续进行之前,测试它仅使用LD_PRELOAD起作用!)
  2. 编译该库并将其与原始库链接,以便ldd libwrapper-foo.so包含以下内容:
    libfoo.so.0 => /usr/lib/x86_64-linux-gnu/libfoo.so.0 (0x0000deadbeef0000)
  3. 使用patchelf对完整路径进行硬编码:
    patchelf --replace-needed libfoo.so.0 /usr/lib/x86_64-linux-gnu/libfoo.so.0 libwrapper-foo.so
  4. 符号链接libwrapper-foo.solibfoo.so.0
  5. 现在LD_LIBRARY_PATH=. ldd $(which program-that-uses-libfoo)应该包括以下几行:
    libfoo.so.0 => ./libfoo.so.0 (0x0000dead56780000)
    /usr/lib/x86_64-linux-gnu/libfoo.so.0 (0x0000dead1234000000)
  6. LD_LIBRARY_PATH设置为您的.bashrc或某处包装器库的完整路径

此类代理库的真实示例是my wrapper for libpango,它可以为所有应用程序进行亚像素定位。


¹)也可以将此代理库放入/usr/local/lib,但是ldconfig(更新共享库缓存的工具)拒绝使用具有硬编码绝对路径的库。

答案 1 :(得分:0)

apitrace是一个工具,它涵盖了对许多平台的图形库(OpenGL,DirectX)调用的详细跟踪。对于通用解决方案来说,它可能过于详细和复杂,但至少提供了一些参考和亲和力。