LLVM 原生二进制分析与仿真平台,可将 AArch64 和 x86_64 机器码提升为 LLVM IR,用于插桩、去混淆和运行时恢复。
AetherVM 是一个基于 LLVM 的原生二进制分析与模拟平台,围绕将指令提升为 LLVM IR 构建。它通过统一的中间表示将静态、动态和符号分析整合在一起,从而实现高级插桩、运行时恢复、去混淆和程序理解。
AetherVM 的灵感来源于 ICPP 和 Remill,并部分派生自它们。
Machine)驱动引擎以进行 shellcode 风格分析,或从已加载的 Binary 驱动以进行完整的提升/插桩/分析工作流。Register 枚举以及 RegisterValue/RegisterValueSIMD 表示覆盖两种架构,包括标志位(NZCV/rflags)、FP/SIMD(Q0-31/XMM0-31)以及旧式 x87/MMX 状态。EventCallback 传递。makeExecutable 将任意客户机地址转换为真实、可调用的宿主函数指针。EventConfig::debug / dbgport),默认端口为 60807。Platform.h),用于在 Windows、Linux(Android) 和 Darwin(macOS、iOS[甚至未越狱]) 上进行分页、内存访问、符号解析和进程信息获取。头文件组织在单一的 aether 命名空间下。
| 头文件 | 用途 |
|---|---|
AetherVM.h | 核心 BinaryEngine 类 — 构造、执行、寄存器/内存访问以及事件注册。 |
Event.h | 用于插桩的 EventType、EventConfig、EventResult 以及 Event/EventCallback 类型。 |
Register.h | 用于 AArch64 和 x86_64 的统一 Register 枚举以及 RegisterValue/RegisterValueSIMD 表示。 |
Platform.h | OS 级原语:分页、进程内存读写、动态库加载以及进程信息。 |
Common.h | 平台/架构检测宏以及 AETHER_VMAPI 导出/导入宏。 |
Utils.h | 小型仅头文件实用工具:无分支二分查找、对齐辅助函数以及格式化日志记录。 |
BinaryEngineAetherVM 的核心类。
// Raw architecture context — shellcode analysis, or driving an existing
// VCPU loop (e.g. ICPP) that already manages its own analysis context.
BinaryEngine(const Machine *mach, EventConfig eventcfg = {});
// Full binary context — lifting, instrumenting, and analyzing everything
// within an attached binary.
BinaryEngine(const Binary *bin, EventConfig eventcfg = {});
关键操作:
execute(std::span<const uint8_t>) / execute(addr_t target) — 运行原始操作码或所附加二进制中的静态地址。runMain() — 运行所附加可执行文件的入口点;子类实现 recursiveLoad() 以执行重定位绑定、段映射和依赖库加载。makeExecutable(addr_t target) — 获取客户机地址对应的宿主可调用函数指针。getRegister / setRegister — 读取/写入通用寄存器和 SIMD 寄存器,可针对调用线程或特定 VM 线程(void *cpu),供调试器内部使用。mapMemory(size_t)、readMemory、readUInt64、writeMemory、mappedAddress — 客户机内存管理和地址转换。registerCallback(EventCallback) — 注册插桩回调(必须在执行客户机代码之前完成;非线程安全)。子类(例如 Mach-O/ELF/PE 引擎)重写 recursiveLoad() 以实现特定格式的加载。
EventConfig 是一个打包的 64 位位域,用于选择触发哪些类别的事件:lift、memory、func、block、insn、syscall、trap、bridge 和 debug(带有相关的 dbgport)。事件通过 Event 变体以 EventRuntime、EventLift、EventMemory 或 EventHyperCall 之一的形式传递,回调返回 EventResult(Continue、Processed 或 Terminate)以控制执行。
Register 提供了一个跨越两种架构的枚举,x86_64 名称被别名到共享的通用槽位上(例如 RIP = PC、RSP = SP、RBP = FP)。RegisterValue 是一个联合体,支持所有整数宽度、浮点数、指针以及架构特定的标志布局(AArch64 的 NZCV,x86_64 的 rflags);RegisterValueSIMD 覆盖 128 位情况。
Platform.h 暴露了引擎内部使用的 OS 原语,并可供宿主侧工具使用:页分配/提交/取消提交、进程内存读写(可选针对另一个 pid)、动态库加载和符号解析,以及基本进程信息(self_path、current_pid、stack_size)。
Usage: aevm.cc [-arch x64|arm64] [-bin hex-opcodes] [-reg init-list] [-debug]
-arch : if omitted then the current host architecture will be applied
-bin : raw opcode in hex format
-reg : register initial name=val list split with ';'
-debug : start the internal gdb-remote debug server
e.g.:
icpp aevm.cc -arch arm64 -bin 1f2003d51f2003d51f2003d5
icpp aevm.cc -arch arm64 -bin 1f2003d51f2003d51f2003d5 -reg "x0=1;x1=2;x2=0xa;x3=0xb" -debug
icpp aevm.cc -arch x64 -bin 909090
icpp aevm.cc -arch x64 -bin 909090 -reg "rdi=1;rsi=2;rdx=0xa;rcx=0xb" -debug
如果指定了 -debug,你可以使用 lldb、Cutter 或 IDA 连接到 AetherVM。
如果你使用的是 IDA,请确保在 GDB Configuration 中取消勾选 No-Ack mode。
% icpp aevm.cc -arch arm64 -bin 1f2003d51f2003d51f2003d5 -reg "x0=1;x1=2;x2=0xa;x3=0xb" -debug
Start emulating...
Aether Debugger - listen://0.0.0.0:60807
(lldb) proc conn connect://localhost:60807
Attached to process 30311...
Process 30311 stopped
* thread #1, name = 'AetherThread-1', stop reason = Finished attaching
frame #0: 0x0000000000000000
-> 0x0: nop
0x4: nop
0x8: nop
0xc: udf #0x0
Target 0: (No executable module.) stopped.
(lldb) reg read x0 x1 x2 x3
x0 = 0x0000000000000001
x1 = 0x0000000000000002
x2 = 0x000000000000000a
x3 = 0x000000000000000b
emubin 演示应在 Release 包中编译。
如果你在 Windows 上构建,请首先设置 Visual Studio 构建环境,例如:vcvarsall x64。
emubin % cd demo/emubin
emubin % icpp build.cc
emubin % ./build-RelWithDebInfo/emubin
Usage: ./build-RelWithDebInfo/emubin -bin /path/to/binary [-entry hex-rva] [-reg init-list] [-debug]
-bin : the binary path in PE/ELF/MachO format
-entry : the rva value in hexidecimal format
-reg : register initial name=val list split with ';'
-debug : start the internal gdb-remote debug server
e.g.:
emubin -bin /path/to/binary -entry 0x1000
emubin -bin /path/to/binary -entry 0x1000 -reg "x0=1;x1=2;x2=0xa;x3=0xb" -debug
emubin -bin /path/to/binary -entry 0x1000 -reg "rdi=1;rsi=2;rdx=0xa;rcx=0xb" -debug
AetherVM 通过将原生机器码提升为 LLVM IR 和动态执行处理器,在宿主执行和客户机分析之间架起桥梁:
flowchart TD
A[Raw Machine Opcodes\nARM64 / x86_64] -->|Decode & Lift| B[LLVM IR\nArchitecture-Independent]
B -->|Compile & Encode| C[Runtime Executable Handlers]
subgraph Threaded Chained Execution Engine
C --> D[Handler 1]
D -->|Direct Dispatch| E[Handler 2]
E -->|Direct Dispatch| F[Handler N]
end
E -.->|Yield Event / Syscall| G[Event Callback / Hypercall Hook]
G -.->|Resume Execution| F
如果你在 Windows 上构建,请首先设置 MSVC 环境,否则跳过此步骤:
# all the following steps must be done in "x64 Native Tools Command Prompt for VS"
# or
# run VS_ROOT/.../VC/Auxiliary/Build/vcvarsall.bat to initialize for 'x64'
# replace it to arm64 if you're on a Windows-ARM64 device.
vcvarsall x64
要构建你自己的版本,你需要在当前终端会话中拥有 ICPP、Ninja、CMake,并预先构建 AetherBinary。将此仓库递归克隆到包含 AetherBinary 的同一目录后,一次性构建它:
# build AetherVM
/path/to/icpp build.cc
# build AetherDbg if you'd like
/path/to/icpp lldb/build.cc
经过一段时间后,包应位于:build-Release/install。
如果你在使用 AetherVM 时遇到任何问题,在提交 issue 之前,请查看 Bug Report 模板,并尽可能提供详细信息。只有我们能够复现问题,才能解决它。
如果你有任何问题或想法,欢迎随时给我发邮件:
[email protected]
欢迎任何反馈。