菜单

ELF格式支持

相关源文件

本文档详细介绍了 Ghidra 如何处理可执行与可链接格式 (ELF),涵盖了加载过程、分析能力和定制机制。有关 Ghidra 支持的其他二进制格式的信息,请参阅概述中的 二进制格式支持

Ghidra ELF 支持概述

Ghidra 为解析、加载和分析 ELF(可执行与可链接格式)文件提供了全面的支持,ELF 文件通常在 Unix 和类 Unix 系统(如 Linux、BSD 和其他平台)中使用。Ghidra 中的 ELF 支持包括处理:

  • 32 位和 64 位 ELF 文件
  • 重定位文件、可执行文件和共享对象文件类型
  • 通过扩展机制支持多种处理器架构
  • 段和节
  • 符号表和字符串表
  • 重定位(包括 Android 和 RELR 等专用类型)
  • 动态链接信息
  • PLT/GOT(过程链接表/全局偏移表)结构
  • 线程局部存储 (TLS)
  • 压缩节

来源:Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java32-36 Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java64-202

ELF 文件结构和 Ghidra 表示

ELF 结构概述

ELF 格式包括 ELF 头、程序头(段)、节头和各种数据节。Ghidra 提供了专门的类来表示和处理这些组件。

来源:Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java35-91 Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeader.java32-73 Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfProgramHeader.java31-39

Ghidra 中的关键 ELF 组件

组件描述主要类
ELF 头包含有关 ELF 文件的元数据,包括架构、入口点以及指向其他结构的偏移量ElfHeader
程序头描述执行所需的段ElfProgramHeader
章节标题更详细地描述节ElfSectionHeader
符号表包含程序中定义或引用的符号ElfSymbolTableElfSymbol
字符串表存储其他结构引用的字符串ElfStringTable
重定位表包含用于地址修正的重定位条目ElfRelocationTableElfRelocation
动态表包含动态链接信息ElfDynamicTableElfDynamic

来源:Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java78-92 Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbolTable.java30-44 Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfRelocationTable.java29-52

ELF 加载过程

ELF 加载过程在 Ghidra 中主要由 ElfProgramBuilder 类处理,该类执行一个系统化的过程,将 ELF 文件加载到 Ghidra 程序中。加载过程遵循以下关键步骤:

  1. 解析 ELF 头以获取基本文件信息
  2. 从 ELF 元数据中**添加程序属性**
  3. 为加载程序**设置映像基址**
  4. 为 ELF 文件数据**创建文件字节**
  5. 调整段和节的文件分配
  6. 处理程序头和节头
  7. 解析内存段并创建程序内存块
  8. 标记 ELF 头、程序头和节头
  9. 处理字符串表和符号表
  10. 处理特定于处理器的扩展
  11. 处理重定位以修正地址
  12. 处理入口点以创建函数
  13. 处理导入(来自动态库)
  14. 处理 PLT/GOT 以进行动态链接
  15. 处理 GNU 特定的节和扩展
  16. 调整只读内存区域
  17. 设置编译器信息

来源:Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java114-198

内存加载与解析

ELF 加载过程中的一项基本任务是解析内存段并将内存块创建到 Ghidra 程序中。此过程处理程序头(段)和节头之间可能存在的重叠和冲突。

内存加载过程

  1. 从程序头和节头构建内存段列表
  2. 解析段之间的冲突和重叠
  3. 在 Ghidra 程序中创建内存块
  4. 为每个块设置适当的权限(读、写、执行)

Ghidra 将 ELF 文件中标记为可分配的节视为应加载到内存中的节。不可分配的节(如调试信息)可以可选地作为“OTHER”内存块导入。

来源:Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/MemorySectionResolver.java33-452 Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java214-322

重定位处理

重定位是 ELF 文件的重要组成部分,特别是在共享库和位置无关代码中。Ghidra 处理各种类型的重定位:

重定位类型描述
标准 REL不带显式附加项的重定位
标准 RELA带显式附加项的重定位
PLT 重定位过程链接表条目的重定位
Android 重定位Android 二进制文件中使用的专用格式
RELR 重定位压缩格式的相对重定位

重定位过程包括:

  1. 在 ELF 文件中定位重定位表
  2. 处理每个重定位条目
  3. 在需要时提取符号信息
  4. 应用适当的重定位操作
  5. 将重定位记录在程序的重定位表中

Ghidra 使用一个可扩展的框架来处理特定于处理器的重定位类型,其基本功能由 ElfRelocationHandler 类提供,并由特定于处理器的处理器进行扩展。

来源:Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfRelocationTable.java29-90 Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfRelocation.java28-105 Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java862-1076

符号处理

ELF 文件中的符号提供了关于函数、变量和其他程序元素的信息。Ghidra 处理符号以创建丰富的程序表示。

Ghidra 中的符号处理

  1. 解析 ELF 文件中的静态和动态符号表
  2. 根据符号的类型和绑定处理每个符号
  3. 创建适当的程序元素(函数、标签、数据、外部引用)
  4. 处理特殊符号,如入口点和 TLS(线程局部存储)符号

Ghidra 区分不同的符号类型(函数、对象、节、文件)和绑定(局部、全局、弱),以正确表示程序的结构。

来源:Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbolTable.java Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbol.java48-112 Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java164-166

动态链接和 GOT/PLT 处理

使用动态链接的 ELF 文件依赖于全局偏移表 (GOT) 和过程链接表 (PLT) 等结构。Ghidra 处理这些结构以准确表示程序的动态链接行为。

Ghidra 中的 GOT/PLT 处理

  1. 定位程序中的 GOT 和 PLT 段
  2. 处理 GOT 条目,将其标记为指针
  3. 处理 PLT 条目,创建函数跳转
  4. 将外部引用链接到其对应的 PLT 条目
  5. 反汇编 PLT 段以显示函数跳转

此处理由 ElfDefaultGotPltMarkup 类处理标准情况,特定于处理器的扩展为不同架构提供定制行为。

来源:Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDefaultGotPltMarkup.java40-95 Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfDefaultGotPltMarkup.java358-472

特定于处理器的扩展

Ghidra 使用扩展机制来处理 ELF 文件的特定于处理器方面。这允许为不同架构定制行为,同时保持整体框架的一致性。

扩展机制基于 ElfLoadAdapter 类,该类为 ELF 处理提供了默认实现。特定于处理器的扩展,如 MIPS_ElfExtension,会覆盖这些方法以提供定制行为。

  1. 类型扩展:添加特定于处理器的动态类型、程序头类型和节头类型
  2. 地址映射:确定段和节的首选地址空间
  3. 函数创建:调整函数地址和应用上下文
  4. 符号处理:根据特定于处理器的规则计算符号地址
  5. GOT/PLT 处理:对全局偏移表和过程链接表进行定制处理
  6. 重定位处理:特定于处理器的重定位类型和处理

Ghidra 包含针对多种处理器的扩展,例如 MIPS、PowerPC、ARM 和 x86。

来源:Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/extend/ElfLoadAdapter.java39-228 Ghidra/Processors/MIPS/src/main/java/ghidra/app/util/bin/format/elf/extend/MIPS_ElfExtension.java39-319 Ghidra/Processors/PowerPC/src/main/java/ghidra/app/util/bin/format/elf/extend/PowerPC64_ElfExtension.java

ELF加载器选项

Ghidra 为自定义 ELF 加载过程提供了一些选项

选项描述默认值
执行符号重定位是否应用重定位true
应用未定义符号数据是否为未定义符号创建数据true
镜像基址程序的基址因架构而异
数据镜像基址(对于 Harvard 架构) 数据的基址与架构相关
导入未加载数据是否将未加载的节导入为 OTHER 块true
最大零填充节丢弃大小要丢弃的最大零填充节的大小0xff

这些选项可以在导入过程中进行配置,以控制 ELF 文件加载和处理的各个方面。

来源:Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfLoaderOptionsFactory.java34-60

支持的特殊 ELF 功能

压缩节

Ghidra 支持 ELF 文件中的压缩节,它们使用 SHF_COMPRESSED 标志。遇到压缩节时

  1. 从节中读取压缩头
  2. 识别压缩类型(目前仅支持 ZLIB)
  3. 在加载过程中解压压缩数据
  4. 解压后的节被视为普通节

来源:Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeader.java133-163

Android 特定的重定位

Ghidra 支持 Android 二进制文件中使用的专用重定位格式

  1. SHT_ANDROID_RELSHT_ANDROID_RELA:Android 特定的重定位节类型
  2. SHT_ANDROID_RELR:Android 对 RELR 节的实验性支持
  3. DT_ANDROID_RELDT_ANDROID_RELADT_ANDROID_RELR:相应的动态表条目

Android 重定位使用分组压缩格式来减小文件大小

  • 重定位组在一起存储
  • 重定位信息可能在多个条目之间共享
  • 增量可能不是绝对值

来源:Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeaderConstants.java95-101 Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfRelocationTable.java176-261

线程局部存储 (TLS)

Ghidra 识别并处理 ELF 文件中的线程局部存储(TLS)符号

  1. TLS 节(.tdata.tbss)已被识别
  2. TLS 符号(类型 STT_TLS)已被处理
  3. TLS 特定的重定位已被处理

但是,由于其复杂性,TLS 重定位目前被标记为不受支持。

来源:Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeaderConstants.java47-48 Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSymbol.java79 Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/relocation/ElfRelocationContext.java113-117

结论

Ghidra 为跨各种架构的 ELF 文件加载和分析提供了全面的支持。其可扩展的设计允许针对特定处理器进行定制,同时保持整体框架的一致性。主要功能包括

  • 支持所有标准的 ELF 组件(头、段、节、符号、重定位)
  • 面向不同架构的特定处理器扩展
  • 特殊格式支持(压缩节、Android 重定位、RELR)
  • 可配置的加载选项
  • 对 ELF 结构的详细标记

此支持使 Ghidra 能够准确地表示和分析各种平台和架构上的广泛 ELF 二进制文件。

来源:Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfHeader.java Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java