将代码/符号修补为动态链接的ELF二进制文件
假设我有一个动态链接的ELF二进制文件,并且我想覆盖/重定向某些库调用。我知道我可以用LD_PRELOAD
来做到这一点,但我想要一个在二进制文件中永久存在的独立于环境的解决方案,它适用于setuid/setgid二进制文件,其中没有一个可以实现。将代码/符号修补为动态链接的ELF二进制文件
我想要做的是从其他目标文件(可能在新的部分,如有必要)添加代码,并将这些目标文件中的符号添加到二进制符号表中,以便新添加的代码版本获取用于代替共享库代码。我相信这应该是可能的,而不需要在现有代码中实际执行任何重定位;即使它们在同一个文件中,它们也应该能够在运行时以通常的PLT方式解决(因为它值得我只关心函数,而不关心数据)。
请不要给我答案,沿着“你不想这样做!”或者“那不是便携的!”我正在处理的是一种连接二进制文件与ABI不兼容的备用共享库实现的方式。有问题的平台是i386-linux(即32位)。除非我误解了什么是可能的,否则我可以编写一些工具来解析ELF文件并执行我的黑客攻击,但我怀疑有一种奇特的方式使用GNU链接器和其他工具来完成此操作,而无需编写新代码。
您可以在程序本身中处理一些动态链接。特别是阅读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()而不是信任链接器以正确的顺序获取库。
编辑:我怀疑如果重写的库内的一个不同的函数调用重写的函数,原始函数被调用,而不是覆盖。我不知道如果一个动态库调用另一个库会发生什么。
我想修改二进制文件,而不是源文件。 – 2010-10-27 05:48:26
ld
可以选择--wrap
,它可以让您用符号malloc
代替给定的符号,您可以将其称为__wrap_malloc
。因此,您可以为您感兴趣的功能编写一些存根,并将其链接到相关库。
再次,这个问题是关于修补二进制文件,而不是在我编译的程序中包装库调用。 – 2010-10-27 06:38:45
R .:我不明白为什么你不能在你提出的问题中问你提出的问题。 '__wrap_malloc'不需要调用旧的'malloc',它只是用另一个符号替换一个符号。 'ld'是处理我知道的二进制文件,便携式,灵活的所有你需要的最好的工具。但是你似乎在你的脑海中有某些类型的答案,这并不一定反映在你的问题中。 – 2010-10-27 06:54:32
如果您的意思是有一种方法可以使用现有的可执行ELF文件并添加代码来定义一些符号,否则这些符号将被解析为共享库代码,只使用GNU'ld',我很想知道如何。但请注意,这需要应用的输入程序是可执行的ELF文件,而不是'.o'文件或源文件。 – 2010-10-27 08:23:19
我似乎不能仅仅为此问题添加评论,因此将其张贴为“答案”。很抱歉,这样做只是希望帮助其他搜索答案的人。
所以,我似乎也有类似的用例,但我明确地找到任何修改不能接受(对我来说)现有的二进制文件,所以我在寻找独立代理方式:Proxy shared library (sharedlib, shlib, so) for ELF?
我不知道这是不是为你工作,但检查'nm'系统命令(你可能已经知道它)。给出了相当多的关于这样的信息。 – Marm0t 2010-10-27 04:32:36
哇,LD_PRELOAD技巧看起来很有趣!我也在寻找一种在二进制文件中执行它的方法。我的问题是我的二进制文件有一个象征,表示我的BeagleBone的链接程序无法解析。 – CJxD 2015-09-28 00:22:10