如何将目标文件"链接"到可执行/编译二进制文件?

Mik*_*wan 12 c linux linker

问题

我希望将一个目标文件注入现有的二进制文件中.作为一个具体的例子,考虑一个来源Hello.c:

#include <stdlib.h>

int main(void)
{
    return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)

它可以编译为名为Hellothrough 的可执行文件gcc -std=gnu99 -Wall Hello.c -o Hello.此外,现在考虑Embed.c:

func1(void)
{
}
Run Code Online (Sandbox Code Playgroud)

Embed.o可以从此创建目标文件gcc -c Embed.c.我的问题是如何将一般插入Embed.oHello以这样的方式使必要的位置进行,并适当ELF内部表(如符号表,PLT等)正确修补?


假设

可以假设要嵌入的目标文件已经静态链接其依赖关系.可以假设任何动态依赖项(例如C运行时)也存在于目标可执行文件中.


目前的尝试/想法

  • 使用libbfd从对象文件复制到节二进制.我对此所取得的进展是,我可以使用原始二进制文件中的部分和目标文件中的部分创建一个新对象.问题是,由于目标文件是可重定位的,因此无法在不先执行重定位的情况下将其部分正确复制到输出.
  • 将二进制文件转换回目标文件并重新链接ld.到目前为止,我尝试使用objcopy来执行转换objcopy --input elf64-x86-64 --output elf64-x86-64 Hello Hello.o.显然这不符合我的意图,因为那样ld -o Hello2 Embed.o Hello.o会导致ld: error: Hello.o: unsupported ELF file type 2.我想这应该是预期的,因为Hello它不是一个目标文件.
  • 找到执行此类插入的现有工具?

理由(可选阅读)

我正在制作一个静态可执行编辑器,其目的是允许将任意用户定义的例程检测到现有的二进制文件中.这将分两步进行:

  1. 将对象文件(包含用户定义的例程)注入二进制文件.这是一个必需的步骤,不能通过注入共享对象等替代方法来解决.
  2. 对新二进制文件执行静态分析,并使用它来静态地将例程从原始代码转移到新添加的代码.

在大多数情况下,我已经完成了第2步所需的工作,但是我在注入目标文件时遇到了问题.鉴于其他工具使用相同的对象注入方法(例如EEL),问题肯定是可以解决的.

Dan*_*ego 6

如果是我,我希望创建Embed.c一个共享对象libembed.so,如下所示:

gcc -Wall -shared -fPIC -o libembed.so Embed.c
Run Code Online (Sandbox Code Playgroud)

那应该从创建可重定位的共享对象Embed.c。这样,您可以通过LD_PRELOAD在运行环境时设置环境变量来强制目标二进制文件加载此共享库(请参阅此处的更多信息):

LD_PRELOAD=/path/to/libembed.so Hello
Run Code Online (Sandbox Code Playgroud)

这里的“技巧”将是弄清楚如何进行检测,特别是考虑到它是静态可执行文件。在那里,我无济于事,但这是在进程的内存空间中显示代码的一种方法。您可能需要在构造函数中进行某种初始化,可以使用属性进行初始化(如果gcc至少使用,则可以这样做):

void __attribute__ ((constructor)) my_init()
{
    // put code here!
}
Run Code Online (Sandbox Code Playgroud)


bma*_*ies 0

你无法以任何实际的方式做到这一点。预期的解决方案是将该对象放入共享库,然后对其调用 dlopen。