首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
逆向工程
发新帖
1
0
[分享]vm解释器入门2
发表于: 2026-4-18 23:35
1297
[分享]vm解释器入门2
mb_binusgki
2026-4-18 23:35
1297
# 前言 上篇文章笔者做了一个简单的vm解释器作为入门框架,本节继续来完善这个简易vm解释器 本节中将会在之前的解释器基础上添加 栈空间、栈操作(PUSH、POP)、函数调用(CALL、RET) 以及升级宏的方式进行调用代码更加清楚,并且实现对标签的支持 再无需手写跳转位置(很容易写错 写错了崩溃又很难排查) 最后将上节涉及的阶乘例子改为递归调用的方式实现,可充分练习函数调用以及栈区操作 # 一、新增指令 新增:OP_PUSH, OP_POP, OP_CALL, OP_RET ``` enum { OP_MOV_IMM, OP_MOV_REG, OP_ADD, OP_SUB, OP_PRINT, OP_JMP, OP_JZ, OP_HALT, OP_PUSH, OP_POP, OP_CALL, OP_RET }; ``` # 二、新增解释器规则 ``` case OP_PUSH: { int r = code[vm.pc++];//取出寄存器号 vm.stack[++vm.sp] = vm.reg[r];//入栈 break; } case OP_POP: { int r = code[vm.pc++];//取出寄存器号 vm.reg[r] = vm.stack[vm.sp--];//出栈 break; } case OP_CALL: { int addr = code[vm.pc++];//取出跳转位置 vm.stack[++vm.sp] = vm.pc; // 保存返回地址 vm.pc = addr;//改变pc跳转 break; } case OP_RET: { vm.pc = vm.stack[vm.sp--];//取出返回地址 break; } ``` # 三、新增以及初始化栈区 这里写了新增栈区的结构,在使用时切记初始化栈指针为-1(栈指针永远指向栈空间,刚开始栈空所以指向-1) ``` struct VM { int reg[5]; // 5个通用寄存器 R0~R4 int pc; // 程序计数器 bool running; // 是否运行 int stack[256];//栈区 int sp;//栈指针 }; ``` # 四、实现自动标签插入 这里使用结构实现了对字节码的全程托管,原理是在设置标签时进行记录标签位置和标签名称,在后续处理根据调用名称自动插入标签位置 ``` struct Assembler { // 字节码 vector<int> code; // 标签列表 unordered_map<string, int> labels; // 需要修复的回填跳转 vector<pair<int, string>> fixups; //插入字节码 void emit(int v) { code.push_back(v); } //添加标签 void label(const string& name) { labels[name] = code.size(); } //记录待修复标签 void jmp_placeholder(const string& name) { // 添加到待修复列表 fixups.push_back({ (int)code.size(), name }); // 占位 code.push_back(0); } //回填标签 void patch() { for (auto& f : fixups) { int pos = f.first; const string& name = f.second; code[pos] = labels[name]; } } //获取字节码 int* getData() { //回填标签 patch(); //返回字节码 return this->code.data(); } }; ``` # 五、实现宏定义调用 实现宏定义调用,类似于汇编的形式,结构逻辑更清晰 ``` // 操作 #define MOVI(as, reg, v) do { as.emit(OP_MOV_IMM); as.emit(reg); as.emit(v); } while(0) #define MOVR(as, r1, r2) do { as.emit(OP_MOV_REG); as.emit(r1); as.emit(r2); } while(0) #define ADDR(as, r1, r2) do { as.emit(OP_ADD); as.emit(r1); as.emit(r2); } while(0) #define SUBR(as, r1, r2) do { as.emit(OP_SUB); as.emit(r1); as.emit(r2); } while(0) #define PRINT(as, r) do { as.emit(OP_PRINT); as.emit(r); } while(0) #define HALT(as) do { as.emit(OP_HALT); } while(0) // 跳转 #define LABEL(as, name) do { as.label(name); } while(0) #define JMP(as, name) do { as.emit(OP_JMP); as.jmp_placeholder(name); } while(0) #define JZ(as, reg, name) do { as.emit(OP_JZ); as.emit(reg); as.jmp_placeholder(name); } while(0) #define CALL(as, name) do { as.emit(OP_CALL); as.jmp_placeholder(name); } while(0) #define RET(as) do { as.emit(OP_RET); } while(0) // 栈 #define PUSH(as, r) do { as.emit(OP_PUSH); as.emit(r); } while(0) #define POP(as, r) do { as.emit(OP_POP); as.emit(r); } while(0) ``` # 六、递归调用阶乘练习 这里的逻辑和上节的一样,不同的是更换成递归调用的实现方式,并且升级了宏调用以及自动标签的形式,逻辑更加清晰,代码如下: ``` //阶乘练习 int main() { Assembler as; VM vm = { 0 }; //入参 int n = 5; // main MOVI(as, R0, n); // n = 5 MOVI(as, R2, 1); // const 1 CALL(as, "fact"); //调用fast方法 PRINT(as, R1); //打印 HALT(as); // ===== 函数 fact ===== LABEL(as, "fact"); JZ(as, R0, "base_case");// if (n == 0) PUSH(as, R0);// 保存 n(因为后面要改) SUBR(as, R0, R2);// n = n - 1 CALL(as, "fact");// 递归调用 POP(as, R0);// 恢复 n // ===== 乘法:R1 = R1 * R0 ===== MOVI(as, R3, 0);// temp = 0 MOVR(as, R4, R0);// counter = n LABEL(as, "mul_loop"); JZ(as, R4, "mul_end"); ADDR(as, R3, R1); // temp += result SUBR(as, R4, R2); // counter-- JMP(as, "mul_loop"); LABEL(as, "mul_end"); MOVR(as, R1, R3);// result = temp RET(as); // ===== base_case ===== LABEL(as, "base_case"); MOVI(as, R1, 1); // return 1 RET(as); //执行 run(vm, as.getData()); return 0; } ``` # 七、总结 本节主要内容为完善之前的vm解释器,为后续更为复杂的项目做铺垫,笔者希望借此入门学习解释器并且将其完成为一个可用的vm解释器框架,后续还会持续进行完善,欢迎大家讨论,如有错漏请留言!
传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!!
最后于
2026-4-18 23:39 被mb_binusgki编辑 ,原因:
#调试逆向
#系统底层
#软件保护
#VM保护
#加密算法
#问题讨论
#其他内容
收藏
・
1
点赞
・
0
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
0
)
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
mb_binusgki
29
发帖
6
回帖
0
RANK
关注
私信
他的文章
[分享]注册表回调内核通信
391
[分享]简单编译器实现
1875
[分享]Lexer简单词法解析器入门
1235
[分享]vm解释器入门2
1297
[分享]vm解释器入门
1591
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部