本文档涵盖 Ghidra 对加载和分析 Apple 的 Mach-O 可执行文件格式和 DYLD Cache 文件的支持。它描述了 Ghidra 如何处理这些文件格式、将它们映射到内存、解析符号和处理重定位的实现细节。有关这些格式的处理器特定方面的信息,请参阅处理器架构支持。
Mach-O (Mach Object) 是 macOS、iOS、watchOS 和 tvOS 使用的本地可执行文件格式。它支持单个文件中的多种架构(fat binaries)、各种描述文件结构的加载命令以及复杂的链接和加载机制。
来源
DYLD 缓存(Dynamic Loader Cache)是 iOS 和 macOS 使用的一种优化技术,它将常用动态库合并到一个文件中,以提高加载时间并减少内存消耗。DYLD 缓存文件包含多个 Mach-O 文件,这些文件及其符号和其他元数据是连续存储的。
来源
来源
MachoProgramBuilder 处理 Mach-O 文件并为其段和节创建内存块。它根据文件的加载命令处理文件字节到内存地址的映射。
来源
内存映射过程对具有重叠节的段有特殊处理。它首先为段创建块,然后为这些段中的每个节创建块,从而有效地分割段块。
Ghidra 处理 Mach-O 文件中的几种类型的符号:
来源
现代 Mach-O 文件使用一种名为“链式修复”(chained fixups)的技术,以实现高效的指针重定基和绑定。Ghidra 通过 DyldChainedFixups 类支持此功能。
来源
DyldCacheProgramBuilder 扩展了 MachoProgramBuilder 并增加了对 DYLD 缓存文件的特殊处理。
来源
DYLD 缓存文件使用一种名为“slide info”(滑块信息)的技术,当缓存加载到与其首选地址不同的地址时,用于调整指针。Ghidra 支持多个版本的滑块信息格式。
来源
DYLD 缓存文件包含多个动态库(dylibs)。Ghidra 单独处理每个动态库,创建相应的内存块、符号和修复。
来源
Mach-O 格式使用一个头文件,后跟一系列描述文件结构的加载命令。
| 加载命令类型 | 类 | 目的 |
|---|---|---|
| LC_SEGMENT/LC_SEGMENT_64 | SegmentCommand | 描述 Mach-O 文件中的一个段 |
| LC_SYMTAB | SymbolTableCommand | 包含符号表信息 |
| LC_DYSYMTAB | DynamicSymbolTableCommand | 包含动态链接信息 |
| LC_LOAD_DYLIB | DylibCommand | 引用一个动态库 |
| LC_DYLD_INFO | DyldInfoCommand | 包含 DYLD 特定信息 |
| LC_FUNCTION_STARTS | FunctionStartsCommand | 包含函数起始地址 |
| LC_DYLD_EXPORTS_TRIE | DyldExportsTrieCommand | 包含导出字典树 |
| LC_DYLD_CHAINED_FIXUPS | DyldChainedFixupsCommand | 包含链式修复信息 |
来源
DYLD 缓存格式有其自己的头和组件结构。
| 组件 | 类 | 目的 |
|---|---|---|
| 缓存头 | DyldCacheHeader | 包含缓存布局信息 |
| 映射信息 | DyldCacheMappingInfo | 描述内存映射 |
| 镜像信息 | DyldCacheImage | 描述嵌入式动态库 |
| 滑块信息 | DyldCacheSlideInfoCommon | 包含指针修复信息 |
| 本地符号 | DyldCacheLocalSymbolsInfo | 包含本地符号信息 |
来源
DYLD 缓存加载器提供多个选项来自定义加载过程:
| 选项 | 默认 | 描述 |
|---|---|---|
| 修复滑块指针 | true | 使用滑块信息应用指针修复 |
| 标记滑块指针 | true | 添加滑块指针的标记 |
| 将滑块指针添加到重定位表 | false | 将滑块指针修复添加为重定位 |
| 处理本地符号 | true | 从缓存处理本地符号 |
| 标记本地符号 nlists | false | 为本地符号 nlist 结构添加标记 |
| 处理动态库内存 | true | 为单独的动态库创建内存块 |
| 处理动态库符号 | true | 处理单独动态库中的符号 |
| 处理动态库导出 | true | 处理单独动态库中的导出 |
| 标记动态库加载命令数据 | false | 为动态库加载命令添加标记 |
| 处理 libobjc | true | 对 Objective-C 运行时库的特殊处理 |
来源
现代 DYLD 缓存文件可以拆分到多个文件中。SplitDyldCache 类通过查找和加载所有相关的子缓存文件来处理这些多文件缓存。
来源
Ghidra 还支持 PRELINK Mach-O 文件,这些文件主要用于内核扩展(kexts)。MachoPrelinkProgramBuilder 处理这些文件,其中包含多个嵌入式 Mach-O 文件。
来源
ExtractedMacho 类有助于提取和处理嵌入在 iOS 应用程序包中的 Mach-O 文件。它处理必要的调整,使提取的文件可由 Ghidra 加载。
来源
Ghidra 为 Apple 的 Mach-O 可执行文件格式和 DYLD 缓存文件提供了全面的支持。它能有效地加载、分析和逆向工程这些格式,处理它们复杂的结构、符号表和重定位机制。MachoProgramBuilder 和 DyldCacheProgramBuilder 类,以及各种格式特定的类,共同构成了处理这些文件格式的强大框架。