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

时间:2012-03-22 00:15:59

标签: c gcc linker

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

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

鉴于来源:

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

int main(void)
{
    puts("main");
    return EXIT_SUCCESS;
}

我使用以下内容将其编译为host

gcc -Wall host.c -o host

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

objcopy -B i386 -I binary -O elf64-x86-64 host host.o

然后我尝试使用以下链接:

gcc host.o -o host

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

/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

我的问题是为什么会出现此错误以及如何正确重新连接?

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

额外信息

二进制文件的

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

在可重定位目标文件上:

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

原理

对于那些感兴趣的人,可以找到基本原理here

1 个答案:

答案 0 :(得分:3)

非PIE的可执行文件无法进行重定位。已经进行了重新安置,并且拆除了这些重新安置的记录。也就是说,重新定位它需要在代码和二进制数据中查找对象或函数的所有地址,但是不可能确定字节序列是地址还是某种其他类型的数据或代码。 / p>

应该有办法做你原本想做的事情(添加新代码),但你采取的方法注定要失败。