本文档详细介绍了 Ghidra 如何处理可执行与可链接格式 (ELF),涵盖了加载过程、分析能力和定制机制。有关 Ghidra 支持的其他二进制格式的信息,请参阅概述中的 二进制格式支持。
Ghidra 为解析、加载和分析 ELF(可执行与可链接格式)文件提供了全面的支持,ELF 文件通常在 Unix 和类 Unix 系统(如 Linux、BSD 和其他平台)中使用。Ghidra 中的 ELF 支持包括处理:
来源: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 格式包括 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
| 组件 | 描述 | 主要类 |
|---|---|---|
| ELF 头 | 包含有关 ELF 文件的元数据,包括架构、入口点以及指向其他结构的偏移量 | ElfHeader |
| 程序头 | 描述执行所需的段 | ElfProgramHeader |
| 章节标题 | 更详细地描述节 | ElfSectionHeader |
| 符号表 | 包含程序中定义或引用的符号 | ElfSymbolTable、ElfSymbol |
| 字符串表 | 存储其他结构引用的字符串 | ElfStringTable |
| 重定位表 | 包含用于地址修正的重定位条目 | ElfRelocationTable、ElfRelocation |
| 动态表 | 包含动态链接信息 | ElfDynamicTable、ElfDynamic |
来源: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 加载过程在 Ghidra 中主要由 ElfProgramBuilder 类处理,该类执行一个系统化的过程,将 ELF 文件加载到 Ghidra 程序中。加载过程遵循以下关键步骤:
来源:Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfProgramBuilder.java114-198
ELF 加载过程中的一项基本任务是解析内存段并将内存块创建到 Ghidra 程序中。此过程处理程序头(段)和节头之间可能存在的重叠和冲突。
内存加载过程
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 重定位 | 压缩格式的相对重定位 |
重定位过程包括:
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 中的符号处理
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
使用动态链接的 ELF 文件依赖于全局偏移表 (GOT) 和过程链接表 (PLT) 等结构。Ghidra 处理这些结构以准确表示程序的动态链接行为。
Ghidra 中的 GOT/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,会覆盖这些方法以提供定制行为。
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
Ghidra 为自定义 ELF 加载过程提供了一些选项
| 选项 | 描述 | 默认值 |
|---|---|---|
| 执行符号重定位 | 是否应用重定位 | true |
| 应用未定义符号数据 | 是否为未定义符号创建数据 | true |
| 镜像基址 | 程序的基址 | 因架构而异 |
| 数据镜像基址 | (对于 Harvard 架构) 数据的基址 | 与架构相关 |
| 导入未加载数据 | 是否将未加载的节导入为 OTHER 块 | true |
| 最大零填充节丢弃大小 | 要丢弃的最大零填充节的大小 | 0xff |
这些选项可以在导入过程中进行配置,以控制 ELF 文件加载和处理的各个方面。
来源:Ghidra/Features/Base/src/main/java/ghidra/app/util/opinion/ElfLoaderOptionsFactory.java34-60
Ghidra 支持 ELF 文件中的压缩节,它们使用 SHF_COMPRESSED 标志。遇到压缩节时
来源:Ghidra/Features/Base/src/main/java/ghidra/app/util/bin/format/elf/ElfSectionHeader.java133-163
Ghidra 支持 Android 二进制文件中使用的专用重定位格式
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
Ghidra 识别并处理 ELF 文件中的线程局部存储(TLS)符号
.tdata、.tbss)已被识别STT_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 文件加载和分析提供了全面的支持。其可扩展的设计允许针对特定处理器进行定制,同时保持整体框架的一致性。主要功能包括
此支持使 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