假设我有一个动态链接的ELF二进制文件,我想覆盖/重定向某些库调用。我知道我可以使用LD_PRELOAD
执行此操作,但我想要一个在二进制文件中永久存在的解决方案,独立于环境,并且适用于setuid / setgid二进制文件,其中LD_PRELOAD
都无法实现。< / p>
我想要做的是添加其他目标文件中的代码(如果需要,可能在新的部分中),并将这些目标文件中的符号添加到二进制符号表中,以便使用新添加的代码版本代替共享库代码。我相信这应该是可能的,而不需要在现有代码中实际执行任何重定位;即使它们在同一个文件中,这些也应该能够在运行时以通常的PLT方式解决(因为我只关心函数而不是数据)。
请不要给我答案“你不想这样做!”或者“那不便携!”我正在研究的是一种将二进制文件与稍微ABI不兼容的备用共享库实现连接起来的方法。有问题的平台是i386-linux(即32位),如果重要的话。除非我弄错了什么是可能的,否则我可以编写一些工具来解析ELF文件并执行我的黑客攻击,但我怀疑有一种奇特的方法可以使用GNU链接器和其他工具来完成此操作而无需编写新代码。
答案 0 :(得分:5)
答案 1 :(得分:2)
ld
有--wrap
选项,可让您将malloc
之类的符号替换为您调用__wrap_malloc
的符号。有了它,您可以为您感兴趣的函数编写一些存根,并将其链接到相关库。
答案 2 :(得分:1)
我似乎无法在此问题上添加评论,因此将其发布为&#34;答案&#34;。对此感到抱歉,这样做只是为了帮助其他搜索答案的人。
所以,我似乎有类似的用例,但我明确地发现对现有二进制文件的任何修改都是不可接受的(对我而言),所以我正在寻找独立的代理方法:Proxy shared library (sharedlib, shlib, so) for ELF?
答案 3 :(得分:0)
您可以在程序中处理一些动态链接。特别是阅读dlsym(3)的手册页,并为动态链接接口的其余部分阅读dlopen(3),dlerror(3)和dlclose(3)。
一个简单的例子 - 说我想从libc覆盖dup2(2)。我可以使用以下代码(让我们称之为“dltest.c”):
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dlfcn.h>
int (*prev_dup2)(int oldfd, int newfd);
int dup2(int oldfd, int newfd) {
printf("DUP2: %d --> %d\n", oldfd, newfd);
return prev_dup2(oldfd, newfd);
}
int main(void) {
int i;
prev_dup2 = dlsym(RTLD_NEXT, "dup2");
if (!prev_dup2) {
printf("dlsym failed to find 'dup2' function!\n");
return 1;
}
if (prev_dup2 == dup2) {
printf("dlsym found our own 'dup2' function!\n");
return 1;
}
i = dup2(1,3);
if (i == -1) {
perror("dup2() failed");
}
return 0;
}
编译:
gcc -o dltest dltest.c -ldl
静态链接的dup2()函数会覆盖库中的dup2()。即使该函数在另一个.c文件中(并且被编译为单独的.o),这也可以工作。
如果您的重写函数本身是动态链接的,您可能希望使用dlopen()而不是信任链接器以正确的顺序获取库。
编辑:我怀疑如果被覆盖的库中的不同函数调用了重写函数,则调用原始函数而不是覆盖。我不知道如果一个动态库调用另一个动态库会发生什么。