简介
Mach-O 组件的主要作用是加载二进制文件,将 mach-o 文件内容以 mmap 的方式加载到内存中,并读取 mach-o headers 来获取 text 段, 符号表, objc 等关键段的地址。
使用方法
加载一个包含 ARM64 架构的 Mach-O
#include <iostream>#include <iblessing-core/v2/mach-o/mach-o.hpp>using namespace std;using namespace iblessing;int main(int argc, const char * argv[]) {string filePath = "/Users/soulghost/Desktop/research/ib-sample/ib-sample/iblessing-sample.benchmark";shared_ptr<MachO> macho = MachO::createFromFile(filePath);assert(macho->loadSync() == IB_SUCCESS);return 0;}
ScannerContext
在调用完 loadSync 并返回 IB_SUCCESS 后,MachO 模块会构建起一个与二进制信息有关的 context,可通过 macho->context 访问,你可以打开 ScannerContext.hpp 来查看:
class ScannerContext {
public:
// ...
// fileMemory 是指 mach-o 载入进程后的 fileData 信息
std::shared_ptr<VirtualMemory> fileMemory;
// 基于 unicorn 的虚拟内存的挂载点,在 mach-o 初始化时还不可用
std::shared_ptr<VirtualMemoryV2> readonlyMemory;
// mach-o 的 string table,在这里提供了基于 index 访问的 API
std::shared_ptr<StringTable> strtab;
// mach-o 的 symbol table,同时包含了 dynamic symbol table,通过名称、地址等倒排索引
// 提供查询能力
std::shared_ptr<SymbolTable> symtab;
// objc runtime 模块的挂载点,** 在 mach-o 初始化时还不可用 **
std::shared_ptr<ObjcRuntime> objcRuntime;
// ...
};
FileMemory (VirtualMemory)
macho->context->fileMemory (VirtualMemory) 是 iblessing 早期的模块,它最早用于直接在当前进程内模拟 mach-o 的内存,这并不安全,因此大部分 API 已被废弃(目前模拟 mach-o 内存是直接使用 unicorn 提供的虚拟地址空间),因此请不要使用 VirtualMemory 模块的读写 API。目前它仅仅用来记录 mach-o 相关的段信息:
class VirtualMemory {
public:
// ...
uint64_t spUpperBound;
uint64_t spLowerBound;
uint64_t heapCursor;
uint64_t heapCopyCursor;
// mach-o 文件的 data,这里是直接将整个文件 mmap 进来的,mappedFile 永远指向文件起始
uint8_t *mappedFile;
// mach-o 文件的 size
uint64_t mappedSize;
// vmaddr base, 文件载入虚拟内存的起点,这里用的是 __text 段的 vmaddr - fileoff 得到的
// 一般是 0x100000000,即从 PAGE_ZERO 之后开始加载
uint64_t vmaddr_base;
// symtab、dlsymtab、strtab's vmaddr base on LINKEDIT's vmaddr
uint64_t linkedit_base;
// __bss section
uint64_t vmaddr_bss_start;
uint64_t vmaddr_bss_end;
// objc classlist & categorylist 地址
uint64_t objc_classlist_addr;
uint64_t objc_classlist_size;
uint64_t objc_catlist_addr;
uint64_t objc_catlist_size;
// 所有段的信息,这里已经按照 offset 正序排列
std::vector<struct ib_segment_command_64 *> segmentHeaders;
// dyld_info load_command
ib_dyld_info_command *dyldinfo;
// __TEXT,__text load_command
struct ib_segment_command_64 *textSeg;
struct ib_section_64 *textSect;
// ...
};
目前暴露的 API 是基于 iblessing 目前的需求,并未全面透出,如果有需求可以通过 GitHub 或 README 中的联系方式反馈给作者。
