p-x9/MachOKit
GitHub: p-x9/MachOKit
一个用 Swift 编写的 Mach-O 文件解析库,支持从文件和内存中提取二进制结构信息并解析 dyld 共享缓存。
Stars: 224 | Forks: 21
# MachOKit
用于解析 MachO 文件以获取各种信息的库。
除了读取文件外,还支持通过 `_dyld_get_image_header` 解析内存中的镜像。
[](https://github.com/p-x9/MachOKit/issues)
[](https://github.com/p-x9/MachOKit/network/members)
[](https://github.com/p-x9/MachOKit/stargazers)
[](https://github.com/p-x9/MachOKit/)
## 功能特性
- 解析 load commands
- 符号列表
- 获取所有 cstrings
- rebase 操作
- binding 操作
- 导出 trie
- ...
## 用法
### 从内存加载
要从内存中读取,请使用 `MachOImage` 结构体。
可以使用通过 `_dyld_get_image_header` 获取的 Mach-O Header 指针来进行初始化。
```
guard let mh = _dyld_get_image_header(0) else { return }
let machO = MachOImage(ptr: mh)
```
或者,也可以使用名称进行初始化。
```
// /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation
guard let machO = MachOImage(name: "Foundation") else { return }
```
### 从文件加载
要从文件中读取,请使用 `MachOFile` 结构体。
从文件读取的操作如下。
由于存在 Fat 文件和单一 MachO 文件的情况,因此需要进行条件分支处理。
```
let path = "Path to MachO file"
let url = URL(string: path)
let file = try MachOKit.loadFromFile(url: url)
switch file {
case .machO(let machOFile): // single MachO file
print(machOFile)
case .fat(let fatFile): // Fat file
let machOFiles = try fatFile.machOFiles()
print(machOFiles)
}
```
### 主要属性和方法
`MachOImage` 和 `MachOFile` 都可以使用基本相同的属性和方法。
可用的方法在以下文件中定义为 `MachORepresentable` 协议。
[MachORepresentable](./Sources/MachOKit/Protocol/MachORepresentable.swift)
### Dyld 缓存
也支持加载 `dyld_shared_cache`。
可用的方法在以下文件中定义为 `DyldCacheRepresentable` 协议。
[DyldCacheRepresentable](./Sources/MachOKit/Protocol/DyldCacheRepresentable.swift)
#### Dyld 缓存 (文件)
```
let path = "/System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/dyld_shared_cache_arm64e"
let url = URL(fileURLWithPath: path)
let cache = try! DyldCache(url: url)
```
还可以提取包含在 `dyld_shared_cache` 中的 machO 信息。
提取出的 machO 类型为 `MachOFile`。
与从单一 MachO 文件读取一样,可以进行各种分析。
```
let machOs = cache.machOFiles()
for machO in machOs {
print(
String(machO.headerStartOffsetInCache, radix: 16),
machO.imagePath,
machO.header.ncmds
)
}
// 5c000 /usr/lib/libobjc.A.dylib 22
// 98000 /usr/lib/dyld 15
// 131000 /usr/lib/system/libsystem_blocks.dylib 24
// ...
```
#### 完整 Dyld 缓存 (文件)
除了 `DyldCache` 之外,还可以使用 `FullDyldCache` 将多个 dyld 缓存文件(主缓存和子缓存)作为单个统一的缓存进行处理。
```
let path = "/System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/dyld_shared_cache_arm64e"
let url = URL(fileURLWithPath: path)
let fullCache = try! FullDyldCache(url: url)
// Access all Mach-O files across main and subcaches
let machOs = fullCache.machOFiles()
for machO in machOs {
print(
String(machO.headerStartOffsetInCache, radix: 16),
machO.imagePath,
machO.header.ncmds
)
}
```
`FullDyldCache` 类型提供了诸如 `mainCache`、`subCaches`、`allCaches` 和 `urls` 等属性,用于访问各个组件的缓存文件。
#### Dyld 缓存 (内存中)
在 Apple 平台上,dyld 缓存被部署在内存中。
```
var size = 0
guard let ptr = _dyld_get_shared_cache_range(&size) else {
return
}
let cache = try! DyldCacheLoaded(ptr: ptr)
```
也可以提取包含在 `dyld_shared_cache` 中的 machO 信息。
提取出的 machO 类型为 `MachOImage`。
与从单一 MachO 镜像读取一样,可以进行各种分析。
```
let machOs = cache.machOImages()
for machO in machOs {
print(
String(Int(bitPattern: machO.ptr), radix: 16),
machO.path!,
machO.header.ncmds
)
}
// 193438000 /usr/lib/libobjc.A.dylib 24
// 193489000 /usr/lib/dyld 15
// 193513000 /usr/lib/system/libsystem_blocks.dylib 24
// ...
```
### 示例代码
有各种不同的用法,但大多数都在 Test 目录中展示了打印输出的基本示例。
#### 从内存加载
以下文件包含示例代码。
[MachOPrintTests](./Tests/MachOKitTests/MachOPrintTests.swift)
#### 从文件加载
以下文件包含示例代码。
[MachOFilePrintTests](./Tests/MachOKitTests/MachOFilePrintTests.swift)
#### Dyld 缓存 (文件)
以下文件包含示例代码。
[DyldCachePrintTests](./Tests/MachOKitTests/DyldCachePrintTests.swift)
#### Dyld 缓存 (内存中)
以下文件包含示例代码。
[DyldCacheLoadedPrintTests](./Tests/MachOKitTests/DyldCacheLoadedPrintTests.swift)
## 相关项目
- [MachOKitSPM](https://github.com/p-x9/MachOKit-SPM)
MachOKit 的预构建版本
- [SwiftHook](https://github.com/p-x9/swift-hook)
⚓️ 一个用于 hook swift 方法和函数的 Swift 库。
- [FishHook](https://github.com/p-x9/swift-fishhook)
使用 MachOKit 以 Swift 对 [facebook/fishhook](https://github.com/facebook/fishhook) 进行重新实现
- [AntiFishHook](https://github.com/p-x9/swift-anti-fishhook)
一个用于停用 fishhook 的 Swift 库。
### 其他二进制类型
- [ELFKit](https://github.com/p-x9/ELFKit)
Elf 格式
## 许可证
MachOKit 在 MIT 许可证下发布。详情请见 [LICENSE](./LICENSE)
标签:dyld, Fat文件, iOS开发, Load Commands, Mach-O, macOS开发, Swift, 二进制解析, 云安全监控, 云资产清单, 内存解析, 动态库, 字符串提取, 导出符号, 文件解析, 符号表, 绑定操作, 逆向工程, 重定基操作, 静态分析