什么是 VMP?
vmp就是把真实机器指令转为自定义的虚拟指令, 然后交由虚拟机解释器去执行
名词解释
操作码(Opcode)
— 指令要执行的“动作”,
操作数(Operand)
— 这个动作所作用的数据(或数据的地址)
示例:
ADD R0, R1, R2 ADD 就是操作码, R0, R1, R2就是操作数,
R0 是目标寄存器,R1 和 R2 是源操作数寄存器
VMP 的基本流程
C/C++ 源代码
↓ (编译器)
机器指令(真实指令)
↓ (VMP 虚拟化)
虚拟指令(自定义指令集)
↓
虚拟机解释器执行
VMP 转化的步骤
编译生成真实指令
指令抓取与分析
VMP 工具会在编译好的程序里找到这些指令,把它们解析出来(控制流、寄存器使用、数据依赖等)。
转换为虚拟指令
真实指令 | 虚拟指令 |
MOV EAX, 5 | PUSH_IMM 5 |
ADD EAX, 3 | ADD_IMM 3 |
RET | VM_RET |
真实指令

虚拟指令
加密与打包
所有虚拟指令序列通常会:
- 被加密(防止直接读出);
- 混淆顺序;
- 隐藏在数据段或动态解密中。
插入虚拟机解释器
在程序运行时,真实 CPU 并不执行原始代码,而是执行一个 虚拟机解释器(VM Engine):
解释器从虚拟代码区读出虚拟指令,逐条“翻译执行”,从而实现了和原来一样的逻辑。
虚拟机执行流程
Fetch(取指阶段)
vPC指向虚拟代码的指针, 就是虚拟的pc寄存器, 取指从vpc寄存器取出指令vInsn
Decode(译码阶段)
取出vInsn之后,就开始解析翻译
具体来说就是对32位的数据进行切分, 就是对二进制进行切分, 提取操作码Opcode和操作数Operand
比如
ADD R0, R1, R2 ADD 就是操作码, R0, R1, R2就是操作数
Execute(执行阶段)
译码得到:操作码Opcode和操作数Operand
执行就是switch(Opcode) 做不同的执行处理
PCUpdate(更新阶段)
阶段 | 汇编指令 | 功能 | 对应虚拟机行为 |
Fetch | LDR W12, [X0] | 从内存中取指令 | vInsn = *vPC |
Decode | 一系列 AND | 提取操作码和字段 | 解析 vOpcode、vXn、vXd、imm 等 |
Execute | LDRSW → ADD → BR | 根据操作码跳转执行 | switch(vOpcode) 执行对应虚拟操作 |
PCUpdate | ADD → STR | 更新虚拟 PC | vPC = vPC + 4 |
PCUpdate(更新)之后,又继续下一轮的Fetch
实际案例执行流程
Fetch(取指)
从vPC取出vInsn 指令
Decode(译码)
把vInsn 指令的二进制切分得到操作码, 操作数, 等等
Execute(执行)
switch(vOpcode)跳转到不同的地方执行
PCUpdate(更新)
更新完继续下一个取指
需要注意不一定是顺序执行
VMState(虚拟机状态结构体)
通过 VMState,虚拟指令可以:
- 操作虚拟寄存器(vX0~vX31)
- 访问或修改虚拟 PC(vPC)
- 控制调度逻辑(vFlag)
- 实现跳转和函数调用(vAddrJump、vAddrReturn)
可以把 VMState 理解为虚拟机“CPU 的寄存器 + 内存状态”,是虚拟机执行每条指令的环境和上下文。
VMP的逆向
完全参考
- 作者:拓森Leo
- 链接:https://www.uzilol.cn/article/289bf20f-1d11-8040-921f-f06ffd6bd028
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。



