进程里直接跑机器码:轻量 x86-64 仿真库 Cpueaxh 的 Guest/Host 双模式拆解

说明:微信源页触发「环境异常 / 验证码」,无法直读原文。本文按题意(开源 x86-64 CPU 仿真库 Cpueaxh),并基于官方仓库
saileaxh/cpueaxh的中英文 README、公开 API 头文件与示例说明做工程向改写;版本口径以撰写时 README 为准。本篇只讨论合法研究/插桩场景下的仿真执行与宿主对接,不涉及对抗检测、绕过安全产品或恶意利用。
做二进制分析、沙箱原型或主机侧插桩时,很多人第一反应是上 Unicorn:自己 mem_map 一块客户机地址空间,再 emu_start。这很稳,但有一类需求它不够顺手——你已经在本进程里,目标函数就躺在真实虚拟地址上,只想「用模拟 CPU 跑一段,而不是再拷一份镜像」。
saileaxh/cpueaxh(MIT)把这件事做成了产品点:轻量、无第三方依赖的 x86-64 仿真库,API 尽量贴近 Unicorn,同时提供:
- Guest 模式:自管理内存,用法接近传统模拟器;
- Host 模式:直接对着当前进程真实地址空间模拟执行,并支持内存补丁叠层(模拟 CPU 看到的字节可以和底层真实内存不一致)。
同一套核心还能经薄平台层编进用户态静态库或内核驱动侧(kcpueaxh + KMDF 示例)。项目仍在积极开发,不是完整 Unicorn 替代品,也不是系统级虚拟化;但已经覆盖常用整数/控制流/字符串指令,以及 SSE/SSE2/AVX/部分 AVX2,并带状态化异常、Hook 与指令 Escape。
一、它解决什么问题:Guest 够用,Host 才是差异化

| 维度 | Guest 模式 | Host 模式 |
|---|---|---|
| 内存来源 | 用户显式映射 | 当前进程真实地址空间 |
| 典型用途 | 隔离执行、自建沙箱页 | 主机侧跟踪、在线函数分析、插桩实验 |
| 补丁 | 正常写映射页 | mem_patch_* 叠层:模拟视图 ≠ 真实内存 |
| API 气质 | 刻意接近 Unicorn | 额外暴露完整 cpueaxh_x86_context、Escape/Host Call |
README 的定位很清楚:研究向 / 实验向 x86-64 模拟器、Windows 主机分析与插桩核心、轻量执行引擎。若你要跨架构(ARM + Dalvik)或完整系统仿真,应继续看 Unicorn / QEMU / Unidbg 一类方案——本篇同日另有 Unidbg+MCP 文,产品与问题域不同,勿混为一谈。

二、工程画像:C ABI、静态库、用户态与内核共用核心
公开接口在 cpueaxh/cpueaxh.hpp,导出符号统一 cpueaxh_*,C/C++ 均可调用。核心以静态库形式集成(VS2022 / MSVC v143 / x64);内核示例 kexample 链接 kcpueaxh,演示 KMDF 非 PnP 驱动里跑 Host 模式。
设计取舍(对实践有感的几条):
1. 执行不依赖异常处理机制:异常状态写在 CPU 上下文里,用 cpueaxh_code_exception() / cpueaxh_error_code_exception() 查询,而不是靠宿主 SEH/VEH「撞出来」。
2. 已建模的 CPU 异常:#DE #GP #SS #NP #UD #PF #AC。
3. 页属性不止 R/W/X:cpueaxh_mem_set_cpu_attrs() + CPUEAXH_MEM_ATTR_USER,CPL 与页属性不匹配时可走正确的页错误语义。
4. Guest 内存语义类 Unicorn:4KB 对齐、unmap/protect 可按区间拆分、区分 UNMAPPED / PROT 的读/写/取指结果。
仓库骨架可记成:
cpueaxh/ # 用户态核心静态库
cpu/ # 上下文、执行器、访存
memory/ # 虚拟内存管理
instructions/ # 指令族实现
example/ # 用户态示例(含 Hook / Escape / Host MessageBox 等)
kcpueaxh/ # 内核态静态库变体
kexample/ # KMDF Host 示例
构建环境目前以 Windows + Visual Studio 2022 + WDK/KMDF(可选) 为主;示例除 MSVC/MASM 外无额外第三方库依赖。
三、最小可用路径:打开引擎 → 映射 → 跑起来
下面片段直接来自官方 README 的「快速示例」口径,适合作为集成冒烟测试。
1. 创建引擎
cpueaxh_engine* engine = NULL;
cpueaxh_err err = cpueaxh_open(CPUEAXH_ARCH_X86, CPUEAXH_MODE_64, &engine);
if (err != CPUEAXH_ERR_OK) {
/* 处理打开失败 */
}
2. Guest:映射代码页并写入机器码
cpueaxh_set_memory_mode(engine, CPUEAXH_MEMORY_MODE_GUEST);
cpueaxh_mem_map(engine, 0x1000, 0x1000,
CPUEAXH_PROT_READ | CPUEAXH_PROT_WRITE | CPUEAXH_PROT_EXEC);
cpueaxh_mem_write(engine, 0x1000, code, code_size);
3. 设置 RIP 并启动
uint64_t rip = 0x1000;
cpueaxh_reg_write(engine, CPUEAXH_X86_REG_RIP, &rip);
cpueaxh_emu_start(engine, 0x1000, 0, 0, 0);
4. 枚举映射区
cpueaxh_mem_region* regions = NULL;
uint32_t count = 0;
if (cpueaxh_mem_regions(engine, ®ions, &count) == CPUEAXH_ERR_OK) {
/* 使用 regions[0..count) */
cpueaxh_free(regions);
}
生命周期上记得配对 cpueaxh_close()。寄存器用 cpueaxh_reg_read / cpueaxh_reg_write;执行还有 cpueaxh_emu_start_function() 与 cpueaxh_emu_stop()。
边界:指令覆盖仍在扩展中;遇到未实现操作码会走
#UD等异常路径。上线前用目标工作负载做覆盖率抽检,不要假设「能跑完任意商业 PE」。
四、Hook 与 Escape:观察流、补洞、把特权指令交回宿主
Cpueaxh 的可观测性分三层,和 Unicorn 用户的心智模型基本对齐,但 Escape + cpueaxh_host_call() 是 Host 场景的关键拼图。

1. 代码与内存 Hook
cpueaxh_hook_add()/cpueaxh_hook_del()cpueaxh_hook_add_address():精确地址- 代码:
CPUEAXH_HOOK_CODE_PRE/POST - 成功访存:
MEM_READ/WRITE/FETCH(回调拿地址、大小、值) - 非法访存:
*_UNMAPPED/*_PROT;回调可修复映射/权限后返回非 0 让引擎重试,返回 0 则维持失败路径
示例工程里演示了:pre-hook 打印后续 16 字节、post-hook 打 RIP、精确地址 hook、访存观察、以及 READ_UNMAPPED / WRITE_PROT 自愈。
2. Escape:把「不该在纯软模拟里硬扛」的指令交出去
按指令类别注册(当前每类一个 Escape),可限制地址范围。已支持类别包括:
syscall / sysenter、int / int3 / hlt、cpuid / xgetbv / rdtsc / rdtscp / rdrand、rdsspd / rdsspq、端口 in / out。
回调拿到已解码指令字节 + 可修改的 cpueaxh_x86_context,两条路:
1. 纯 C/C++ 软模拟(示例里 rdtsc / rdtscp / rdrand 等);
2. cpueaxh_host_call() 原生桥:把模拟上下文的寄存器/标志/SIMD 灌进真实 CPU 上下文 → 跳进用户桥接例程 → 再把结果写回模拟上下文。桥接前 guest 栈顶会预置恢复地址,例程结束可通过 [rsp] 跳回模拟流。示例对 syscall / cpuid / xgetbv 用了 MASM 原生桥。
公开的 cpueaxh_x86_context 含 GPR、RIP、RFLAGS、XMM/高位 YMM、MMX、MXCSR、段寄存器、GDTR/LDTR、CPL、当前异常状态——Host 模式、Escape、调试同步都靠它。
3. Host 模式补丁
cpueaxh_mem_patch_add() / cpueaxh_mem_patch_del():让模拟 CPU 看见与真实内存不同的字节,适合「只改模拟视图、不动宿主映像」的实验。示例含 Host 下跑 MessageBoxA 与补丁演示——请在自有样本与授权环境中复现,勿对未授权第三方进程做注入式实验。
五、和 Unicorn / Unidbg 怎么选(防预期错位)
| 需求 | 更合适的选择 | 原因 |
|---|---|---|
| 多架构、生态成熟、跨平台脚本 | Unicorn | 覆盖广、绑定多、社区大 |
| Android/iOS Native + JNI/ART | Unidbg | Dalvik/JNI 补环境是强项 |
| Windows 进程内就地跑 x64、要补丁叠层 / Escape 回宿主 | Cpueaxh | Host 模式 + 用户态/内核同核 |
| 完整 OS / 设备模型 | QEMU 等 | Cpueaxh 明确不做系统虚拟化 |
诚实边界(来自 README 定位):
- 积极开发中,目标含完整 x86-64 与 Heaven's Gate,但现状是「常用指令 + 部分 SIMD」;
- 非完整 Unicorn 替代;
- 构建与示例偏 Windows/MSVC;跨平台移植要自己评估平台抽象层成本;
- Escape 每指令类仅一个注册槽——复杂多插件场景要自己做分发层。
六、排坑清单(集成前先过一遍)
1. 页对齐:Guest 映射按 4KB;随意地址会在 map/protect 阶段失败。
2. 模式切错:Host 下再按 Guest 习惯 mem_map 一块「假进程」会浪费时间;先 cpueaxh_set_memory_mode。
3. 未实现指令:用 #UD / Escape 兜底策略提前设计,避免长跑到一半静默偏航。
4. 非法访存回调语义:返回值决定「重试还是失败」;忘记修复映射会陷入反复失败。

5. 内核示例:需要 WDK/KMDF;先在用户态 example 验证逻辑再上驱动。
6. 合规:Host 模式能力强,只用于授权分析、自有软件测试与研究原型。
配套目录 practice/ 可放你本地精简的 Guest 冒烟工程(机器码片段 + 寄存器断言)。本环境为 Linux 沙箱,未强行交叉编译 Windows/MSVC 工程;以官方 example/main.cpp 为准做复现。
七、小结
Cpueaxh(saileaxh/cpueaxh)把「类 Unicorn 的 Guest 沙箱」和「对着真实进程 VA 的 Host 模拟」放进同一份无依赖 x86-64 核心,再用 Hook、状态化异常、Escape/host_call 和内存补丁叠层补齐主机侧分析闭环。适合做 Windows 向研究引擎与插桩原型;若要多架构生态或移动 Native 全家桶,请继续 Unicorn / Unidbg。先跑通 Guest 冒烟,再按需切 Host——比一上来对复杂二进制「全量仿真」更不容易踩坑。
仓库:https://github.com/saileaxh/cpueaxh
协议:MIT
交流:README 公布的 QQ 群 / Discord(以仓库为准)
💻 配套实训环境与动手练习
本文涉及的相关技术指令、开发环境与工具链已内置在边学边练在线实验室中,无需繁琐安装配置,随时在浏览器中实践体验: