我想将一个目标文件注入一个现有的二进制文件.作为一个具体的例子,考虑一个源码Hello.c:
#include <stdlib.h> int main(void) { return EXIT_SUCCESS; }
可以通过gcc -std = gnu99 -Wall Hello.c -o你可以编译成一个名为Hello的可执行文件.此外,现在考虑Embed.c:
func1(void) { }
可以通过gcc -c Embed.c从中创建一个对象文件Embed.o.我的问题是如何一般地将Embed.o插入到Hello中,以便执行必要的重新定位,并且适当的ELF内部表(例如符号表,PLT等)被正确地修补?
假设
可以假设要嵌入的对象文件具有静态链接的依赖关系.可以假设任何动态依赖关系,例如C运行时也存在于目标可执行文件中.
当前尝试/想法
>使用libbfd将对象文件中的部分复制到二进制文件中.我所做的进步是,我可以创建一个新对象,其中包含原始二进制文件和对象文件中的部分.问题是,由于目标文件是可重新定位的,所以它的部分无法正确地复制到输出,而不首先执行重定位.
>将二进制转换回目标文件,并使用ld重新链接.到目前为止,我尝试使用objcopy执行转换objcopy –input elf64-x86-64 – 输出elf64-x86-64 Hello Hello.o.显然,这不工作,因为我打算,因为ld -o Hello2 Embed.o Hello.o然后会导致ld:error:Hello.o:不受支持的ELF文件类型2.我想这应该是预期的,因为你不是一个对象文件.
>查找执行此类插入的现有工具?
理由(可选阅读)
我正在制作一个静态可执行编辑器,其中的愿景是允许将任意用户定义的例程的工具设置为现有的二进制文件.这将分两步进行:
>将对象文件(包含用户定义的例程)注入到二进制文件中.这是一个强制性步骤,而不能通过诸如注入共享对象等替代方法来解决.
>对新的二进制文件执行静态分析,并使用它来将原始代码的静态迂回路由到新添加的代码.
大部分时间已经完成了第2步所需的工作,但是在注入目标文件时遇到麻烦.鉴于其他工具使用相同的对象注入方法(例如EEL),问题是可以解决的.
解决方法
gcc -Wall -shared -fPIC -o libembed.so Embed.c
这应该从Embed.c创建一个可重定位的共享对象.这样,您可以通过在运行环境变量LD_PRELOAD时设置目标二进制文件来加载此共享对象(请参阅更多信息here):
LD_PRELOAD=/path/to/libembed.so Hello
这里的“诀窍”将是找出如何做你的仪器,特别是考虑到它是一个静态的可执行文件.在那里,我不能帮助你,但这是一个在进程内存空间中存在代码的方法之一.你可能想在一个构造函数中做一些初始化,你可以使用一个属性(如果你至少使用gcc):
void __attribute__ ((constructor)) my_init() { // put code here! }