解析 (ELF) 节名称的反汇编程序

逆向工程 拆卸 linux 小精灵
2021-07-02 03:15:03

我正在使用 linux 可执行文件,只是想知道如何在反汇编 ELF 时将节名称解析为地址。

例如从 objdump 中获取一些随机反汇编输出,

  4002b5:       00 00                   add    %al,(%rax)
  4002b7:       00 67 55                add    %ah,0x55(%rdi)
  4002ba:       61                      (bad)  
  4002bb:       10                      .byte 0x10

Disassembly of section .dynsym:

00000000004002c0 <.dynsym>:
        ...
  4002d8:       9b                      fwait
  4002d9:       00 00                   add    %al,(%rax)
  4002db:       00 12                   add    %dl,(%rdx)
        ...
  4002ed:       00 00                   add    %al,(%rax)
  4002ef:       00 32                   add    %dh,(%rdx)
  4002f1:       00 00                   add    %al,(%rax)
  4002f3:       00 12                   add    %dl,(%rdx)
        ...
  400305:       00 00                   add    %al,(%rax)
  400307:       00 17                   add    %dl,(%rdi)

如果从启发式的角度来看,它如何检测到该地址处的部分称为 dynsm?.text、.bss 甚至 objdump 列出的函数(例如“main”)也是如此。

如果我自己编写一个反汇编工具 + 可执行分析器,我将如何重现这个?

谢谢

1个回答

请注意,在问题中的示例中,数据被反汇编为代码。.dynsym部分包含动态链接符号表,不包含代码


  • 在该段的段头给出了诸如段的第一个字节的名称和虚拟地址之类的信息

  • 节头是存储在ELF 二进制文件节头表中的结构

在这种情况下objdump打印虚拟地址00000000004002c0和名称,.dynsym因为这是存储在该特定部分的部分标题中的信息(从技术上讲,部分名称是存储在部分标题字符串表中的字符串.shstrtab,但在这种情况下这并不重要)。如果此节没有节头,或者如果二进制文件中没有节头表,objdump将无法输出此信息。

除非二进制文件中不存在节头表,否则不需要试探法。这是不寻常的,但既然已经观察到在某些Linux的ELF二进制文件(病毒)的情况下,为了挫败分析gdbobjdump和其他二进制文件基于描述符的公用事业(谢谢你,伊戈尔Skochinsky的校正)依赖于信息的节头表来解析二进制文件。

相关文档可以在System V ABI(通用)中找到,从第 4 章“对象文件”(第 44 页)开始,以及ELF手册页

节头表包含了描述文件的部分信息。每个部分在表中都有一个条目;每个条目都提供诸如节名称、节大小等信息。

进一步来说:

目标文件的节头表可以让我们定位文件的所有节。节头表是一个Elf32_ShdrElf64_Shdr结构的数组节头表索引是该数组的下标。ELF 头的e_shoff成员给出了从文件开头到节头表的字节偏移量;e_shnum告诉节头表包含多少条目;e_shentsize给出每个条目的字节大小。

此外,

节包含目标文件中的所有信息,除了 ELF 头、程序头表和节头表。此外,目标文件的部分满足几个条件。

  • 目标文件中的每一节都只有一个节头来描述它。可能存在没有节的节标题。

  • 每个部分在文件中占据一个连续的(可能是空的)字节序列。

  • 文件中的部分不能重叠。文件中的任何字节都不会驻留在多个节中。

  • 目标文件可能有非活动空间。各种标题和部分可能不会“覆盖”目标文件中的每个字节。未指定非活动数据的内容。

以下是定位包含在 ELF 二进制文件的各个部分标题中的信息所涉及的内容的高级概述。引用的文档适用于 ELF32 二进制文件,但该过程与 ELF64 二进制文件相同。

节头表的位置在ELF头中给出:

ELF 标头位置

ELF 头是一个结构体,节头表的偏移量存储在一个名为 的成员中e_shoff

ELF 头结构和成员

e_shoff

$ readelf -h /bin/ls
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:               0x404890
  Start of program headers:          64 (bytes into file)
  Start of section headers:          108288 (bytes into file)   <---------- e_shoff
  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:         28
  Section header string table index: 27

节头表通常位于所有节之后的二进制文件的末尾:

二进制中的节头表位置

正如文档中所述和前面提到的,每个部分在部分标题表中都有一个条目。每个条目都是一个结构,其中包含有关该部分的信息,包括其名称和当二进制文件映射到内存时的虚拟地址。节的名称存储在名为 的结构成员中sh_name,地址信息存储在名为 的结构成员中sh_addr

节头结构

sh_name

sh_地址

检索此信息只是在给定二进制文件中正确解析这些结构的问题。

更多信息可以在这里找到: