菜单

Mach-O和DYLD缓存支持

相关源文件

目的与范围

本文档涵盖 Ghidra 对加载和分析 Apple 的 Mach-O 可执行文件格式和 DYLD Cache 文件的支持。它描述了 Ghidra 如何处理这些文件格式、将它们映射到内存、解析符号和处理重定位的实现细节。有关这些格式的处理器特定方面的信息,请参阅处理器架构支持

Mach-O 格式概述

Mach-O (Mach Object) 是 macOS、iOS、watchOS 和 tvOS 使用的本地可执行文件格式。它支持单个文件中的多种架构(fat binaries)、各种描述文件结构的加载命令以及复杂的链接和加载机制。

来源

DYLD 缓存格式概述

DYLD 缓存(Dynamic Loader Cache)是 iOS 和 macOS 使用的一种优化技术,它将常用动态库合并到一个文件中,以提高加载时间并减少内存消耗。DYLD 缓存文件包含多个 Mach-O 文件,这些文件及其符号和其他元数据是连续存储的。

来源

Mach-O 加载过程

类层次结构

来源

内存映射

MachoProgramBuilder 处理 Mach-O 文件并为其段和节创建内存块。它根据文件的加载命令处理文件字节到内存地址的映射。

来源

内存映射过程对具有重叠节的段有特殊处理。它首先为段创建块,然后为这些段中的每个节创建块,从而有效地分割段块。

符号处理

Ghidra 处理 Mach-O 文件中的几种类型的符号:

  1. 导出符号 - 由二进制文件导出的符号,从 DYLD 信息命令中的导出字典树或新的 DYLD 导出字典树命令中处理。
  2. 常规符号 - 从符号表命令 (nlist 条目) 中处理。
  3. 存根 - 通常重定向到外部函数的函数存根。
  4. 未定义符号 - 在运行时需要解析的外部符号引用。
  5. 绝对符号 - 具有绝对地址的符号。

来源

链式修复和重定基

现代 Mach-O 文件使用一种名为“链式修复”(chained fixups)的技术,以实现高效的指针重定基和绑定。Ghidra 通过 DyldChainedFixups 类支持此功能。

来源

DYLD 缓存处理

加载 DYLD 缓存

DyldCacheProgramBuilder 扩展了 MachoProgramBuilder 并增加了对 DYLD 缓存文件的特殊处理。

来源

滑块指针修复

DYLD 缓存文件使用一种名为“slide info”(滑块信息)的技术,当缓存加载到与其首选地址不同的地址时,用于调整指针。Ghidra 支持多个版本的滑块信息格式。

来源

处理单独的动态库(Dylib)

DYLD 缓存文件包含多个动态库(dylibs)。Ghidra 单独处理每个动态库,创建相应的内存块、符号和修复。

来源

关键数据结构

Mach-O 头和加载命令

Mach-O 格式使用一个头文件,后跟一系列描述文件结构的加载命令。

加载命令类型目的
LC_SEGMENT/LC_SEGMENT_64SegmentCommand描述 Mach-O 文件中的一个段
LC_SYMTABSymbolTableCommand包含符号表信息
LC_DYSYMTABDynamicSymbolTableCommand包含动态链接信息
LC_LOAD_DYLIBDylibCommand引用一个动态库
LC_DYLD_INFODyldInfoCommand包含 DYLD 特定信息
LC_FUNCTION_STARTSFunctionStartsCommand包含函数起始地址
LC_DYLD_EXPORTS_TRIEDyldExportsTrieCommand包含导出字典树
LC_DYLD_CHAINED_FIXUPSDyldChainedFixupsCommand包含链式修复信息

来源

DYLD 缓存头和组件

DYLD 缓存格式有其自己的头和组件结构。

组件目的
缓存头DyldCacheHeader包含缓存布局信息
映射信息DyldCacheMappingInfo描述内存映射
镜像信息DyldCacheImage描述嵌入式动态库
滑块信息DyldCacheSlideInfoCommon包含指针修复信息
本地符号DyldCacheLocalSymbolsInfo包含本地符号信息

来源

加载器选项

DYLD 缓存加载器提供多个选项来自定义加载过程:

选项默认描述
修复滑块指针true使用滑块信息应用指针修复
标记滑块指针true添加滑块指针的标记
将滑块指针添加到重定位表false将滑块指针修复添加为重定位
处理本地符号true从缓存处理本地符号
标记本地符号 nlistsfalse为本地符号 nlist 结构添加标记
处理动态库内存true为单独的动态库创建内存块
处理动态库符号true处理单独动态库中的符号
处理动态库导出true处理单独动态库中的导出
标记动态库加载命令数据false为动态库加载命令添加标记
处理 libobjctrue对 Objective-C 运行时库的特殊处理

来源

拆分 DYLD 缓存

现代 DYLD 缓存文件可以拆分到多个文件中。SplitDyldCache 类通过查找和加载所有相关的子缓存文件来处理这些多文件缓存。

来源

特殊情况

Ghidra 还支持 PRELINK Mach-O 文件,这些文件主要用于内核扩展(kexts)。MachoPrelinkProgramBuilder 处理这些文件,其中包含多个嵌入式 Mach-O 文件。

来源

从 iOS 应用包中提取 Mach-O 文件

ExtractedMacho 类有助于提取和处理嵌入在 iOS 应用程序包中的 Mach-O 文件。它处理必要的调整,使提取的文件可由 Ghidra 加载。

来源

结论

Ghidra 为 Apple 的 Mach-O 可执行文件格式和 DYLD 缓存文件提供了全面的支持。它能有效地加载、分析和逆向工程这些格式,处理它们复杂的结构、符号表和重定位机制。MachoProgramBuilderDyldCacheProgramBuilder 类,以及各种格式特定的类,共同构成了处理这些文件格式的强大框架。