彩票走势图

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

转帖|使用教程|编辑:杨鹏连|2021-06-22 10:00:51.233|阅读 373 次

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

# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>

VMProtect是一种很可靠的工具,可以保护应用程序代码免受分析和破解,但只有在应用程序内保护机制正确构建且没有可能破坏整个保护的严重错误的情况下,才能实现最好的效果。

VMProtect通过在具有非标准体系结构的虚拟机上执行代码来保护代码,这将使分析和破解软件变得十分困难。除此之外,VMProtect还可以生成和验证序列号,限制免费升级等等。

下载VMProtect最新试用版

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

相关链接:

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

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

三、详细分析

我们先分析一下头和尾,那我们怎么知道哪里才是一个VM指令的开始和结束呢?记得jmp reg 和 push + ret 没,我们就由这两个去确定一个VM指令的范围

  • A、分析一下VM进入的操作
VM_Entry
----------------------------------------------------------------
0044A580 Main     PUSH 83819110                             ; Key 你可以看做一个密文经过解密    压栈1  Key
0044A585 Main     CALL vmptest_.0042FA52                    ; Key 经过解密后就是bytescode 压找2  压返回地址
0042FA52 Main     PUSH EDX                                  ; 压栈3  EDX
0042FA53 Main     JMP vmptest_.0042BF92
0042BF92 Main     PUSHFD                                    ; 压栈4  eflags符号寄存器
0042BF93 Main     TEST CX,SI
0042BF96 Main     CMC
0042BF97 Main     PUSH ECX                                  ; 压栈5  ECX
0042BF98 Main     SHLD CX,SI,0BA
0042BF9D Main     ADD CL,97                                 ; ECX=00000097
0042BFA0 Main     PUSH EBX                                 ;  压栈6  EBX
0042BFA1 Main     MOV CL,DL                                 ; ECX=00000008
0042BFA3 Main     SHR EBX,CL                                ; EBX=007FFDF0
0042BFA5 Main     PUSH EBP                                 ; 压栈7  EBP
0042BFA6 Main     PUSH ESI                                  ; 压栈8  ESI
0042BFA7 Main     PUSH EAX                                 ; 压栈9  EAX
0042BFA8 Main     PUSH EDI                                  ; 压栈10 EDI
0042BFA9 Main     ADD ECX,173475C8                          ; ECX=173475D0
0042BFAF Main     MOV EAX,0
0042BFB4 Main     XOR ESI,239C226E                          ; ESI=239C226E
0042BFBA Main     PUSH EAX                                  ; 压栈11 0x00000000
0042BFBB Main     SETLE BH                                  ; EBX=007F00F0
0042BFBE Main     MOV ESI,DWORD PTR SS:[ESP+28]             ; ESI=83819110   取ESP+0x28地址的值 0x28/4= 10 往上数第10个
0042BFC2 Main     LEA ESI,DWORD PTR DS:[ESI+D093E2F1]       ; ESI=54157401   从0开始数 你看看是不是取到了Key的值 注意
0042BFC8 Main     NEG ESI                                   ; ESI=ABEA8BFF   注意这个 [ESP + 0x28]这个特征 现在赋值给ESI
0042BFCA Main     BTS BP,BX                                 ; EBP=0012FF95
0042BFCE Main     JMP vmptest_.00430A03
00430A03 Main     ROR ESI,1                                 ; ESI=D5F545FF
00430A05 Main     INC ESI                                   ; ESI=D5F54600
00430A06 Main     ADD EBP,64941F8C                          ; EBP=64A71F21
00430A0C Main     ADC CX,SP                                 ; ECX=17347530
00430A0F Main     BTR EDI,73
00430A13 Main     BSWAP ESI                                 ; ESI=0046F5D5
00430A15 Main     CMOVPE EBX,ESI                            ; EBX=0046F5D5
00430A18 Main     BTC BP,8C                                 ; EBP=64A70F21
00430A1D Main     ADD ESI,EAX
00430A1F Main     MOV EBP,ESP                               ; EBP=0012FF60  ;注意这里EBP的赋值 记住这里现在ebp是上面压的栈顶
00430A21 Main     SUB ESP,0C0                              ; 和这里esp的开栈 其实这里是给vm_context开空间
00430A27 Main     MOV EBX,ESI                                               ;和给vm_ss开空间
00430A29 Main     MOV ECX,0                                 ; ECX=00000000  ;注意这里有个mov ebx,esi 解密因子 我接下来就不
00430A2E Main     OR EDI,EBP                                ; EDI=0012FF60  ;会去多提他 如果你要运行程序你就要注意他 这个解密因子 往上看是不是Key解密而来的
00430A30 Main     SUB EBX,ECX                             ;分析好几个vm 分析ebx一直指向这个vm_decryptfactor
00430A32 Main     ROL CX,CL                                 ;我不知道这样叫他对不对 不过这不是重点
00430A35 Main     LEA EDI,DWORD PTR DS:[430A35]             ; EDI=00430A35  ;知道他是干什么的就可以了
00430A3B Main     SUB CX,SI                                 ; ECX=00000A2B ;看到这里的LEA 本身这个指令上一个地址 没错他就是vm_JumpBase 相对谁去跳到下一个地址 肯定是当前
00430A3E Main     OR CL,0D5                                 ; ECX=00000AFF
00430A41 Main     ROL CX,23                                 ; ECX=000057F8
00430A45 Main     MOV ECX,DWORD PTR DS:[ESI]                ; ECX=B0D37F60 ;到这里 经过解密之后ESI才是真正的vm_bytescode
00430A47 Main     ADD ESI,4                                 ; ESI=0046F5D9 ;你或者叫他(ESI)为跳转间隔 好像也没什么错
00430A4D Main     TEST EDI,EBX                              ; 取值后 ESI +=4 往后移
00430A4F Main     XOR ECX,EBX                               ; ECX=B0958AB5
00430A51 Main     JMP vmptest_.00439FEC
00439FEC Main     LEA ECX,DWORD PTR DS:[ECX+DEFE95D9]       ; ECX=8F94208E
00439FF2 Main     CMP AX,25AD
00439FF6 Main     TEST BH,90
00439FF9 Main     NOT ECX                                   ; ECX=706BDF71
00439FFB Main     TEST AL,DL
00439FFD Main     CMC
00439FFE Main     CMP SP,7CB8
0043A003 Main     NEG ECX                                   ; ECX=8F94208F
0043A005 Main     LEA ECX,DWORD PTR DS:[ECX+A504E271]       ; ECX=34990300
0043A00B Main     JMP vmptest_.00416562
00416562 Main     BSWAP ECX                                 ; ECX=00039934
00416564 Main     XOR EBX,ECX                               ; EBX=00456CE1
00416566 Main     CMP SI,130B
0041656B Main     ADD EDI,ECX                               ; EDI=0046A369 ;上面说到了取bytescode链上的值
0041656D Main     JMP vmptest_.0045F2B5                     ; 经过解密后 与JumpBase相加得到下一个指令的地址
0045F2B5 Main     PUSH EDI                                 ; 然后把这个地址压栈 RET反弹给物理机EIP
0045F2B6 Main     RETN                                     ;或者这里你可能也会遇到jmp edi 他们是一样的功能

上面这个我们没有去混淆,我们直接分析了。那么肯定是有技巧的是吧,从上往下看,push 和pushfd肯定要保留,这个是重要的,然后从下往上分析,EDI是重要的,然后看到谁影响了EDI一直这样往上找去,有关的提取出来。另外关于ESP寄存器的要保留下来,主要是ESP减0xC0这个开VM栈空间和VM_REG空间,还有ESP在减0xC0之前把值给了谁,谁就是VM_ESP即vm栈顶(栈底),当然给的这个寄存器不在传递给其他寄存器的话才行,但目前我并没有遇到还在传递的情况。我们是看了开始,我们在看看紧跟着的VM指令:

VM_PopReg32  vm_context->0x10
---------------------------------------------------------------------------------------------
0046A369 Main     MOV EAX,DWORD PTR SS:[EBP]                ;返回上面看看我们说EBP是上面压的物理环境的栈顶
0046A36D Main     STC                                                       ;
0046A36E Main     ROR DL,CL                                 ; EDX=00401080
0046A370 Main     LEA EBP,DWORD PTR SS:[EBP+4]              ; EBP=0012FF64 ;这里EBP = EBP + 4 栈回缩是不 那不就是出栈的意思
0046A376 Main     MOVZX EDX,BYTE PTR DS:[ESI]               ; EDX=0000008D ;注意这种取1byte的指令类似这个
0046A379 Main     CMP CX,BP
0046A37C Main     ADD ESI,1                                 ; ESI=0046F5DA ;ESI+1  刚刚说了esi是bytescode 他也保存了寄存器
0046A382 Main     CMP CX,4F65                                              ;编号  我们不是之前叫他跳转间隔吗 噢见鬼了
0046A387 Main     CMP ECX,EBX                                              ;反正我们知道他有这样的能力就可以  这里ESI+=1
0046A389 Main     XOR DL,BL                                 ; EDX=0000006C ;有可能他不是正向走 可能是-1 那上面的也对应-4
0046A38B Main     TEST DI,5D07                                             ;这没什么好争论的不是吗  具体看汇编就出来了
0046A390 Main     STC                                                      ;为什么会这么说 是以为我之前有遇到是反向增长
0046A391 Main     NOT DL                                    ; EDX=00000093 ;看到上面的 xor dl,bl  记得我说的EBX是解密因子了没
0046A393 Main     CMP DI,2768
0046A398 Main     JMP vmptest_.0043EDAF
0043EDAF Main     SUB DL,8B                                 ; EDX=00000008
0043EDB2 Main     CMC
0043EDB3 Main     ROR DL,1                                  ; EDX=00000004
0043EDB5 Main     DEC DL                                    ; EDX=00000003
0043EDB7 Main     JMP vmptest_.00413DC1
00413DC1 Main     NOT DL                                    ; EDX=000000FC
00413DC3 Main     CMP SP,6B29
00413DC8 Main     JMP vmptest_.00416D48
00416D48 Main     ADD DL,14                                 ; EDX=00000010
00416D4B Main     STC
00416D4C Main     XOR BL,DL                                 ; EBX=00456CF1;而这里我们主要关心EDX的值不是吗 这里是0x10
00416D4E Main     MOV DWORD PTR SS:[ESP+EDX],EAX            ; 发现EDX是从上面去esi地址1byte值经过变化而来的
00416D51 Main     AND DH,0F7                                ; 而我们之前说的什么ESP指向的是vm_context是吧
00416D54 Main     NEG DX                                    ; EDX=0000FFF0;在结合我们上面的分析 这应该是一个出栈的操作
00416D57 Main     MOV EDX,DWORD PTR DS:[ESI]                ; EDX=E45184BF;在次取ESI (bytescode)的值 关键 这个是跳转间隔密文
00416D59 Main     CMP ESI,EDI
00416D5B Main     CMC
00416D5C Main     JMP vmptest_.00419F08
00419F08 Main     ADD ESI,4                                 ; ESI=0046F5DE;ESI += 4
00419F0E Main     STC
00419F0F Main     XOR EDX,EBX                               ; EDX=E414E84E
00419F11 Main     TEST DH,36
00419F14 Main     XOR EDX,29474E33                          ; EDX=CD53A67D
00419F1A Main     TEST ESP,EDX
00419F1C Main     ADD EDX,64682765                          ; EDX=31BBCDE2
00419F22 Main     JMP vmptest_.00472890
00472890 Main     NEG EDX                                   ; EDX=CE44321E
00472892 Main     TEST SI,BX
00472895 Main     STC
00472896 Main     ADD EDX,44017C67                          ; EDX=1245AE85
0047289C Main     JMP vmptest_.00463068
00463068 Main     ROR EDX,1                                 ; EDX=8922D742
0046306A Main     CMP CX,DI
0046306D Main     STC
0046306E Main     CMP DI,358A
00463073 Main     NEG EDX                                   ; EDX=76DD28BE
00463075 Main     JMP vmptest_.0047F903
0047F903 Main     BSWAP EDX                                 ; EDX=BE28DD76
0047F905 Main     INC EDX                                   ; EDX=BE28DD77
0047F906 Main     STC
0047F907 Main     XOR EDX,41D507D0                          ; EDX=FFFDDAA7
0047F90D Main     XOR EBX,EDX                               ; EBX=FFB8B656;注意这里解密因子 ebx 改变 每一个vm指令都有这个
0047F90F Main     CMP SP,BP
0047F912 Main     TEST EDX,29E10AB5                         ;解密因子的参与  接下来我就不多提他了 记得每个指令都有
0047F918 Main     STC                                     ;而且每运行一个vm指令 他都会变
0047F919 Main     ADD EDI,EDX                             ; EDI=00447E10;跳转间隔经过解密后 与JumpBase相加
0047F91B Main     JMP vmptest_.00420B9F
00420B9F Main     PUSH EDI
00420BA0 Main     RETN                                      ;跳转到下一条指令地址
-------------------------------------------------------------------------------------------------
然后针对VM指令非入口和出口的分析,也有方法,当然可能这些方法这是适用我们当前遇到的指令(即目前这个demo)。看到第一条指令是取VM_ESP位置的uint32_t值 ,然后VM_ESP回缩4byte,第一反应就是这个应该是pop操作,在往下看看,能不能看到MOV [ESP + REG1],REG2 这个样子的汇编,OK能找到,那么明显就是栈中弹数据到VM_REG中了。在往下看是取VM_Bytescode中的值然后解密与VM_JumpBase相加。无疑是VM_PopReg32了,但是那个寄存器呢?看到
00416D4E Main     MOV DWORD PTR SS:[ESP+EDX],EAX            ;往上看到EDX的值 看右边的追踪结果 EDX=0x10
所以我们这里应该翻译为VM_PopReg32 vm_context->0x10 或者 VM_PopReg32 DwReg4 (0x10/4=4) 可能名字和别人不一样,差不多就是这个意思。注意看看这个EDX的值也是从VM_Bytescode中得到解密出来的。然后紧跟着的几条重要的VM指令我就不一一分析了,和上面是同理的,我直接贴分析出的VM指令
[---------VM_Init--------]  这里我们可以又把这几条vm指令解释为VM_Init 主要是把物理环境反弹到虚拟机里面
/----------------------------------------------------------------------
VM_PopReg32  vm_context->0x10   0x00000000
 
VM_PopReg32  vm_context->0x2C  
 
VM_PopReg32  vm_context->0x18
 
VM_PopReg32  vm_context->0x28
 
VM_PopReg32  vm_context->0x20   0x0012FF94
 
VM_PopReg32  vm_context->0x08   0x7FFDF000
 
VM_PopReg32  vm_context->0x24   0x00000000
 
VM_PopReg32  vm_context->0x3C   0x00000246
 
VM_PopReg32  vm_context->0x30   0x00401008
 
VM_PopReg32  vm_context->0x14   0x0044A58A           那我们很早之前说的上面压栈是保存物理机环境就不太对了
 
VM_PopReg32  vm_context->0x0C   0x83819110           应该说是 物理机环境映射到虚拟机的一个过渡
\-------------------------------------------------------------------------
把物理环境弹入VM寄存器环境后,重新调整vm_bytescode的指向和之前的VM_REG乱序,就比如上面这个vm_context->0x14是push + call 中call的下一个地址 ,经过调整后vm_context->0x14也就不是这个地址了(这个地址并不是退出VM后仅跟着的执行真实汇编的地址),再比如EBP是vm_bytescode,变换后EBP可能就不是了,可能是EBX或者EAX等。我就不贴代码了,之后会有整理。
  • B、分析一下VM退出的操作
VM_Exit
/------------------------------------------------------------------------------
0047A839 Main     MOV ESP,EDI                               ;虚拟机栈给物理机esp栈 没错了这里应该是要
0047A83B Main     OR AX,CX                                  ; EAX=0000EFEA;返回物理机了
0047A83E Main     POP ECX                                   ; ECX=00000000;弹栈  ECX
0047A83F Main     ROR DX,CL                                 ;看到这么多pop 看来是真的要还原到物理机了
0047A842 Main     CMP DH,DL                                 ;在看看我们的进度条 也到底了 终于分析完了
0047A844 Main     POP EBP                                   ; EBP=0012FF94;弹栈  EBP
0047A845 Main     POP EAX                                   ; EAX=00004545;弹栈  EAX
0047A846 Main     POP EBX                                   ; EBX=7FFDF000;弹栈  EBX
0047A847 Main     OR DI,73E7                                ; EDI=0012FFEF
0047A84C Main     ADC DI,6287                               ; EDI=00126276
0047A851 Main     CMOVO SI,DI
0047A855 Main     POP EDI                                   ; EDI=00000000;弹栈  EDI
0047A856 Main     CWD                                       ; EDX=00120000
0047A858 Main     POPFD                                                   ;弹栈  EFLAGS  符号寄存器
0047A859 Main     POP ESI                                   ; ESI=00000000;弹栈  ESI
0047A85A Main     POP EDX                                   ; EDX=00401008;弹栈  EDX
0047A85B Main     RETN                                                    ;返回物理机
    Breakpoint at vmptest_.00401040
 
00401040 Main     PUSH EAX                                  ; <%04X> = 4545 返回物理机第一条汇编
    Run trace closed
我们可以看到ESP寄存器的值被EDI赋值了,然后从栈中弹出值到物理机(真实环境)的寄存器中。那么这个EDI应该是被安排了真实环境的值,很可能他就是VM_ESP是吧。我们在往上分析一下看看,我直接贴关键的VM指令

[---------VM_Destroy----------] 下面的这几句你可以各类为新的vm指令 他其实就是准备退出虚拟机时把 处理后的物理环境压栈
/----------------------------------------------------------------------------------------
VM_PushImm32 0x00401040        retAddr
 
VM_PushReg32 vm_context->0x14  0x00401008
 
VM_PushReg32 vm_context->0x30  0x00000000
 
VM_PushReg32 vm_context->0x18  0x00000202
 
VM_PushReg32 vm_context->0x24  0x00000000
 
VM_PushReg32 vm_context->0x04  0x7FFDF000
 
VM_PushReg32 vm_context->0x10  0x00004545  我们要的最终值
 
VM_PushReg32 vm_context->0x3C  0x0012FF94
 
VM_PushReg32 vm_context->0x28  0x00000000
\-------------------------------------------------------------------------------------------
这里我就不展示EDI是VM_ESP了,我可以告诉你他是的。看看这个返回地址他是由VM_Bytescode中得到的,还记得我们VM_Entry进来时压的那个push + call 中 call指令后面的地址吗,不是返回仅跟着CALL后面地址的位置,所以我们往往在那个地方下断点就没作用。

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


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@pclwef.cn

文章转载自:

为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP