何潇潇_VMProtect 的一次奇妙之旅

姒飞燕

2017/11/14 发布于 技术 分类

VMProtect 是目前最强的虚拟化保护技术。本议题将讨论其虚拟化保护相关背景知识与设计原理,并结合一个非常流行的客户端进行还原演示。

文字内容
1. VMProtect的一次奇妙之旅 何潇潇@永信至诚
2. CONTENTS VMProtect是什么 VMProtect背后的原理 还原VMProtect的方法 演示还原 总结
3. VMProtect是什么? VMProtect是世界上最强大的二进制代码保护软件之一,是由俄 罗斯人开发的,至今没有人公开声称对其完全破解。 8/27/16 2:30PM 2
4. VMProtect是什么? 01 03 02 一个基于堆 栈机的intel指 令的模拟器 通过编译,把intel 指令编译成精心 设计的一组虚拟 指令(PCode) 特定的解释引 擎,用于解释 执行上述的虚 拟指令 8/27/16 2:30PM 从本质来讲,VMProtect是 2
5. 8/27/16 2:30PM 3
6. 相关术语 Intel指令寄存器(Register) 和 VM指令寄存器(VMReg) VMProtect一共有14个寄存 器,但是用16个格子(slot)存 放它们,有多的2个格子可 以理解成自由寄存器,最终 扩展成16个寄存器。 8/27/16 2:30PM 4
7. 相关术语 Intel指令(Intel Instruction) 和 VM指令(VMRecord) Intel指令就是Intel的汇编指令, 比如 add eax,ecx xor eax,eax … 在VMProtect的世界里面,指令是由 VMRecord组成的,比如 vm_push_imm32 0x1 vm_get_context_dword slot_offset 8/27/16 2:30PM Intel指令编译生成对应的一组VMRecord, 比如 mov ecx,eax; vm_get_context_dword vEax vm_save_context_dword vEcx 5
8. 相关术语 Intel函数基本块(BasicBlock) 和 VM基本块(VMBlock) 8/27/16 2:30PM BasicBlock是组成Intel函数控制 流图的基本单位,在VMProtect 里面,VMBlock和它一一对应的, 只不过VMBlock是VMRecord的 载体。而且基本块与基本块之间 的关系(也就是控制流图CFG), 也在VMBlock之间一一对应。 6
9. VMProtect背后的原理 8/27/16 2:30PM 7
10. VMProtect背后的原理 逻辑门运算 VMProtect是通过NOR(或非门)和ADD(加法门)来实现intel指令的等价运算。 NOR(a,b) = NOT(OR(a,b)) = AND(NOT(a),NOT(b)) 有了NOR的操作,就很容易表示其他的运算,例如: NOT(a) = NOR(a,a) AND(a,b) = NOR(NOT(a),NOT(b)) = NOR(NOR(a,a),NOR(b,b)) OR(a,b) = NOR(NOR(a,b),NOR(a,b)) XOR(a,b) = NOR(NOR(a,b),NOR(NOR(a,a),NOR(b,b))) SUB(a,b) = NOR(ADD(NOR(a,a),b),ADD(NOR(a,a),b)) 比如VMRecord来表示and eax,ecx 8/27/16 2:30PM 7
11. VMProtect背后的原理 映射 指令集可以理解成线性空间,寄存器就是空间的基,寄存器个数也就是空间 的维数。指令集中的指令,可以理解成算子,比如intel里面的add,xor,or等 在这里,intel指令集空间维度是9,VMProtect的是16,所以注定这2个空间不 同构。 从intel指令到VMProtect指令的变换f,是同态变换,也就是这种变换没有逆 变换,从理论上面证明了不存在完全还原方法。 8/27/16 2:30PM 8
12. VMProtect背后的原理 具体原因是,VMProtect的寄存器16个格子里面,任何时刻都有2个格子是 自由的(其实是3个,因为vEex是垃圾寄存器,也是自由的)。 VMProtect当一个 寄存器发生变化的时候,它不会把新的值保存在原来的那个格子里面,它会 从空闲格子里面取一个出来保存新值。比如vEax 开始存放在1号格子里面, 经过一系列运算vEax值发生变化,需要更新,这时会从空闲格子里面随机 取出一个比如(2号格子)用来存放vEax,原来的1号格子就会进入空闲池子里 了,正是这种特性,造成了Intel指令到VM指令之间不可能是一一对应的关 系,因为操作数也就是VMProtect用到的格子时刻都在随机变化,只有 VMProtect自己知道对应关系,除了它本身,第三者很难知道。 8/27/16 2:30PM 9
13. VMProtect背后的原理 还是and eax,ecx ,通过变换f,生成了上面的VMRecords 比如vEax开始保存在1号格子里面,经过and运算以后,保存最后结果的 时候,从空闲格子中随机取一个出来(比如2号),最终vEax从1号格子转 移到2号格子里面,而1号格子变成了空闲格子。 8/27/16 2:30PM 10
14. 还原VMProtect的方法 8/27/16 2:30PM 10
15. 还原VMProtect的方法 基于数据流的还原方法 是通过动态监控堆栈机的执行,获取其每一步的执行的指令,和操 作数.然后根据最终的结果进行溯源,找到其指令的内在联系. 优点 比较简单,而且效率比较高. 缺点 并没有跑遍所有的指令(non-all-path),相当粗糙,不精确. 8/27/16 2:30PM 11
16. 还原VMProtect的方法 基于控制流的静态还原方法 1.Control Flow的还原 2.Intel指令还原 Intel指令与VMRecord的对应 操作符(opcode)还原 操作数(operand)还原 8/27/16 2:30PM 12
17. Control Flow的还原 8/27/16 2:30PM 13
18. Intel指令还原 Intel指令与VMRecord的对应 在一个VMBlock里面,哪些 VMRecords对应原始的Intel指 令,这是需要首先解决,因为虚 拟机的本质是堆栈机,也就是 说,当执行完一条Intel指令对应 的VMRecords后,堆栈机的堆栈 应该是平衡的。为此,这里给 VMRecord加上一个字段,表示 执行完后,相对于VMBlock入口 出的堆栈偏移。通过观察这个堆 栈的偏移的变化来确定。 8/27/16 2:30PM 14
19. Intel指令还原 操作符(opcode)还原 操作符的还原,就是模式识别。首先是要建 立识别库,也就是规则,这个需要相当的积累。 还是用前面的例子and eax,ecx,看到左边的 VMRecords,通过模式识别,很容易就能分析 出,这是一个and 或者是 test操作,操作数是寄 存器,操作数大小是dword,通过具体后面分析, 因为结果不是垃圾数据,确定是and操作。 8/27/16 2:30PM 15
20. Intel指令还原 操作数(operand)还原 只讨论寄存器操作数的还原,这是VMProtect里面最难 的部分,先前的介绍了解到,VMProtect有2个自由寄存器和 1个vEex垃圾寄存器,导致再重新写入1个寄存器的时候,不 是写在先前位置,而是从空闲里面找一个出来写入,这种情 况在很多时候会带来很大麻烦。 对于二元操作,比如add,xor,and,or等,可以表示成 result = lhs op rhs。这是一个典型的三地址模式,因为Intel 的格式,这种指令在Intel下面其实是两地址模式,result 和 lhs 重合了。对于二元操作的情况,只要分析出源操作符, 就能对应出目的操作数是Intel下面的哪个寄存器。 8/27/16 2:30PM 16
21. Intel指令还原 但是情况在mov eax,ecx这种时候,却变得很棘手。它对应的 VMRecords是: vm_get_context_dword vEcx vm_save_context_dwordslot_id 此时我们并不知道save的slot_id对应的是哪个寄存器。 8/27/16 2:30PM 17
22. Intel指令还原 解决办法 待定寄存器法 通过vm_exit指令和vm_jmp指令,对应到真实寄存器环境,或者已知 的VMBlock入口上面,从而找到所需的数据 空闲寄存器队列法 一个寄存器被重新写入后,原来的是被放入空闲寄存器里面,而且空 闲队列就3个,再加上指令执行过程中,会经常从空闲中选择出格子写 入,所以原来的位置有很大的可能(1/3)会从空闲队列中选择出来,从 而捕捉到机会。 猜测法 8/27/16 2:30PM 17
23. 演示还原,是基于WeChat的某个版本的添加联系人功能做演示的。 8/27/16 2:30PM 17
24. 总结——VMProtect的不足 01 Options 堆栈机固有的缺陷 02 Options 指令模式只有或非逻辑,有些单调 03 Options 空闲寄存器队列长度不够,导致基于它的攻 击成功率很高 8/27/16 2:30PM 17
25. 总结——我的工作 0 Treadstone保护引擎,杜绝上面的大部 021 分缺点,还引入了寄存器置换引擎 02 目前正在基于LLVM框架,实现一个 arm指令集的类似虚拟保护引擎 8/27/16 2:30PM 17
26. THANKS