ELF - .got 段的起始地址与 GOT(全局偏移表)的入口点地址不同

逆向工程 手臂 小精灵
2021-07-09 12:07:03

readelf以前是读取ELF文件的信息的。我发现.got节头的地址与从动态节中读取的GOT入口点地址不同。.got地址和GOT入口点之间存储的数据是垃圾吗?以下是从readelf.


ELF Header - 此 ELF 在 ARMv7A 上运行。

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          38412 (bytes into file)
  Flags:                             0x5000200, Version5 EABI, soft-float ABI
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         8
  Size of section headers:           40 (bytes)
  Number of section headers:         26
  Section header string table index: 25

节标题-的地址.got位于0x00008eac

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .note.gnu.build-i NOTE            00000134 000134 000024 00   A  0   0  4
  [ 2] .dynsym           DYNSYM          00000158 000158 0006a0 10   A  3   1  4
  [ 3] .dynstr           STRTAB          000007f8 0007f8 000704 00   A  0   0  1
  [ 4] .hash             HASH            00000efc 000efc 000334 04   A  2   0  4
  [ 5] .gnu.version      VERSYM          00001230 001230 0000d4 02   A  2   0  2
  [ 6] .gnu.version_d    VERDEF          00001304 001304 00001c 00   A  3   1  4
  [ 7] .gnu.version_r    VERNEED         00001320 001320 000020 00   A  3   1  4
  [ 8] .rel.dyn          REL             00001340 001340 000178 08   A  2   0  4
  [ 9] .rel.plt          REL             000014b8 0014b8 000250 08  AI  2  10  4
  [10] .plt              PROGBITS        00001708 001708 00038c 00  AX  0   0  4
  [11] .text             PROGBITS        00001a94 001a94 0053d4 00  AX  0   0  4
  [12] .ARM.extab        PROGBITS        00006e68 006e68 000078 00   A  0   0  4
  [13] .ARM.exidx        ARM_EXIDX       00006ee0 006ee0 000178 08  AL 11   0  4
  [14] .rodata           PROGBITS        00007058 007058 000038 00  AM  0   0  4
  [15] .fini_array       FINI_ARRAY      00008cf8 007cf8 000008 00  WA  0   0  4
  [16] .data.rel.ro      PROGBITS        00008d00 007d00 00007c 00  WA  0   0  4
  [17] .init_array       INIT_ARRAY      00008d7c 007d7c 000008 00  WA  0   0  4
  [18] .dynamic          DYNAMIC         00008d84 007d84 000128 08  WA  3   0  4
  [19] .got              PROGBITS        00008eac 007eac 000154 00  WA  0   0  4
  [20] .data             PROGBITS        00009000 008000 001450 00  WA  0   0  4
  [21] .bss              NOBITS          0000a450 009450 000004 00  WA  0   0  4
  [22] .comment          PROGBITS        00000000 009450 000065 01  MS  0   0  1
  [23] .note.gnu.gold-ve NOTE            00000000 0094b8 00001c 00      0   0  4
  [24] .ARM.attributes   ARM_ATTRIBUTES  00000000 0094d4 000034 00      0   0  1
  [25] .shstrtab         STRTAB          00000000 009508 000103 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

动态部分的一部分

Dynamic section at offset 0x7d84 contains 32 entries:
  Tag        Type                         Name/Value
 0x00000003 (PLTGOT)                     0x8ecc
 0x00000002 (PLTRELSZ)                   592 (bytes)
 0x00000017 (JMPREL)                     0x14b8
 0x00000014 (PLTREL)                     REL
 0x00000011 (REL)                        0x1340
 0x00000012 (RELSZ)                      376 (bytes)
 0x00000013 (RELENT)                     8 (bytes)
 0x6ffffffa (RELCOUNT)                   41
 0x00000006 (SYMTAB)                     0x158
 0x0000000b (SYMENT)                     16 (bytes)
 0x00000005 (STRTAB)                     0x7f8
 0x0000000a (STRSZ)                      1796 (bytes)
 0x00000004 (HASH)                       0xefc
 ...

尾部.dynamic和头部.got

...
0x8e84:   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   |................|
0x8e94:   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   |................|
0x8ea4:   00 00 00 00 00 00 00 00  00                        |.........       |
; section: .got
0x8eac:   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   |................|
0x8ebc:   00 00 00 00 58 70 00 00  e0 6e 00 00 00 00 00 00   |....Xp...n......|
0x8ecc:   00 00 00 00 00 00 00 00  00 00 00 00 08 17 00 00   |................|
0x8edc:   08 17 00 00 08 17 00 00  08 17 00 00 08 17 00 00   |................|
...

Oracle 的规范中提到:

符号 _GLOBAL_OFFSET_TABLE_ 可用于访问该表。这个符号可以位于 .got 部分的中间,允许负和非负下标进入地址数组。

但GOT进入之前的数据,却悄然与其他数据不同。所有其他数据都指向第一个 PLT 地址(0x1708)。GOT的入口点之前的空间是用来存放外部函数地址的,是和其他的一样,还是有其他的使用方式,或者只是无用的垃圾?


更新

我发现0x8eacto块中有两个数字0x8ecb,即GOT入口点之前的块。0x8ec0,0x7058.rodata的地址而 at 0x8ec4,0x6ee0.ARM.exidx的地址是不是在.gotARM的链式工具和编译器的特定功能中填充这两个地址

我还没有看到任何 ELF 规范提到这一点。

1个回答

没有示例很难说,但是您需要记住动态加载器不关心节。它只使用来自程序头的信息,包括PT_DYNAMIC条目(它可能与.dynamic不同,在这种情况下节的内容被简单地忽略)。

虽然通常 GOT 在.got的开头开始,但它不是加载程序完成其工作的要求。它只使用动态标签和动态重定位信息(DT_JMPRELDT_PLTRELDT_REL,再加上DT_SYMTABDT_STRTABDT_HASH和符号解析)。事实上,您可以完全删除节表,文件仍将运行(但某些工具可能难以解析它)。

可能其他部分与 合并.got,尽管我不知道它可能是什么。