代码保护软件VMP逆向分析虚拟机指令:分析VMP的一些细节

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

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

相关链接:

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

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

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

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

五、分析VM的一些细节

我们差不多讲完基础分析是吧,基本上可以说是可以动手分析了,但是在那之前我们有些东西好像还没讲清楚,一些细节。

1、VM的栈问题

有个地方我们还没讲 ,就是如果压栈时 , 如果超出了栈大小 (就目前我们看到的还没有超栈的情况),占用到了vm_context怎么办下面是我截取的汇编, 所以你看到地址有时候很奇怪 。我们来分析一下如果压栈超出了栈空间怎么办

00433391    8D4424 60       lea eax,dword ptr ss:[esp+0x60]00433395    F6C5 65         test ch,0x6500433398    3BC9            cmp ecx,ecx0043339A    66:81FD EA79    cmp bp,0x79EA0043339F    3BE8            cmp ebp,eax004333A1    E9 0F3A0000     jmp vmptest_.00436DB500436DB5   /0F87 F2C80200   ja vmptest_.004636AD ;看到这里我们之前都是跳了 我们追踪代码00436DBB   |8BC4            mov eax,esp          ;的时候下面的代码就被跳过了,直接到了00436DBD   |8ACB            mov cl,bl            ;vmtest_.004636AD 接下来我们重点讲没跳00436DBF   |B9 40000000     mov ecx,0x40         ;过的这部分代码00436DC4   |0FC0F6          xadd dh,dh00436DC7   |8D5425 80       lea edx,dword ptr ss:[ebp-0x80]00436DCB   |3BFF            cmp edi,edi00436DCD  E9 101CFEFF     jmp vmptest_.004189E2004189E2    81E2 FCFFFFFF   and edx,0xFFFFFFFC004189E8    F9              stc004189E9    66:F7C7 8465    test di,0x6584004189EE    2BD1            sub edx,ecx004189F0  ^ E9 38D1FFFF     jmp vmptest_.00415B2D00415B2D    8BE2            mov esp,edx00415B2F    57              push edi00415B30    66:BF CD59      mov di,0x59CD00415B34    0FBFF8          movsx edi,ax00415B37    E9 FA590400     jmp vmptest_.0045B5360045B536    56              push esi0045B537  ^ E9 058AFEFF     jmp vmptest_.00443F4100443F41    9C              pushfd00443F42    66:0FCE         bswap si00443F45    8BF0            mov esi,eax00443F47    66:0F46FB       cmovbe di,bx00443F4B    8BFA            mov edi,edx00443F4D    E9 490E0400     jmp vmptest_.00484D9B00484D9B    FC              cld00484D9C  ^ E9 9513F9FF     jmp vmptest_.0041613600416136    F3:A4           rep movs byte ptr es:[edi],byte ptr ds:[esi]00416138    C1E6 B0         shl esi,0xB00041613B    C1C7 FA         rol edi,0xFA0041613E    66:0FBAFF 16    btc di,0x1600416143    9D              popfd00416144    5E              pop esi00416145    66:0FCF         bswap di00416148    8BFB            mov edi,ebx0041614A    5F              pop edi0041614B    E9 5DD50400     jmp vmptest_.004636AD004636AD    FFE7            jmp edi

我们先去混淆一下看看,按之前的方法

00433391    8D4424 60       lea eax,dword ptr ss:[esp+0x60]0043339F    3BE8            cmp ebp,eax                     ;比较栈顶 与vm_context末尾位置00436DB5   /0F87 F2C80200   ja vmptest_.004636AD            ;如果栈顶 大于 vm_context最末尾位置 证明栈还没有顶到vm_context00436DBB   |8BC4            mov eax,esp                     ;eax记录一下vm_context位置00436DBF   |B9 40000000     mov ecx,0x4000436DC7   |8D5425 80       lea edx,dword ptr ss:[ebp-0x80]004189E2    81E2 FCFFFFFF   and edx,0xFFFFFFFC              ;让后2位为0 地址对齐004189EE    2BD1            sub edx,ecx                     ;其实就是栈顶 -0xC000415B2D    8BE2            mov esp,edx                     ;把vm_context 与栈底 拉高0xC0个字节 主要是栈底不动 vm_context动00415B2F    57              push edi                        ;这一方面也是看出来为什么每次都要和esp+0x60比较0045B536    56              push esi                        -------------------------------------00443F41    9C              pushfd                          ;备份 edi 、esi、和eflags值00443F45    8BF0            mov esi,eax00443F4B    8BFA            mov edi,edx00416136    F3:A4           rep movs byte ptr es:[edi],byte ptr ds:[esi] ;然后把旧vm_context线上值 拷贝到新vm_context上00416143    9D              popfd                           ---------------------------------------00416144    5E              pop esi                         ;还原 edi、esi、和eflags值0041614A    5F              pop edi                 004636AD    FFE7            jmp edi

然后你发现了什么问题, 在最后的rep movs中, 我们是拷贝byte为单位, 拷贝的长度是由ecx决定的,但是ecx=0x40, 而我们之前很早之前说 esp+0x60我们推出寄存器有 0x60/4=0x18 个, 芜湖!!!!!!!那么我们现在怎么解释呢这里我们应该可以看出来 vm_context应该只有16个寄存器。 即0x10个寄存器而多出来的 0x20个byte(8 int32) 应该是给压栈时缓冲用的, 比如像这里他是先压栈, 在判断栈是否 栈了 ,那么如果爆栈了, 假如vm_context是0x18个寄存器, 他就会覆盖到第0x17编 寄存器,那么他就没办法回缩 还原vm_context上被感染的寄存器值(如果要能还原 带价太大) 所以这里多出的8 int32 应该是缓冲用的。

所以说分析问题 往往都是 ,从假设开始 ,你之前看到的可能 会被后面的又重新定义 ,然后你会发现
你之前的好像不太严谨 ,往后看这个就严谨了 ,好像一切 就 豁然开朗了。

2、寄存器轮转机制

VM_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句汇编已经运行完毕了

我们可以看到 0x2222 + 0x3333 = 0x5555 如果按我们的那4句汇编来的话, 这个0x5555应该是在eax寄存器上,如果说vm_context 的某个偏移值与我们物理机的寄存器是绝对对应关系的话, 那么往下走得到的最终结果应该也是在 0x5555所在的这个寄存器上即 vm_context->0x1C, 但是我们发现不是了, 而是vm_context + 0x10上。这就是VMP所谓的寄存器轮转机制, 这个轮转是在程序编译期间有一张表, 所以现在你是无法看到这个对应关系的转变。

3、同一条指令的不同比较

-------------------------------------------------------------------------------------------VM_PushReg32  vm_context->0x1C                      VM_PushReg32  vm_context->0x1C/------------------------------------------------------------------------------------------0042E1A7  LEA ESI,DWORD PTR DS:[ESI-1]              0043B877  SUB ESI,1          0042E1AD  MOVZX EAX,BYTE PTR DS:[ESI]              0043B87D  ROL EAX,CL          0042E1B0  SHR DX,CL                                0043B87F  MOVSX ECX,DX        0042E1B3  MOVZX EDX,BX                             0043B882  MOVZX EAX,BYTE PTR DS:[ESI]0042E1B6  CDQ                                      0043B885  BTC CX,BX            0042E1B7  XOR AL,BL                                0043B889  BTS ECX,EBX0042E1B9  ADD ECX,605116AB                         0043B88C  OR DH,640042E1BF  CMP DH,87                                0043B88F  XOR AL,BL            0042E1C2  ADD AL,19                                0043B891  ADD AL,19            0042E1C4  ROR AL,1                                 0043B893  MOVZX CX,DH          0042E1C6  CMOVNB EDX,ESI                           0043B897  ROR AL,1            0042E1C9  XCHG CX,DX                               0043B899  JMP vmptest_.0045256F0042E1CC  MOV EDX,EBP                              0045256F  INC AL             0042E1CE  INC AL                                   00452571  XOR AL,49            0042E1D0  AND DX,53E2                              00452573  ROR DH,CL0042E1D5  XOR AL,49                                00452575  XOR BL,AL            0042E1D7  BSF CX,BX                                00452577  MOVSX EDX,SP        0042E1DB  SBB ECX,EBP                              0045257A  BTR ECX,ESP          0042E1DD  XOR BL,AL                                0045257D  SUB EDX,1D2A7287    0042E1DF  SAR DX,CL                                00452583  MOV EDX,DWORD PTR SS:[ESP+EAX]0042E1E2  MOV EDX,DWORD PTR SS:[ESP+EA             00452586  NOT ECX              0042E1E5  MOV CL,1A                                00452588  LEA EDI,DWORD PTR DS:[EDI-4] 0042E1E7  RCR CH,CL                                0045258E  MOV DWORD PTR DS:[EDI],EDX0042E1E9  MOVSX ECX,CX                             00452590  SUB ESI,4            0042E1EC  LEA EDI,DWORD PTR DS:[EDI-4]             00452596  DEC CX                0042E1F2  MOV DWORD PTR DS:[EDI],EDX               00452599  JMP vmptest_.00410D3E0042E1F4  XOR CH,0A4                               00410D3E  MOV ECX,DWORD PTR DS:[ESI] 0042E1F7  BTS ECX,EBX                              00410D40  CMC0042E1FA  SUB ESI,4                                00410D41  STC0042E200  MOV ECX,DWORD PTR DS:[ESI]               00410D42  CLC0042E202  STC                                      00410D43  XOR ECX,EBX          0042E203  TEST DH,DH                               00410D45  CMP EDI,ESP0042E205  XOR ECX,EBX                              00410D47  NOT ECX              0042E207  CLC                                      00410D49  CMP DL,0F70042E208  CMC                                      00410D4C  STC0042E209  NOT ECX                                  00410D4D  ADD ECX,1B2352AE      0042E20B  CLC                                      00410D53  BSWAP ECX            0042E20C  ADD ECX,1B2352AE                         00410D55  TEST ESP,4D941F4C0042E212  CMC                                      00410D5B  XOR ECX,26A7DD4      0042E213  CLC                                      00410D61  STC0042E214  BSWAP ECX                                00410D62  XOR EBX,ECX          0042E216  TEST EDI,EDI                             00410D64  CLC0042E218  STC                                      00410D65  CMP BP,11E10042E219  XOR ECX,26A7DD4                          00410D6A  CMC0042E21F  CMP CX,BX                                00410D6B  ADD EBP,ECX          0042E222  XOR EBX,ECX                              00410D6D  JMP vmptest_.0047F0F30042E224  STC                                      0047F0F3  JMP vmptest_.00472E410042E225  TEST ECX,ESI                             00472E41  LEA EDX,DWORD PTR SS:[ESP+60]0042E227  ADD EBP,ECX                              00472E45  TEST DH,AL0042E229  JMP vmptest_.00409E73                    00472E47  CLC00409E73  JMP vmptest_.00472E41                    00472E48  CMP EDI,EDX00472E41  LEA EDX,DWORD PTR SS:[ESP+60]            00472E4A  JMP vmptest_.0046EE8600472E45  TEST DH,AL                               0046EE86  JA vmptest_.00480A0500472E47  CLC                                      00480A05  JMP EBP00472E48  CMP EDI,EDX00472E4A  JMP vmptest_.0046EE860046EE86  JA vmptest_.00480A0500480A05  JMP EBP---------------------------------------------------------------------------------

指令与压哪个寄存器无关,我这里只是恰巧找了两个压了相同VM寄存器的。 你看他们的主要代码是不是一样的, 去混淆一下, 就发现是一模一样的, 解密都一样,不过可能存在乱序(在不影响经结果的情况下), 而每次vmp加壳同一个程序这些同vm指令解密都不一样。去混淆我就不去了, 很简单 1-2min的事情 从vm的环境去提取关键汇编就可以了。不过我相信现在你用肉眼就已经看出来了。那么我们上面分析的东西材料我都放在demo文件夹下了。

六、简单总结一下过程
总结就是 :
1.VM_Entry 进入虚拟机
2.VM_Init 物理环境映射虚拟机
3.VM_Init_bytescode vm的代码解析环境初始化
4.执行VM的代码
5.VM_Destroy 虚拟机环境压栈
6.VM_Exit 物理环境从栈上弹出

在整个过程中我们并没有看到有一个大循环, 心脏去驱动 去取指令, 然后解析指令是吧。 这个就是vmp3与vmp1和vmp2的最大区别,解析bytescode不在由VMDispatcher 分发下一个指令执行什么了(每个指令记为一个handle) 而是有vm_bytescode掌管,执行上一个指令才能得到下一个指令地址 这样一来代码的膨胀可想而知。在VM_Instruct内部应该是没有CALL指令的。

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

标签:

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

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

相关推荐

发表回复

登录后才能评论