简介
Mach-O 模块仅仅管理了文件级的加载,此时只是将 Mach-O 文件的内容原封不动的加载到了当前进程的内存中,并将关键信息记录在 macho->fileMemory,Memory 模块则会完成将 Mach-O 加载到基于 unicorn 的虚拟地址空间的过程。此外针对静态库还会进行 relocation fix。
使用方法
Memory 的初始化依赖于 mach-o 模块,因此你需要先创建 mach-o 模块并完成 load,随后再加载内存模块。
#include <iostream>#include <iblessing-core/v2/mach-o/mach-o.hpp>#include <iblessing-core/v2/memory/memory.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);shared_ptr<Memory> memory = Memory::createFromMachO(macho);assert(memory->loadSync() == IB_SUCCESS);return 0;}
Memory 模块
memory.hpp 中展示了 memory 模块的核心功能,其中 fileMemory 来自 mach-o,virtualMemory 是基于 unicorn 的虚拟地址空间(它安全的模拟了 mach-o 实际的虚拟地址空间):
class Memory {public:// 这个方法用于将已加载的虚拟地址空间拷贝到其他 unicorn 实例,这非常使用,因为你往往会// 创建自己的 unicorn 实例来进行扫描ib_return_t copyToUCEngine(uc_engine *uc);// fileMemory 来自于 mach-o 模块std::shared_ptr<VirtualMemory> fileMemory;// mach-o 的虚拟地址空间,详见下面的解释std::shared_ptr<VirtualMemoryV2> virtualMemory;};
memory->virtualMemory (VirtualMemoryV2) 是基于 unicorn 划定的一个 12GB 虚拟地址空间 (4GB PAGEZERO + 8GB Heap/Stack),也就是从 0x100000000 ~ 0x300000000 的区域,根据 load commands 逐段映射进 unicorn 虚拟地址空间。
一般而言,用户都会新建一个 unicorn 实例进行扫描,因此需要将 Memory 已加载的内容同步到新的 uc 实例,在这种情况下,你可以调用 copyToUCEngine 来同步 Memory 模块加载的虚拟地址空间,但需要注意的是,这里并不是真正的完整内存拷贝,而是按照同样的规则将 mach-o 模块进行加载和 relocation,因此如果你修改了 Memory 模块的内容,他们是不会被同步的,所以要么使用 Memory 模块提供的 unicorn 实例(通过 virtualMemory->getEngine()),要么就在修改内存前提早创建好 uc 实例,通过 copyToUCEngine 拷贝初始内容,并且在接下来只修改你创建的实例 。
注意事项
Memory 模块主要扮演的角色是 Mach-O 内存初始化和查询者,如果你需要查询 Mach-O 的文件信息,可以通过 memory->fileMemory 或 macho->context->fileMemory,如果你想读写 Mach-O 虚拟地址空间,请使用 memory->virtualMemory 提供的 read / write API。
