代码保护软件VMP逆向分析虚拟机指令:分析那4条汇编被VM的VM指令

?看了网上大神们写了好多的vmp 虚拟代码的分析 ,但是在对实在项目时,插件总是提示不对或者未知版本,一直对vm代码的还原有质疑,于是就萌发了具体分析这个vm代码是怎么回事,若有错误,欢迎指出,能力有限只能分析皮毛,只谈vm的代码。

VMProtect正版授权在线订购享受最低价,仅售801元起!还不赶紧加入你的订购清单/span>>>更多详情可点击咨询购买

相关链接:

代码保护软件VMP逆向分析虚拟机指令:初步认识与环境搭建(一)

代码保护软件VMP逆向分析虚拟机指令:VMP代码的提取(二)

代码保护软件VMP逆向分析虚拟机指令详细分析(三)

四、分析那4条汇编被VM的VM指令

其他无关的我就不贴上来了,我直接贴上分析出的VM指令,怎么分析出的,和上面的分析VM指令同理

----------------------------------------------------------------                                             >>>>>>>>>>>>>>>>>>>>>>>>vm的汇编解析VM_PushImm32 0x00001111VM_PopReg32  vm_context->0x1C   0x00001111VM_PushImm32 0x00003333VM_PopReg32  vm_context->0x00   0x00003333VM_PushImm32 0x00002222                       执行下面的VM_Add后  | dwResult 0x00005555VM_PushReg32 vm_context->0x00   0x00003333                        | eflags   0x00000206VM_AddVM_PopReg32  vm_context->0x1C   0x00000206 EFLAGSVM_PopReg32  vm_context->0x1C   0x00005555VM_PushImm32 0x00001010VM_PushReg32 vm_context->0x1C   0x00005555 dwResult 上一次Add的结果VM_PushReg32 vm_context->0x1C   0x00005555VM_Nand                         执行后 [ESP] = EFLAGS = 0x286  [ESP+4]=0xFFFFAAAAVM_PopReg32  vm_context->0x00   0x286 弹出这个后 现在栈上应该是[ESP]=0xFFFFAAAA [ESP+4]=0x0x00001010VM_Add                          执行这个这里后  [ESP] = EFLAGS = 0x282    [ESP+4]=0xFFFFBABAVM_PopReg32  vm_context->0x0C   0x282 eflagsVM_PushReg32 vm_esp             现在[ESP] = ESP+4 即保存这个地址 这个地址对应的值是 0xFFFFBABA 没问题吧VM_SSReadMemSS                  把栈顶的值当mem读 值返回到自身 [ESP]=[[ESP]] = [ESP + 4] = 0xFFFFBABAVM_Nand                         还没运行这个指令时[ESP]=0xFFFFBABA [ESP+4]=0xFFFFBABAVM_PopReg32  vm_context->0x20   0x202  eflagsVM_PopReg32  vm_context->0x10   0x00004545  到这里 可以说这4句汇编已经运行完毕了VM_PushReg32 vm_context->0x0C   0282        但是还要处理这个符号寄存器的值应该是多少VM_PushImm32 0x815              因为我们是用其他方式去解析这个解法 是吧 那么每一步的eflags的变化VM_Nor                          dwResult = 0xFFFFFFFFVM_PopReg32  vm_context->0x00   0x286 eflags        那么这些每一步eflags的变化怎么转化为减法时产生的eflags一致呢VM_PushReg32 vm_esp VM_SSReadMemSS                 看到很多vm指令可以合为一个我们认识的指令是吧 比如这里的 压esp 直接读[[esp]]值反回[ESP]VM_Nand                        其实就是 VM_Nand(0xFFFFFFFF,0xFFFFFFFF) -> dwResult = 0x00000000VM_PopReg32  vm_context->0x1C  0x246 eflagsVM_PushReg32 vm_context->0x20  0x202VM_PushReg32 vm_context->0x20  0x202VM_Nor                         ~0x202 & ~0x202 =  0xfffffdfdVM_PopReg32  vm_context->0x18  0x282VM_PushImm32 0x815             ----------  这里应该是提取 OF、ZF 标志 -------------VM_Nand                        ----------------------------------------------------VM_PopReg32  vm_context->0x1C  eflags 这里说的是 VM_Nand(0x282,0x815)的eflagsVM_Add                         0x202 dwResultVM_PopReg32  vm_context->0x1C  eflags 这里也是一样 不管是VM_Add还是VM_Nor等 都是读[ESP]和[ESP+4]值运算VM_PopReg32  vm_context->0x00  0x202  接上句 结果放[ESP+4]  影响的符号(或者说运算后符号寄存器)放[ESP]                                                >>>>>>>>>>>>>>>>>vm的代码解析完毕

然后我们总结简化一下是这样:

VM_Add (0x00003333,0x00002222)   0x00005555VM_Nand(0x00005555,0x00005555)   0xFFFFAAAAVM_Add (0xFFFFAAAA,0x00001010)   0xFFFFBABAVM_Nand(0xFFFFBABA,0xFFFFBABA)   0x00004545

哦豁!有点东西了是不,与非门。vmp中大名鼎鼎的与非门,传说中的化简为繁…………

我们把上面的4句vm指令翻译成数学表达/- A = 0x3333 + 0x2222| A = ~A 因为这里VM_Nand 中and 两边的值是一样的我就不写成~A & ~A 了| B = A + 0x1010- B = ~B我们知道 int32的X 的 ~X = 0xFFFFFFFF - X 是吧所以我们在化解/ A = ~0x5555 --> B = 0xFFFFFFFF - (0xFFFFFFFF - 0x5555 + 0x1010) ---> B=0x5555-0x1010 = 0x4545 B = ~(A + 0x1010)这个是数学上的东西是吧 当然了 这些规律我们都是可以总结的

我们简单总结一下这个与非门变换出的几种算术推导

1.NOT(A):      NAND(A,A)2.AND(A,B):    NAND(NAND(A,A),NAND(B,B))3.OR(A,B):    NAND(NAND(A,B),NAND(A,B))4.XOR(A,B):    NAND(NAND(NAND(A,A),NAND(B,B)),NAND(A,B))5.SUB(A,B):    NAND(NAND(A,A)+B)6.AND(A,B):       NAND(NOR(A,B),NOR(A,B)) 注意这个推导

很明显,我们上面的 0x5555-0x1010用到了 推导5
到这里我们差不多分析完毕了,但是我们还差一个符号位的变化,看看他是怎么搞的,分析下

VM_Add (0x00003333,0x00002222)   0x00005555  eflags 0x206 丢弃VM_Nand(0x00005555,0x00005555)   0xFFFFAAAA  eflags 0x286 vm_context->0x00VM_Add (0xFFFFAAAA,0x00001010)   0xFFFFBABA  eflags 0x282 vm_context->0x0c  --有效的eflagsVM_Nand(0xFFFFBABA,0xFFFFBABA)   0x00004545  eflags 0x202 vm_context->0x20  --有效的eflags看到上面 SUB(A,B)-> NAND(NAND(A,A)+B) 而这里有的代码是先加0x2222 在减0x1010所以我们 加0x2222得到的符号eflags我们丢弃了 看到下面可以看出是用了之后的进行处理的也就是说只要模拟出减时的符号变化即可 (我们知道加和减的符号影响是一样的 在计算机中加减有什么区别呢 是吧)imm32 0x815 -> SF、AF、PF、CF----------------------------------------------------------VM_Nor (0x282, 0x815)           -> dwResult = 0xffffffff---->|VM_Nand(0xffffffff, 0xffffffff) -> dwResult = 0x00000000-----|- 0x282 & 0x815VM_Nor (0x202, 0x202)           -> dwResult = 0xfffffdfd---->|VM_Nand(0xfffffdfd, 0x815)      -> dwResult = 0x202--------->|- 0x202 & 0xffff7ea  - > (0x202 & ~0x815)VM_Add (0x00000000, 0x202)      -> dwResult = 0x202----------|- (0x282 & 0x815) + (0x202 & 0xffff7ea)

所以我们只是对两个eflags的变换就完成了真正的sub影响的符号位。我们知道sub影响的标志位为: 0F SF ZF AF PF CF

-> 公式应该是 : (0x282 & 0x815) + (0x202 & 0xffff7ea)
注意0x815指的是 SF、AF、PF、CF , 而0xffff7ea正好是0x815的反
-> 所以应该是第一个eflagsA 取 OF、AF、PF、CF 。 第二个eflagsB取其他值,
当然这里有意义的就是AF和ZF。

1.eflagsA = 0x282 是 VM_Add (0xFFFFAAAA,0x00001010)来的, 而我们知道add影响的标志位和sub是一样的,说明这一步后
其实我们就得到了0F SF ZF AF PF CF那么说明我们是不是只要这个eflagsA就可以了呢,但是你别忘了了后面还有个VM_Nand
2.eflagsB = 0x202 是紧跟着的VM_Nand来的,而我们知道and影响的标志位为: 清空OF、CF,设置SF、ZF和PF,AF不影响
 
我们回过头来分析
eflagsA ->  0x282 & 0x815   提取的是      OF、AF、PF、CF
eflagsB ->  0x202 & ~0x815  提取的是      SF、ZF
当然标志位的值不只是这些,但是我们只关心目前的sub影响的标志位,其他的我们先不考虑,其他我不知道是什么用的,没深入分析。
这样最后 相加(加 或者 或 都可以) 就得到了 0F SF ZF AF PF CF 6个标志位
 
1.疑问 : 为什么对于eflagsB我们只是提取了SF、ZF 没有提取OF、CF。首先SUB的计算其实在ADD中就做完了,关于标志的部分(与结果无关只与过程),
所以eflagsB VM_Nand生成的 and影响清空OF、CF,我们不提eflagsB中的OF、CF做结果是因为OF、CF是计算的过程中影响的符号,而用了SF、ZF是因
为SF是结果符号标志(即负数或者正数),ZF也是结果符号标志(结果是0就激活ZF)。所以用的最后的eflagsB的影响的这两个标志位,也是VM_Nand后才得
到最后的结果。
2.那在VM_Nand中我们要考虑Not操作影响的符号标志位吗不需要,因为他不影响标志位

如果您对该加密/解密软件感兴趣,欢迎加入vmpQQ交流群:

标签:

来源:慧都

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年5月20日
下一篇 2021年5月20日

相关推荐

发表回复

登录后才能评论