对浅显类 vm 题的思路总结 # vm 概述 vm 是 virtual machine 的缩写,也就是虚拟机的意思。开发者把执行逻辑通过自己编写的解释器进行封装编写成自定义的代码执行。因为逻辑被封装,所以和一般汇编不一样,不可以直接阅读。任何语言都可以编写 vm,即使是 java (jvm 里套 vm,哈哈)。vm 题一般较难,必须有耐心。 # vm 题特征 特征一般很容易判断 一长串的字节,他们是操作码 opcode (可能是在 data 里,也可能是存储在单独的文件里) 通过 switch 分发执行 (也可以是 if-else) 有一个执行位置控制变量 (ip) # vm 解题流程 还原 vm 代码 vm 用什么编写,那还原代码就用什么编写。需要编写出与 vm 题里逻辑一样的代码。可以由 ida (c 语言) 或者 jadx (java) 生成的代码修改得到。 在每行 case 末尾 print 出代码执行的逻辑 这是最重要的一步。打印的字符串尽量规范,以便于直接运行。注意识别有没有入栈出栈的代码实现。 注释掉不必要代码 在输入错误 flag 情况下执行可能会出现许多问题,比如数组访问越界,控制语句导致执行退出等等。所以建议把其他代码全注释掉,只留下打印代码和改变 ip 的代码,如果有判断寄存器的代码,可以根据 vm 运行情况来注释掉判断语句。要让 vm 跑完所有 opcode 再正常退出循环。 分析逻辑 根据打印的代码逻辑分析 vm 的执行情况。vm 的代码很可能是使用 z3 约束求解进行解题的,也可能是其他逻辑,需要自行变通。 汇编 Re