如何将目标文件“链接"到可执行/编译的二进制文件? [英] How to 'link' object file to executable/compiled binary?

查看:28
本文介绍了如何将目标文件“链接"到可执行/编译的二进制文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题

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

I wish to inject an object file into an existing binary. As a concrete example, consider a source Hello.c:

#include <stdlib.h>

int main(void)
{
    return EXIT_SUCCESS;
}

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

It can be compiled to an executable named Hello through gcc -std=gnu99 -Wall Hello.c -o Hello. Furthermore, now consider Embed.c:

func1(void)
{
}

一个目标文件Embed.o可以通过gcc -c Embed.c创建.我的问题是如何将 Embed.o 插入到 Hello 中,以便执行必要的重定位以及适当的 ELF 内部表(例如符号表、PLT、等)是否正确修补?

An object file Embed.o can be created from this through gcc -c Embed.c. My question is how to generically insert Embed.o into Hello in such a way that the necessary relocations are performed, and the appropriate ELF internal tables (e.g. symbol table, PLT, etc.) are patched properly?

假设

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

It can be assumed that the object file to be embedded has its dependencies statically linked already. Any dynamic dependencies, such as the C runtime can be assumed to be present also in the target executable.

目前的尝试/想法

  • 使用 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 不是目标文件.
  • 找到执行这种插入的现有工具?
  • Use libbfd to copy sections from the object file into the binary. The progress I have made with this is that I can create a new object with the sections from the original binary and the sections from the object file. The problem is that since the object file is relocatable, its sections can not be copied properly to the output without performing the relocations first.
  • Convert the binary back to an object file and relink with ld. So far I tried using objcopy to perform the conversion objcopy --input elf64-x86-64 --output elf64-x86-64 Hello Hello.o. Evidently this does not work as I intend since ld -o Hello2 Embed.o Hello.o will then result in ld: error: Hello.o: unsupported ELF file type 2. I guess this should be expected though since Hello is not an object file.
  • Find an existing tool which performs this sort of insertion?

基本原理(可选阅读)

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

I am making a static executable editor, where the vision is to allow the instrumentation of arbitrary user-defined routines into an existing binary. This will work in two steps:

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

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

I have, for the most part, already completed the work necessary for step 2, but I am having trouble with the injection of the object file. The problem is definitely solvable given that other tools use the same method of object injection (e.g. EEL).

推荐答案

如果是我,我希望将 Embed.c 创建到共享对象 libembed.so,像这样:

If it were me, I'd look to create Embed.c into a shared object, libembed.so, like so:

gcc -Wall -shared -fPIC -o libembed.so Embed.c

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

That should created a relocatable shared object from Embed.c. With that, you can force your target binary to load this shared object by setting the environment variable LD_PRELOAD when running it (see more information here):

LD_PRELOAD=/path/to/libembed.so Hello

这里的诀窍"是弄清楚如何进行检测,尤其是考虑到它是一个静态可执行文件.在那里,我帮不了你,但这是让代码存在于进程的内存空间中的一种方法.您可能希望在构造函数中进行某种初始化,您可以使用属性来完成(如果您使用的是 gcc,至少):

The "trick" here will be to figure out how to do your instrumentation, especially considering it's a static executable. There, I can't help you, but this is one way to have code present in a process' memory space. You'll probably want to do some sort of initialization in a constructor, which you can do with an attribute (if you're using gcc, at least):

void __attribute__ ((constructor)) my_init()
{
    // put code here!
}

这篇关于如何将目标文件“链接"到可执行/编译的二进制文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆