VMP1.60分析

Demo指令:mov eax,0x200

主要看与vm1.10版本的虚拟机不同之处:

1、不再是用一个固定地址来保存vm_context,而是将vm_context放在了堆栈上,vm_esp不再直接是esp而是ebp,esp只是用来作混淆作用。

2、每次handler执行中都会对esp进行减不等数值,在handler执行完成后会还原esp到vm_context位置

3、opcode部分也就是vm_eip还是用esi指向,不同之处在于esi不再是递增,还是递减获取opcode

4、vm_start以及vm_ret都不会用pushad和pushfd来一键保存还原寄存器,而是每个寄存器的分别vPush操作。

5、加入了很多垃圾代码来干扰分析。

6、由于vm_eip是倒置的,在取常量时候会用到xchg指令来重置

7、1.60开始VMP就是栈式虚拟机,不再将vm_context放在内存中,而是放在了vm_esp(ebp)的上面,如果ebp将要覆盖到vm_context,比如一些vPushImmxx操作后就会进行vCheckEsp操作,发现快要覆盖就将原来的vm_context复制到更高的栈地址去(-xx)。

具体分析如下,mov这一条指令vm后主要就是由vPushReg32,vPushImm32,vPopReg32,每个handler都只保留了非垃圾指令部分,其实也就只用关注那几个重要的寄存器,eax,ebp,edi,esi这几个寄存器操作的一般都是有效指令,而在每条handler的结尾都会由一条lea esp,[esp+xxx]来恢复esp:

esi = vm_eip
edi = vm_context
ebp = vm_esp

00417600    68 26764100     push    00417626
$ ==>    > 00417626  VMP1_60_.00417626
------------

00416E26    891C24          mov     dword ptr [esp], ebx                  ; push ebx
$-8      > 44444444
$-4      > 0041760A  
$ ==>    > 00417626  
------------

004160C8    894424 04       mov     dword ptr [esp+0x4], eax              ; push eax
$-10     > 00416E2E 
$-C      > 11111111
$-8      > 44444444
$-4      > 0041760A 
$ ==>    > 00417626  
------------

004160CD    877C24 20       xchg    dword ptr [esp+0x20], edi             ; push edi
$-10     > 77777777  
$-C      > 11111111
$-8      > 44444444
$-4      > 0041760A  
$ ==>    > 00417626  VMP1_60_.00417626
------------

004160D5    895C24 1C       mov     dword ptr [esp+0x1C], ebx             ; push ebx
$-14     > 44444444
$-10     > 77777777  
$-C      > 11111111
$-8      > 44444444
$-4      > 0041760A  
$ ==>    > 00417626  
------------

004160DB    9C              pushfd
004160DC    8F4424 10       pop     dword ptr [esp+0x10]                  ; pushfd
$-18     > 00000206
$-14     > 44444444
$-10     > 77777777  
$-C      > 11111111
$-8      > 44444444
$-4      > 0041760A  
$ ==>    > 00417626  
------------

004160E8    894C24 0C       mov     dword ptr [esp+0xC], ecx              ; push ecx
$-1C     > 22222222
$-18     > 00000206
$-14     > 44444444
$-10     > 77777777 
$-C      > 11111111
$-8      > 44444444
$-4      > 0041760A  
$ ==>    > 00417626  
------------

004160F9    896C24 08       mov     dword ptr [esp+0x8], ebp              ; push ebp
$-20     > 55555555
$-1C     > 22222222
$-18     > 00000206
$-14     > 44444444
$-10     > 77777777 
$-C      > 11111111
$-8      > 44444444
$-4      > 0041760A  
$ ==>    > 00417626 
------------

00416105    895424 24       mov     dword ptr [esp+0x24], edx             ; push edx
$-24     > 33333333
$-20     > 55555555
$-1C     > 22222222
$-18     > 00000206
$-14     > 44444444
$-10     > 77777777  
$-C      > 11111111
$-8      > 44444444
$-4      > 0041760A  
$ ==>    > 00417626  
------------

0041610C    877424 20       xchg    dword ptr [esp+0x20], esi             ; push esi
$-28     > 66666666
$-24     > 33333333
$-20     > 55555555
$-1C     > 22222222
$-18     > 00000206
$-14     > 44444444
$-10     > 77777777  
$-C      > 11111111
$-8      > 44444444
$-4      > 0041760A  
$ ==>    > 00417626  
------------

0041741C    C74424 20 00000>mov     dword ptr [esp+0x20], 0x0             ; reloc
$-2C     > 00000000
$-28     > 66666666
$-24     > 33333333
$-20     > 55555555
$-1C     > 22222222
$-18     > 00000206
$-14     > 44444444
$-10     > 77777777  
$-C      > 11111111
$-8      > 44444444
$-4      > 0041760A  
$ ==>    > 00417626  
------------

0041742D    8B7424 6C       mov     esi, dword ptr [esp+0x6C]             ; ;;;;esi = key
------------

00417436    8D6C24 40       lea     ebp, dword ptr [esp+0x40]             ;ebp = 临时寄存器栈顶
------------

00417446    83EC 7C         sub     esp, 0x7C      
0041744D    68 C52A792D     push    0x2D792AC5          ;esp 此时 = 最开始 - 0xF0
00417455    8D7C24 04       lea     edi, dword ptr [esp+0x4]              ; edi = vm_context
//也就是最开始 - 0xEC
------------

00417467    0375 00         add     esi, dword ptr [ebp]                  ; vm重定向--->[ebp]保存reloc地址
------------

---------------vm_loop
00417472    8A46 FF         mov     al, byte ptr [esi-0x1]                ; esi = vm_data , al = opcode,对应vm_handler表中索引
0041747C    4E              dec     esi                                   ;esi = vmv_data,这里倒着增长。
00417485    0FB6C0          movzx   eax, al
00417489    8B0C85 F76E4100 mov     ecx, dword ptr [eax*4+0x416EF7]       ; ;;;;;;ecx = 加密handler地址
00417495    81F1 E4FAC583   xor     ecx, 0x83C5FAE4                       ; Decode_handler地址1
00417361    41              inc     ecx                                   ; Decode_handler地址2
00416490    C1C9 1B         ror     ecx, 0x1B                             ; Decode_handler地址3
00416496    F7D9            neg     ecx                                   ; Decode_handler地址4
00416499    81C1 00000000   add     ecx, 0x0                              ; Decode_handler地址5
00416B82    894C24 30       mov     dword ptr [esp+0x30], ecx             ; ecx = handler地址
00416B8C    9C              pushfd
00416B8D    FF7424 34       push    dword ptr [esp+0x34]                  ; push handler地址
00416B91    C2 3800         retn    0x38

------------vPopReg32
00416DD9    80E0 3C         and     al, 0x3C                              ; 解密操作数
00416DE6    8B55 00         mov     edx, dword ptr [ebp]                  ; 取vm_esp栈顶元素
00416C44    83C5 04         add     ebp, 0x4                              ; vm_esp += 4
004168BD    891407          mov     dword ptr [edi+eax], edx              ; edi = vm_comtext,这里就是vPopReg32 edi[eax]

------------vPushImm32
00416C0F    66:8B46 FE      mov     ax, word ptr [esi-0x2]                ; ax = 00000002
00416C0F    66:8B46 FE      mov     ax, word ptr [esi-0x2]                ; ax = 00000200
00416C25    98              cwde                                          ; ax -> eax = 00000200
00416123    83ED 04         sub     ebp                                   ; vm_esp -= 4
00416541    8945 00         mov     dword ptr [ebp], eax                  ; vPushImm32 0x200
004169C7    8D76 FE         lea     esi, dword ptr [esi-0x2]              ; vm_data -= 2

------------vPushReg32
00416B57    80E0 3C         and     al, 0x3C                              ; 解密操作数
00416B63    8B1407          mov     edx, dword ptr [edi+eax]              ; 获取vm_reg
00416B6F    83ED 04         sub     ebp, 0x4                              ; vm_esp -= 4
00416D17    8955 00         mov     dword ptr [ebp], edx                  ; vPush

------------vRet
004165FC    8B7424 24       mov     esi, dword ptr [esp+0x24]             ; pop esi
00416605    8B5424 28       mov     edx, dword ptr [esp+0x28]             ; pop edx
0041758B    8B6C24 30       mov     ebp, dword ptr [esp+0x30]             ; pop ebp
00417592    8B4C24 34       mov     ecx, dword ptr [esp+0x34]             ; pop ecx
00416C76    FF7424 38       push    dword ptr [esp+0x38]                  ; +0x38 = eflags
00416C7A    9D              popfd                                         ; popfd
00416C7E    8B5C24 38       mov     ebx, dword ptr [esp+0x38]             ; pop ebx
00416C88    8B7C24 3C       mov     edi, dword ptr [esp+0x3C]             ; pop edi
00416941    8B4424 44       mov     eax, dword ptr [esp+0x44]             ; pop eax
00416949    8B5C24 4C       mov     ebx, dword ptr [esp+0x4C]             ; pop ebx
00416951    FF7424 50       push    dword ptr [esp+0x50]                  ; push retAddr
00416955    C2 5400         retn    0x54                                  ; ret



vCheckEsp:

004146E8    8D47 50         lea     eax, dword ptr [edi+0x50]        ; eax = 距离vm_context0x50地址处

004146F7    39C5            cmp     ebp, eax                         ; vm_esp和vm_context + 0x50比较

004146FE    8D6424 24       lea     esp, dword ptr [esp+0x24]        ; 恢复esp为vm_context栈顶

00414702   /0F87 74060000   ja      <vm_loop>                        ; if( vm_esp > vm_context + 0x50 )

0041470A    89E2            mov     edx, esp                         ; edx = 现在的vm_context

00415A58    8D4F 40         lea     ecx, dword ptr [edi+0x40]        ; ecx = vm_context + 0x40

00415A64    29D1            sub     ecx, edx                         ; ecx = vm_context + 0x40 - vm_context = 0x40
								     ; ecx = 0x40作为后面rep复制的长度
00415A71    8D45 80         lea     eax, dword ptr [ebp-0x80]        ; eax = vm_esp - 0x80

00415A7A    29C8            sub     eax, ecx                         ; vm_esp - 0x80 - 0x40 = vm_esp - 0x120

00415A83    89C4            mov     esp, eax                         ; ;

00415AA2    897424 18       mov     dword ptr [esp+0x18], esi        ; 保存vm_eip $-C8     > 00415B48

004140D1    89D6            mov     esi, edx                         ; esi = vm_context

004140D7    8D7C08 C0       lea     edi, dword ptr [eax+ecx-0x40]    ; edi = eax+ecx-0x40 = eax = 新vm_context地址

004149D9    877C24 18       xchg    dword ptr [esp+0x18], edi	     ; 保存新的vm_context地址

00414BD0    8D6424 18       lea     esp, dword ptr [esp+0x18]        ; 抬高栈顶

00414BE1    89C7            mov     edi, eax                         ; 恢复edi = 新vm_context地址

00414BE4    FC              cld                                      ; df = 0 ,每次复制向下递增esi和edi

00414620    F3:A4           repmovs byte ptr es:[edi], byte ptr [esi]; 复制vm_context的0x40部分到抬高的栈位置

00414629    8B7C24 2C       mov     edi, dword ptr [esp+0x2C]	     ; 更新vm_context

0041462E    8B7424 30       mov     esi, dword ptr [esp+0x30]  	     ; 还原vm_eip

00414651    8D6424 40       lea     esp, dword ptr [esp+0x40]        ; 恢复栈顶

00414655   /E9 22070000     jmp     <vm_loop>


vCheckEsp:
vm_esp与接近vm_context的部分比较,如果快要接近到vm_context,就将vm_context内容复制到更高的栈上去(-x地址),然后还原
edi为新的vm_context,再把vm_eip还原。

猜你喜欢

转载自blog.csdn.net/a893574301/article/details/82823584