文章总结: 本文通过IDAPro逆向分析SimpleVM.exe程序,详细剖析了VM解释器架构、状态结构及13条指令集功能。文章分析了字节码数据位置与执行流程,指出程序具备PC边界、算术溢出及栈边界检查等安全特性。建议读者提取完整字节码、编写反汇编器及VM模拟器进行动态分析,加深对虚拟机保护技术的理解。 综合评分: 88 文章分类: 逆向分析,二进制安全
“逆向VM字节码程序”的学习(四)
原创
MicroPest MicroPest
MicroPest
2026年2月1日 17:21 安徽
昨天,我们通过编写VM字节码程序(《“逆向VM字节码程序”的学习(三)》)了解了它的“取码、译码、执行”规则。今天,我们继续对昨天编写的程序进行一次逆向分析,再次加深理解和感悟。
通过网盘分享的程序1:smokestack.exe(《“逆向VM字节码程序”的学习》)
链接: https://pan.baidu.com/s/1Wdw3BNPQfmXTu7If5Fz_RA 提取码: 4v4q
网盘分享的程序2:SimpleVM.exe(《“逆向VM字节码程序”的学习(三)》)
链接: https://pan.baidu.com/s/1alCw5cm2JB_4ChuznOIacg 提取码: ur5m
VM字节码程序分析报告(对SimpleVM.exe逆向分析)
一、 程序概览
通过IDA Pro MCP分析,该程序是一个基于虚拟机(VM)的应用程序,使用自定义字节码来执行逻辑。
二、 VM架构分析
1、 VM解释器函数
-
地址
:
0x41EBA8(sub_41EBA8) -
功能
: 核心VM解释器,循环读取并执行字节码指令
2、 VM状态结构
VM状态存储在一个数据结构中,关键字段包括:
-
offset +5120 (0x1400): 程序计数器(PC)
-
offset +5124 (0x1404): 未知寄存器(-1初始值)
-
offset +5128 (0x1408): 停止标志(halt flag)
-
offset +0-4095: 字节码数组(1024个DWORD,即4KB字节码空间)
3、 VM指令集
通过反编译解释器函数,识别出以下13条指令:
指令 0: HALT
-
操作
: 停止VM执行
-
PC变化
: PC++
-
功能
: 程序正常退出
指令 1: PUSH (立即数)
-
操作
: 将下一个DWORD作为立即数压入栈
-
PC变化
: PC += 2
-
功能
: 压栈操作数
-
格式
:
[1] [immediate_value]
指令 2: POP
-
操作
: 从栈中弹出一个值
-
PC变化
: PC++
-
功能
: 出栈
指令 3: ADD
-
操作
: 弹出两个值,相加后压栈
-
PC变化
: PC++
-
功能
: 加法运算 (v2 = pop(); v1 = pop(); push(v1 + v2))
-
错误检查
: 检查溢出
指令 4: SUB
-
操作
: 弹出两个值,相减后压栈
-
PC变化
: PC++
-
功能
: 减法运算 (v2 = pop(); v1 = pop(); push(v1 – v2))
-
错误检查
: 检查溢出
指令 5: MUL
-
操作
: 弹出两个值,相乘后压栈
-
PC变化
: PC++
-
功能
: 乘法运算 (v2 = pop(); v1 = pop(); push(v1 * v2))
-
错误检查
: 检查乘法溢出
指令 6: DIV
-
操作
: 弹出两个值,相除后压栈
-
PC变化
: PC++
-
功能
: 除法运算 (v2 = pop(); v1 = pop(); push(v1 / v2))
-
错误检查
: 除数为0时报错 “Division by zero”
指令 7: JMP (无条件跳转)
-
操作
: 直接跳转到指定地址
-
PC变化
: PC = [PC+1]
-
功能
: 无条件跳转
-
格式
:
[7] [target_address]
指令 8: JNZ (条件跳转)
-
操作
: 如果栈顶非零则跳转
-
PC变化:
-
如果pop() != 0: PC += 2
-
否则: PC = [PC+1]
-
功能: 条件跳转
-
格式:
[8] [target_address]
指令 9: INPUT
-
操作
: 读取用户输入并压栈
-
PC变化
: PC++
-
功能
: 输入操作
指令 10: SWAP
-
操作
: 交换栈顶两个元素
-
PC变化
: PC++
-
功能
: v2 = pop(); v1 = pop(); push(v2); push(v1)
指令 11: OUTPUT
-
操作
: 输出栈顶值
-
PC变化
: PC++
-
功能
: 输出操作
指令 12: EXIT
-
操作
: 设置停止标志
-
PC变化
: 不变
-
功能
: 强制退出VM
三、 字节码数据位置
1、 字节码段1
-
地址
:
0x423524 -
大小
: 至少11个DWORD
-
内容:
01 00 00 00 ; PUSH
05 00 00 00 ; [value: 5]
01 00 00 00 ; PUSH
03 00 00 00 ; [value: 3]
01 00 00 00 ; PUSH
02 00 00 00 ; [value: 2]
05 00 00 00 ; MUL
03 00 00 00 ; ADD
0b 00 00 00 ; OUTPUT
0c 00 00 00 ; EXIT
00 00 00 00 ; HALT
分析: 这段代码计算 5 + (3 * 2) = 11 并输出
2、 字节码段2
-
地址
:
0x423554 -
大小
: 至少14个DWORD
-
内容:
01 00 00 00 ; PUSH
05 00 00 00 ; [value: 5]
01 00 00 00 ; PUSH
05 00 00 00 ; [value: 5]
04 00 00 00 ; SUB
08 00 00 00 ; JNZ
0b 00 00 00 ; [target: 11]
01 00 00 00 ; PUSH
78 03 00 00 ; [value: 0x378 = 888]
0b 00 00 00 ; OUTPUT
0c 00 00 00 ; EXIT
01 00 00 00 ; PUSH
e7 03 00 00 ; [value: 0x3e7 = 999]
0b 00 00 00 ; OUTPUT
0c 00 00 00 ; EXIT
分析:
- 计算 5 – 5 = 0
- 如果结果非0跳转到地址11
- 否则输出888并退出
- 跳转目标: 输出999并退出
后续还有函数指针表数据。
四、 程序执行流程
1 初始化流程
(1)start
(0x421984) – 程序入口
(2)sub_41F0C4
/ sub_41F104 – 加载字节码到VM
(3)sub_41F060
- 拷贝字节码数组
(4)sub_41E9B8
- 初始化VM状态
(5)sub_41EBA8
- 执行字节码
2 VM执行过程
(1)检查halt标志
(2)检查PC是否越界 (PC < 0x400)
(3)读取当前指令: opcode = vm[PC]
(4)根据opcode执行相应操作
(5)更新PC
(6)循环执行直到halt
五、辅助函数
-
sub_41EA08: 栈PUSH操作
-
sub_41EA9C: 栈POP操作
-
sub_41EB30: INPUT操作
-
sub_405A70,
sub_405D70,sub_4044E4: OUTPUT相关 -
sub_405F50: PC越界错误处理
-
sub_405F58: 溢出错误处理
-
sub_41B698: 错误信息显示
-
sub_407684: 错误退出
六、安全特性
程序包含多项安全检查:
-
PC边界检查
: 防止代码执行越界
-
算术溢出检查
: ADD/SUB/MUL操作检查溢出
-
除零检查
: DIV操作检查除数
-
栈边界检查
: 防止栈溢出/下溢
七、逆向分析建议
1 提取完整字节码
可以通过以下方式提取完整字节码:
- 从
0x423524和0x423554读取完整数据 - 分析调用
sub_41F060时传递的长度参数
2 编写反汇编器
基于识别的指令集,可以编写Python脚本将字节码反汇编为可读格式。
3 编写VM模拟器
可以用Python重新实现VM解释器,用于动态分析和调试。
八、 示例分析
字节码段1执行过程:
PUSH 5 ; stack = [5]
PUSH 3 ; stack = [5, 3]
PUSH 2 ; stack = [5, 3, 2]
MUL ; stack = [5, 6] (3*2)
ADD ; stack = [11] (5+6)
OUTPUT ; 输出: 11
EXIT ; 退出
HALT
字节码段2执行过程:
PUSH 5 ; stack = [5]
PUSH 5 ; stack = [5, 5]
SUB ; stack = [0] (5-5)
JNZ 11 ; 0==0, 不跳转
PUSH 888 ; stack = [888]
OUTPUT ; 输出: 888
EXIT ; 退出
九、 总结
这是一个设计良好的基于栈的虚拟机实现,具有:
- 完整的算术运算指令集
- 控制流指令(JMP/JNZ)
- I/O操作(INPUT/OUTPUT)
- 完善的错误检查机制
- 清晰的架构设计
该VM可用于:
- 代码混淆
- 程序保护
- 脚本执行引擎
- CTF挑战
十、 进一步研究方向
- 提取并分析所有字节码段
- 分析INPUT函数的具体实现
- 查找可能的flag检查逻辑
- 编写完整的VM模拟器用于动态分析
- 寻找可能的VM漏洞或绕过机制
十一、感悟
通过四篇系列文章,我们完成了从对“VM字节码”逆向学习到编程学习的不断深化前进的工作,收获颇多。总体感觉到字节码技术作为编程语言与硬件之间的桥梁,在现代软件工程中扮演着越来越重要的角色:
核心价值
- 跨平台性
- 一次编译,到处运行
- 安全性
- 沙箱隔离、代码保护
- 可移植性
- 中间表示的标准化
- 优化空间
- JIT/AOT编译机会
发展方向
- 🚀 性能接近原生 (WebAssembly, GraalVM)
- 🔐 安全性增强 (形式化验证, 沙箱技术)
- 🌍 应用场景扩展 (区块链, 边缘计算, IoT)
- 🤖 AI/ML融合 (模型部署, 推理优化)
字节码技术不会消亡,反而会在云原生、Web3、边缘计算等新兴领域找到更广阔的应用空间!
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:MicroPest MicroPest MicroPest《“逆向VM字节码程序”的学习(四)》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论