首页 > 解决方案 > 拦截动态链接库的静态链接依赖项

问题描述

我正在尝试调试第三方应用程序正在使用的 API。第三方应用程序有一个我认为不可能的配置:

应用程序二进制文件包含其共享库依赖项之一所需的导出。也就是说,它们动态链接了它们的依赖关系,但该依赖关系的依赖关系是静态链接的。

这发生在具有古老内核的基于 MIPS 的 linux 上。

我已经使用 Ghidra 来反汇编可执行文件/共享库来确认这一点。

基本上我们有二进制文件和共享对象

file initApp
initApp: ELF 32-bit LSB executable, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, interpreter /lib/ld-uClibc.so.0, stripped

file libhyCoreSdk.so
libhyCoreSdk.so: ELF 32-bit LSB shared object, MIPS, MIPS32 rel2 version 1 (SYSV), dynamically linked, stripped

objdump -T libhyCoreSdk.so | grep -i IMP_ISP_Open
00047900      DF *UND*  00000000 IMP_ISP_Open

initApp 在 libhyCoreSdk.so 中调用“coreAvInit”,然后 libhyCoreSdk.so 在 initApp 中调用 IMP_ISP_Open()。

您可能会想“这并不罕见,您可以通过回调、传递指针、调用 dlsym 等来做到这一点。” 但这不是那些东西,这是符号的直接​​导入/导出,这正是您希望看到 libhyCoreSdk 是否依赖于另一个共享库时所看到的。

除此之外,我真正的问题是我试图弄清楚 IMP_ISP_Open 传递了哪些参数,而 LD_PRELOAD 无助于这种奇怪/独特的情况。我有另一个示例应用程序,它针对 API 的共享库版本调用相同的 API。当我针对该版本使用 LD_PRELOAD(加载我编写的一个小拦截器程序)时,效果很好。但是当我对链接回二进制文件的这个版本使用它时,它不起作用。

我希望有人对我如何拦截这些 API 调用有想法。

部分解决方案:

Daniel Kleinstein 给了我一个好的开始。我将目标函数从 IMP_... 重命名为 XMP_...(例如 IMP_ISP_DisableSensor-> XMP_ISP_DisableSensor)。现在,我的 LD_PRELOAD 中的 IMP_ISP_DisableSensor 已正确命中。不幸的是,我仍然遇到麻烦。调用 dlsym(RTLD_DEFAULT, "XMP_ISP_DisableSensor") 无明显原因返回 NULL ......这意味着我无法重定向回原始函数。

尽管 objdump 显示了这一点:

objdump -T initApp_mod | grep -i XMP
0061fb5c g    DF .text  00000338  Base        XMP_FrameSource_CreateChn
00613c6c g    DF .text  00000204  Base        XMP_ISP_DisableSensor
006097f0 g    DF .text  00000eb0  Base        XMP_Encoder_CreateChn

标签: clinuxmips

解决方案


您的动态依赖项不是静态链接到您的主要可执行文件。加载动态依赖项时,会搜索其导入并由可执行文件导出的符号解析 - 实际上,可执行文件的符号将始终在任何其他动态依赖项之前解析。


不幸的是,这也会阻止您使用LD_PRELOAD.

LD_PRELOAD不起作用,因为它注入的库优先于主可执行文件本身导出的符号 - 仅优先于共享库导出的符号。


如果您希望使用 拦截调用LD_PRELOAD,一个粗略但有效的解决方案是将主可执行文件的导出符号修补为不同的名称 - 这样在加载动态依赖项时它不会解析,并且您的注入库可以提供该符号。


推荐阅读