如何从二进制转换为可重定位目标文件并返回?

Mik*_*wan 5 c linker gcc

我希望将一个目标文件注入现有的二进制文件中.我尝试的方法是:

  • 将已编译的二进制文件转换为可重定位目标文件.
  • 用于gcc/ld将可重定位目标文件与要嵌入的目标文件链接起来.

鉴于来源:

#include <stdlib.h>
#include <stdio.h>

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

host用以下代码编译它:

gcc -Wall host.c -o host
Run Code Online (Sandbox Code Playgroud)

我使用以下命令转换为可重定位目标文件:

objcopy -B i386 -I binary -O elf64-x86-64 host host.o
Run Code Online (Sandbox Code Playgroud)

然后我尝试链接:

gcc host.o -o host
Run Code Online (Sandbox Code Playgroud)

理想情况下,这会将可重定位目标文件重新链接回二进制文件.这也有机会链接任何额外的目标文件.不幸的是,该命令给出了以下错误:

/usr/lib/gcc/x86_64-linux-gnu/4.6.1/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

我的问题是为什么会出现这个错误,我将如何正确地重新连接?

我尝试的东西是在这一点链接另一个目标文件,其中包含一个虚拟主(因为我想我以后可以手动修补入口点),但是发生的事情是新的二进制文件似乎重新定位了旧的代码.奇怪的方式与符号表完全搞砸了.

额外的信息

readelf 在二进制文件上产生以下内容:

mike@mike-ubuntu:~/Desktop/inject-obj$ readelf -h host
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x400410
  Start of program headers:          64 (bytes into file)
  Start of section headers:          4424 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         9
  Size of section headers:           64 (bytes)
  Number of section headers:         30
  Section header string table index: 27
Run Code Online (Sandbox Code Playgroud)

在可重定位目标文件上:

mike@mike-ubuntu:~/Desktop/inject-obj$ readelf -h host.o
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          8480 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           64 (bytes)
  Number of section headers:         5
  Section header string table index: 2
Run Code Online (Sandbox Code Playgroud)

合理

对于那些感兴趣的人,可以在这里找到理由.

R..*_*R.. 3

非 PIE 的可执行文件无法重定位。搬迁已经进行,搬迁记录已被丢弃。也就是说,重新定位它需要找到二进制代码和数据内的对象或函数的所有地址,但无法确定字节序列是地址还是其他类型的数据或代码。

应该有一种方法可以完成您最初想做的事情(添加新代码),但您所采取的方法注定会失败。