wai1216 发表于 2018-3-26 13:55:13

谈谈vmp的还原(2)

0x00 前言
写之前就在想该以一个怎样的方式阐述这些东西,最终还是决定以逆推的方式来描述
另外 先回答下问题 分析的是vmp的主程序,很早的版本

0x01 虚拟化后

测试的指令

68 34504200      PUSH OFFSET zf.??_C@_02MECO@?$CFd?$AA@   ; /format = "%d"
E8 13010000      CALL zf.scanf                            ; \scanf
83C4 08          ADD ESP,0x8
817D FC 33020000 CMP DWORD PTR SS:,0x233
75 09            JNZ SHORT zf.00401062

被用来vm的两条指令:

817DFC33020000          cmp dword ptr ,00000233
7509                  jnz 00401062

先看看是cmp被vm之后的情况,因为既然大S提到了这个,看了他的帖子,所以叫他大S


1.lodsd -0x233
push -0x233
   
stack_top   fffffdcd
   
2.lodsb
push _context <===> push ebp
   
stack_top   ebp
      fffffdcd

3.lodsb
push disp
   
stack_top   disp
      ebp
      fffffdcd

4.pop disp
add ebp,dis <===> get addr input

stack_top   ebp+disp
      fffffdcd
   
5.pop addr (input)
push input

stack_top   input
      fffffdcd

6.pop input
add [-0x233],input ... get a
   
stack_top   fffffe48
   
pushfw
   
stack_top   fe480296

7.push eflags
stack_top    02960216
             00fffffe48

8.push stack
stack_top   ebp
      02960216
      fffffe48

9.pop stack
push
   
stack_top   02160216
      fe480296

10.and(not(eflags),not(eflags))
stack_top   fde9fde9

stack_top   0296fde9
      fffffe48

11.lodsw ~0x400
    push ~0x400
   
stack_top   FDE9FBFF
      FE480296
   
11.and(not(eflags),not(~0x400)) = and(eflags,0x400)
stack_top   02160400

stack_top   02960000
      fffffe48

12.pop result
   add ,result
   
stack_top   fe480296 <==> 0296+result
   
13.lodsb
   pop _context

_context == 0296
stack_top   fffffe48

14.pop a

eax == a <==> fffffe48
stack_top ebp

15.push lodsw
   push 0x11
   
stack_top   FF48FFEE
            0018

16.push
stack_top   FFEE0296
            0018FF48
17.push
stack_top   02960296
      FF48FFEE
      00000018

18.and(not(pushfw),not(pushfw))
stack_top   FD69FD69
      FF48FFEE
      00000018
            
stack_top   FFEEFD69
      0018FF48

19.and(0x11,pushfw)
stack_top   FF480010 <==> and(0x11,0x269)
                0018


20.push pushfw
stack_top   00100296
      0018FF48

21.lodb push 0x11
stack_top    02960011
             FF480010
               0018


22.and(not(pushfw),not(0x11))
stack_top       0010FD68
      0018FF48

23.and(not(result),not(0x11))
stack_top       FF480287
            0018

24.lodb
   push _context <===> push
   
stack_top       02870296
      0018FF48
            
24.lodb
   push _context <===> push
   
stack_top       02960296
      FF480287
            0018

25.and(296,296)

stack_top       0287FD69
      0018FF48

26.lodw ~0x400
    push ~0x400
   
stack_top       FD69FBFF
                FF480287
      0018
               
27.and(0x400,0x296)

stack_top   02870000
      0018FF48

28.pop result
   add ,result
   
stack_top   FF480287
      00000018
            
29.lodsb
   pop _context <==> result save to context
   
stack_top   0018FF48

28.lodsb
   push _context
   
stack_top   00000000
                0018FF48

以上就是cmp的vm流程

hex如下

0042FB216C CD FD CF 05 38 FC 69
0042FB29C4 C1 B6 08 0C 8E 99 57
0042FB31FF FB 99 3B 5D 08 08 57
0042FB39EE FF B6 08 FA 08 99 99
0042FB41E9 08 A0 11 99 99 B6 08
0042FB49B6 08 99 57 FF FB 99 3B
0042FB515D 08 18 0C


0x10 原由

那么我们先来看看是如何得到这些hex


代码很简单
匹配就行了,那么我们来看看匹配表,注意到上一篇的handle_size == 1488 / 8


恩,vmp实现虚拟引擎的核心可以说就是这些虚拟规则。注意到我是用的这些,而不是186个,因为在写之前,我担心版本太老,所以又去逆了逆v2.12.3,发现框架太体差不多,不过代码量优化了很多。还有昨天看了看大Z哥的帖子,对里面有句话感触很深(它们的价值来自于本身的神秘面纱)。但毕竟吧,vmp也3.x,代码重构了,我想也可以谈一谈了。扯远了。
查看引用表的地方


在看看RandIndexArray的引用,来到这个地方


注意到这里可能是乱序之后的,那么如果说不乱序的话,这个表和vm_opcode的应该是一一对应的关系
举例:


定位到handler_table,
则有

Handle_471094:
LODS BYTE PTR DS:
PUSH DWORD PTR DS:
对应
01 02 02 00 00 00 00 00


如下:


struct _vmp_esi_table _esi_table[] = {
    {0x1,0x2,0x2,0x0,0x0,0x0,0x0,0x0,"LODS BYTE PTR DS: PUSH DWORD PTR DS:" }
    ,{0x1,0x1,0x2,0x0,0x0,0x0,0x0,0x0,"LODS DWORD PTR DS: PUSH EAX" }
    ,{0x1,0x2,0x2,0x0,0x1,0x0,0x0,0x0,"PUSH ESP" }
    ,{0x1,0x3,0x2,0x0,0x0,0x0,0x0,0x0,"POP EAX PUSH DWORD PTR ES:" }
    ,{0x1,0x3,0x2,0x0,0x1,0x0,0x0,0x0,"POP EAX PUSH DWORD PTR CS:" }
    ,{0x1,0x3,0x2,0x0,0x2,0x0,0x0,0x0,"POP EAX PUSH DWORD PTR SS:" }
    ,{0x1,0x3,0x2,0x0,0x3,0x0,0x0,0x0,"POP EAX PUSH DWORD PTR DS:" }
    ,{0x1,0x3,0x2,0x0,0x4,0x0,0x0,0x0,"POP EAX PUSH DWORD PTR FS:" }
    ,{0x1,0x3,0x2,0x0,0x5,0x0,0x0,0x0,"POP EAX PUSH DWORD PTR GS:" }
    ,{0x1,0x2,0x1,0x0,0x0,0x0,0x0,0x0,"LODS BYTE PTR DS: PUSH WORD PTR DS:" }
    ,{0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,"LODS WORD PTR DS: ADD AX,BX ADD BX,AX PUSH AX"}
    ,{0x1,0x1,0x1,0x0,0x1,0x0,0x0,0x0,"LODS WORD PTR DS: ADD AX,BX ADD BX,AX CWDE PUSH EAX"}
    ,{0x1,0x3,0x1,0x0,0x0,0x0,0x0,0x0,"POP EDX PUSH WORD PTR ES:" }
    ,{0x1,0x3,0x1,0x0,0x1,0x0,0x0,0x0,"POP EDX PUSH WORD PTR CS:" }
    ,{0x1,0x3,0x1,0x0,0x2,0x0,0x0,0x0,"POP EDX PUSH WORD PTR SS:" }
    ,{0x1,0x3,0x1,0x0,0x3,0x0,0x0,0x0,"POP EDX PUSH WORD PTR DS:" }
    ,{0x1,0x3,0x1,0x0,0x4,0x0,0x0,0x0,"POP EDX PUSH WORD PTR FS:" }
    ,{0x1,0x3,0x1,0x0,0x5,0x0,0x0,0x0,"POP EDX PUSH WORD PTR GS:" }
    ,{0x1,0x2,0x0,0x0,0x0,0x0,0x0,0x0,"LODS BYTE PTR DS: ADD AL,BL ADD BL,AL MOV AL,BYTE PTR DS: PUSH AX"}
    ,{0x1,0x2,0x0,0x0,0x1,0x0,0x0,0x0,"LODS BYTE PTR DS: ADD AL,BL ADD BL,AL MOV AL,BYTE PTR DS: PUSH AX"}
    ,{0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,"LODS BYTE PTR DS: ADD AL,BL ADD BL,AL PUSH AX"}
    ,{0x1,0x1,0x0,0x0,0x1,0x0,0x0,0x0,"LODS BYTE PTR DS: ADD AL,BL ADD BL,AL CBW CWDE PUSH EAX"}
    ,{0x1,0x3,0x0,0x0,0x0,0x0,0x0,0x0,"POP EAX MOV AL,BYTE PTR ES: PUSH AX"}
    ,{0x1,0x3,0x0,0x0,0x1,0x0,0x0,0x0,"POP EAX MOV AL,BYTE PTR CS: PUSH AX"}
    ,{0x1,0x3,0x0,0x0,0x2,0x0,0x0,0x0,"POP EAX MOV AL,BYTE PTR SS: PUSH AX"}
    ,{0x1,0x3,0x0,0x0,0x3,0x0,0x0,0x0,"POP EAX MOV AL,BYTE PTR DS: PUSH AX"}
    ,{0x1,0x3,0x0,0x0,0x4,0x0,0x0,0x0,"POP EAX MOV AL,BYTE PTR FS: PUSH AX"}
    ,{0x1,0x3,0x0,0x0,0x5,0x0,0x0,0x0,"POP EAX MOV AL,BYTE PTR GS: PUSH AX"}
    ,{0x1,0x5,0x1,0x0,0x0,0x0,0x0,0x0,"PUSH ES" }
    ,{0x1,0x5,0x1,0x0,0x1,0x0,0x0,0x0,"PUSH CS" }
    ,{0x1,0x5,0x1,0x0,0x2,0x0,0x0,0x0,"PUSH SS" }
    ,{0x1,0x5,0x1,0x0,0x3,0x0,0x0,0x0,"PUSH DS" }
    ,{0x1,0x5,0x1,0x0,0x4,0x0,0x0,0x0,"PUSH FS" }
    ,{0x1,0x5,0x1,0x0,0x5,0x0,0x0,0x0,"PUSH GS" }
    ,{0x1,0x2,0x1,0x0,0x1,0x0,0x0,0x0,"PUSH SP" }
    ,{0x2,0x2,0x2,0x0,0x0,0x0,0x0,0x0,"LODS BYTE PTR DS: ADD AL,BL ADD BL,AL POP DWORD PTR DS:"}
    ,{0x2,0x1,0x2,0x0,0x0,0x0,0x0,0x0,"POP EAX"}
    ,{0x2,0x2,0x2,0x0,0x1,0x0,0x0,0x0,"POP ESP"}
    ,{0x2,0x3,0x2,0x0,0x0,0x0,0x0,0x0,"POP EAX POP DWORD PTR ES:"}
    ,{0x2,0x3,0x2,0x0,0x1,0x0,0x0,0x0,"POP EAX POP DWORD PTR CS:"}
    ,{0x2,0x3,0x2,0x0,0x2,0x0,0x0,0x0,"POP EAX POP DWORD PTR SS:" }
    ,{0x2,0x3,0x2,0x0,0x3,0x0,0x0,0x0,"POP EAX POP DWORD PTR DS:" }
    ,{0x2,0x3,0x2,0x0,0x4,0x0,0x0,0x0,"POP EAX POP DWORD PTR FS:" }
    ,{0x2,0x3,0x2,0x0,0x5,0x0,0x0,0x0,"POP EAX POP DWORD PTR GS:" }
    ,{0x2,0x2,0x1,0x0,0x0,0x0,0x0,0x0,"LODS BYTE PTR DS: POP WORD PTR DS:" }
    ,{0x2,0x1,0x1,0x0,0x0,0x0,0x0,0x0,"POP AX" }
    ,{0x2,0x3,0x1,0x0,0x0,0x0,0x0,0x0,"POP EAX POP WORD PTR ES:" }
    ,{0x2,0x3,0x1,0x0,0x1,0x0,0x0,0x0,"POP EAX POP WORD PTR CS:" }
    ,{0x2,0x3,0x1,0x0,0x2,0x0,0x0,0x0,"POP EAX POP WORD PTR SS:" }
    ,{0x2,0x3,0x1,0x0,0x3,0x0,0x0,0x0,"POP EAX POP WORD PTR DS:" }
    ,{0x2,0x3,0x1,0x0,0x4,0x0,0x0,0x0,"POP EAX POP WORD PTR FS:" }
    ,{0x2,0x3,0x1,0x0,0x5,0x0,0x0,0x0,"POP EAX POP WORD PTR GS:" }
    ,{0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,"POP DX LODS BYTE PTR DS: ADD AL,BL ADD BL,AL MOV BYTE PTR DS:,DL"}
    ,{0x2,0x2,0x0,0x0,0x1,0x0,0x0,0x0,"POP DX LODS BYTE PTR DS: ADD AL,BL ADD BL,AL MOV BYTE PTR DS:,DL"}
    ,{0x1,0x6,0x2,0x0,0x0,0x0,0x0,0x0,"MOV EAX,CR0 PUSH EAX"}
    ,{0x1,0x6,0x2,0x0,0x1,0x0,0x0,0x0,"MOV EAX,CR1 PUSH EAX"}
    ,{0x1,0x6,0x2,0x0,0x2,0x0,0x0,0x0,"MOV EAX,CR2 PUSH EAX"}
    ,{0x1,0x6,0x2,0x0,0x3,0x0,0x0,0x0,"MOV EAX,CR3 PUSH EAX"}
    ,{0x1,0x6,0x2,0x0,0x4,0x0,0x0,0x0,"MOV EAX,CR4 PUSH EAX"}
    ,{0x1,0x6,0x2,0x0,0x5,0x0,0x0,0x0,"MOV EAX,CR5 PUSH EAX"}
    ,{0x1,0x6,0x2,0x0,0x6,0x0,0x0,0x0,"MOV EAX,CR6 PUSH EAX"}
    ,{0x1,0x6,0x2,0x0,0x7,0x0,0x0,0x0,"MOV EAX,CR7 PUSH EAX"}
    ,{0x2,0x6,0x2,0x0,0x0,0x0,0x0,0x0,"POP EAX MOV CR0,EAX"}
    ,{0x2,0x6,0x2,0x0,0x1,0x0,0x0,0x0,"POP EAX MOV CR1,EAX"}
    ,{0x2,0x6,0x2,0x0,0x2,0x0,0x0,0x0,"POP EAX MOV CR2,EAX"}
    ,{0x2,0x6,0x2,0x0,0x3,0x0,0x0,0x0,"POP EAX MOV CR3,EAX"}
    ,{0x2,0x6,0x2,0x0,0x4,0x0,0x0,0x0,"POP EAX MOV CR4,EAX"}
    ,{0x2,0x6,0x2,0x0,0x5,0x0,0x0,0x0,"POP EAX MOV CR5,EAX"}
    ,{0x2,0x6,0x2,0x0,0x6,0x0,0x0,0x0,"POP EAX MOV CR6,EAX"}
    ,{0x2,0x6,0x2,0x0,0x7,0x0,0x0,0x0,"POP EAX MOV CR7,EAX"}
    ,{0x1,0x7,0x2,0x0,0x0,0x0,0x0,0x0,"MOV EAX,DR0 PUSH EAX"}
    ,{0x1,0x7,0x2,0x0,0x1,0x0,0x0,0x0,"MOV EAX,DR1 PUSH EAX"}
    ,{0x1,0x7,0x2,0x0,0x2,0x0,0x0,0x0,"MOV EAX,DR2 PUSH EAX"}
    ,{0x1,0x7,0x2,0x0,0x3,0x0,0x0,0x0,"MOV EAX,DR3 PUSH EAX"}
    ,{0x1,0x7,0x2,0x0,0x4,0x0,0x0,0x0,"MOV EAX,DR4 PUSH EAX"}
    ,{0x1,0x7,0x2,0x0,0x5,0x0,0x0,0x0,"MOV EAX,DR5 PUSH EAX"}
    ,{0x1,0x7,0x2,0x0,0x6,0x0,0x0,0x0,"MOV EAX,DR6 PUSH EAX"}
    ,{0x1,0x7,0x2,0x0,0x7,0x0,0x0,0x0,"MOV EAX,DR7 PUSH EAX"}
    ,{0x2,0x7,0x2,0x0,0x0,0x0,0x0,0x0,"POP EAX MOV DR0,EAX"}
    ,{0x2,0x7,0x2,0x0,0x1,0x0,0x0,0x0,"POP EAX MOV DR1,EAX"}
    ,{0x2,0x7,0x2,0x0,0x2,0x0,0x0,0x0,"POP EAX MOV DR2,EAX"}
    ,{0x2,0x7,0x2,0x0,0x3,0x0,0x0,0x0,"POP EAX MOV DR3,EAX"}
    ,{0x2,0x7,0x2,0x0,0x4,0x0,0x0,0x0,"POP EAX MOV DR4,EAX"}
    ,{0x2,0x7,0x2,0x0,0x5,0x0,0x0,0x0,"POP EAX MOV DR5,EAX"}
    ,{0x2,0x7,0x2,0x0,0x6,0x0,0x0,0x0,"POP EAX MOV DR6,EAX"}
    ,{0x2,0x7,0x2,0x0,0x7,0x0,0x0,0x0,"POP EAX MOV DR7,EAX"}
    ,{0x2,0x1,0x0,0x0,0x0,0x0,0x0,0x0,"POP AX" }
    ,{0x2,0x3,0x0,0x0,0x0,0x0,0x0,0x0,"POP EAX POP AX MOV BYTE PTR ES:,AL"}
    ,{0x2,0x3,0x0,0x0,0x1,0x0,0x0,0x0,"POP EDX POP AX MOV BYTE PTR CS:,AL"}
    ,{0x2,0x3,0x0,0x0,0x2,0x0,0x0,0x0,"POP EDX POP AX MOV BYTE PTR SS:,AL"}
    ,{0x2,0x3,0x0,0x0,0x3,0x0,0x0,0x0,"POP EDX POP AX MOV BYTE PTR DS:,AL"}
    ,{0x2,0x3,0x0,0x0,0x4,0x0,0x0,0x0,"POP EDX POP AX MOV BYTE PTR FS:,AL"}
    ,{0x2,0x3,0x0,0x0,0x5,0x0,0x0,0x0,"POP EDX POP AX MOV BYTE PTR GS:,AL"}
    ,{0x2,0x5,0x1,0x0,0x0,0x0,0x0,0x0,"POP ES" }
    ,{0x2,0x5,0x1,0x0,0x2,0x0,0x0,0x0,"POP SS" }
    ,{0x2,0x5,0x1,0x0,0x3,0x0,0x0,0x0,"POP DS" }
    ,{0x2,0x5,0x1,0x0,0x4,0x0,0x0,0x0,"POP FS" }
    ,{0x2,0x5,0x1,0x0,0x5,0x0,0x0,0x0,"POP GS" }
    ,{0x2,0x2,0x1,0x0,0x1,0x0,0x0,0x0,"POP SP" }
    ,{0x4,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"POP EAX ADD DWORD PTR SS:,EAX"}
    ,{0x4,0x0,0x2,0x0,0x1,0x0,0x0,0x0,"POP EAX ADD DWORD PTR SS:,EAX PUSHFW"}
    ,{0x4,0x0,0x1,0x0,0x0,0x0,0x0,0x0,"POP AX ADD DWORD PTR SS:,AX" }
    ,{0x4,0x0,0x1,0x0,0x1,0x0,0x0,0x0,"POP AX ADD DWORD PTR SS:,AX PUSHFW" }
    ,{0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,"POP AX ADD BYTE PTR SS:,AL" }
    ,{0x4,0x0,0x0,0x0,0x1,0x0,0x0,0x0,"POP AX ADD BYTE PTR SS:,AL PUSHFW" }
    ,{0xF6,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"POP EAX NOT EAX NOT DWORD PTR SS: AND DWORD PTR SS:,EAX"}
    ,{0xF6,0x0,0x2,0x0,0x1,0x0,0x0,0x0,"POP EAX NOT EAX NOT DWORD PTR SS: AND DWORD PTR SS:,EAX PUSHFW"}
    ,{0xF6,0x0,0x1,0x0,0x0,0x0,0x0,0x0,"NOT DWORD PTR SS: POP AX AND WORD PTR SS:,AX" }
    ,{0xF6,0x0,0x1,0x0,0x1,0x0,0x0,0x0,"NOT DWORD PTR SS: POP AX AND WORD PTR SS:,AX PUSHFW" }
    ,{0xF6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,"POP AX POP CX NOT AL NOT CL AND AL,CL PUSH AX"}
    ,{0xF6,0x0,0x0,0x0,0x1,0x0,0x0,0x0,"POP AX POP CX NOT AL NOT CL AND AL,CL PUSH AX PUSHFW"}
    ,{0x1C,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"POP EAX POP CX SHL EAX,CL PUSH EAX"}
    ,{0x1C,0x0,0x2,0x0,0x1,0x0,0x0,0x0,"POP EAX POP CX SHL EAX,CL PUSH EAX PUSHFW"}
    ,{0x1C,0x0,0x1,0x0,0x0,0x0,0x0,0x0,"POP AX POP CX SHL AX,CL PUSH AX"}
    ,{0x1C,0x0,0x1,0x0,0x1,0x0,0x0,0x0,"POP AX POP CX SHL AX,CL PUSH AX PUSHFW"}
    ,{0x1C,0x0,0x0,0x0,0x0,0x0,0x0,0x0,"POP AX POP CX SHL AL,CL PUSH AX"}
    ,{0x1C,0x0,0x0,0x0,0x1,0x0,0x0,0x0,"POP AX POP CX SHL AL,CL PUSH AX PUSHFW"}
    ,{0x1D,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"POP EAX POP CX SHR EAX,CL PUSH EAX"}
    ,{0x1D,0x0,0x2,0x0,0x1,0x0,0x0,0x0,"POP EAX POP CX SHR EAX,CL PUSH EAX PUSHFW"}
    ,{0x1D,0x0,0x1,0x0,0x0,0x0,0x0,0x0,"POP AX POP CX SHR AX,CL PUSH AX"}
    ,{0x1D,0x0,0x1,0x0,0x1,0x0,0x0,0x0,"POP AX POP CX SHR AX,CL PUSH AX PUSHFW"}
    ,{0x1D,0x0,0x0,0x0,0x0,0x0,0x0,0x0,"POP AX POP CX SHR AL,CL PUSH AX"}
    ,{0x1D,0x0,0x0,0x0,0x1,0x0,0x0,0x0,"POP AX POP CX SHR AL,CL PUSH AX PUSHFW"}
    ,{0xF8,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"POP EAX POPAD POPFD RETN"}
    ,{0x3D,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"POP EDX POP EAX POP ECX DIV ECX PUSH EAX PUSH EDX"}
    ,{0x3D,0x0,0x1,0x0,0x0,0x0,0x0,0x0,"POP DX POP AX POP CX DIV CX PUSH AX PUSH DX" }
    ,{0x3D,0x0,0x0,0x0,0x0,0x0,0x0,0x0,"POP AX POP CX DIV CL PUSH AX" }
    ,{0x3F,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"POP EDX POP EAX POP ECX IDIV ECX PUSH EAX"}
    ,{0x3F,0x0,0x1,0x0,0x0,0x0,0x0,0x0,"POP DX POP AX POP CX IDIV CX PUSH AX PUSH DX" }
    ,{0x3F,0x0,0x0,0x0,0x0,0x0,0x0,0x0,"POP AX POP CX IDIV CL PUSH AX" }
    ,{0x40,0x0,0x2,0x0,0x1,0x0,0x0,0x0,"POP EDX POP EAX MUL EDX PUSH EAX PUSH EDX PUSHFW" }
    ,{0x40,0x0,0x1,0x0,0x1,0x0,0x0,0x0,"POP DX POP AX MUL EX PUSH AX PUSH DX PUSHFW" }
    ,{0x40,0x0,0x0,0x0,0x1,0x0,0x0,0x0,"POP DX POP AX MUL DL PUSH AX PUSHFW" }
    ,{0x3E,0x0,0x2,0x0,0x1,0x0,0x0,0x0,"POP EDX POP EAX IMUL EDX PUSH EAX PUSH EDX PUSHFW" }
    ,{0x3E,0x0,0x1,0x0,0x1,0x0,0x0,0x0,"POP DX POP AX IMUL DX PUSH AX PUSH DX PUSHFW" }
    ,{0x3E,0x0,0x0,0x0,0x1,0x0,0x0,0x0,"POP DX POP AX IMUL DL PUSH AX PUSHFW"}
    ,{0x1C,0x0,0x3,0x0,0x1,0x0,0x0,0x0,"POP EAX POP EDX POP CX SHLD EAX,EDX,CL PUSH EAX PUSHFW"}
    ,{0x1D,0x0,0x3,0x0,0x1,0x0,0x0,0x0,"POP EAX POP EDX POP CX SHRD EAX,EDX,CL POUSH EAX PUSHFW"}
    ,{0xF7,0x0,0x2,0x0,0x1,0x0,0x0,0x0,"POP EAX POPAD POPFD RETF" }
    ,{0x2E,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"WAIT" }
    ,{0xB6,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FILD DWORD PTR SS:" }
    ,{0xB6,0x0,0x3,0x0,0x0,0x0,0x0,0x0,"FILD QWORD PTR SS:" }
    ,{0xBB,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FLD DWORD PTR SS:" }
    ,{0xBB,0x0,0x3,0x0,0x0,0x0,0x0,0x0,"FLD QWORD PTR SS:" }
    ,{0xBB,0x0,0x4,0x0,0x0,0x0,0x0,0x0,"FLD TBYTE PTR SS:" }
    ,{0xA0,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FADD DWORD PTR SS:" }
    ,{0xA0,0x0,0x3,0x0,0x0,0x0,0x0,0x0,"FADD QWORD PTR SS:" }
    ,{0xA4,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FSUB DWORD PTR SS:" }
    ,{0xA4,0x0,0x3,0x0,0x0,0x0,0x0,0x0,"FSUB QWORD PTR SS:" }
    ,{0xA5,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FSUBR DWORD PTR SS:" }
    ,{0xA5,0x0,0x3,0x0,0x0,0x0,0x0,0x0,"FSUBR QWORD PTR SS:" }
    ,{0xBC,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FSTP DWORD PTR SS:" }
    ,{0xBC,0x0,0x3,0x0,0x0,0x0,0x0,0x0,"FSTP QWORD PTR SS:" }
    ,{0xBC,0x0,0x4,0x0,0x0,0x0,0x0,0x0,"FSTP TBYTE PTR SS:" }
    ,{0xA6,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FDIV DWORD PTR SS:" }
    ,{0xA6,0x0,0x3,0x0,0x0,0x0,0x0,0x0,"FDIV QWORD PTR SS:" }
    ,{0xA1,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FMUL DWORD PTR SS:" }
    ,{0xA1,0x0,0x3,0x0,0x0,0x0,0x0,0x0,"FMUL QWORD PTR SS:" }
    ,{0xA3,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FCOMP DWORD PTR SS:" }
    ,{0xA3,0x0,0x3,0x0,0x0,0x0,0x0,0x0,"FCOMP QWORD PTR SS:" }
    ,{0xC8,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FCHS" }
    ,{0xDB,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FSQRT" }
    ,{0xEE,0x0,0x1,0x0,0x0,0x0,0x0,0x0,"FSTSW AX PUSH AX" }
    ,{0xC6,0x0,0x1,0x0,0x0,0x0,0x0,0x0,"FSTCW WORD PTR SS:" }
    ,{0xC4,0x0,0x1,0x0,0x0,0x0,0x0,0x0,"FLDCW WORD PTR SS:" }
    ,{0xE3,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"F2XM1" }
    ,{0xC9,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FABS" }
    ,{0xE6,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FCLEX" }
    ,{0xE0,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FCOS" }
    ,{0xD7,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FDECSTP" }
    ,{0xD8,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FINCSTP" }
    ,{0xE5,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FINIT" }
    ,{0xD0,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FLDLN2" }
    ,{0xCF,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FLDLG2" }
    ,{0xD9,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FPREM" }
    ,{0xD6,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FPREM1" }
    ,{0xD3,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FPTAN" }
    ,{0xDD,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FRNDINT" }
    ,{0xDF,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FSIN" }
    ,{0xE1,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FTST" }
    ,{0xD2,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FYL2X" }
    ,{0xD4,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FPATAN" }
    ,{0xD1,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FLDZ" }
    ,{0xB8,0x0,0x1,0x0,0x0,0x0,0x0,0x0,"FISTP WORD PTR SS:" }
    ,{0xB8,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FISTP DWORD PTR SS:" }
    ,{0xB8,0x0,0x3,0x0,0x0,0x0,0x0,0x0,"FISTP QWORD PTR SS:" }
};


Btw:不保证全对哈,最好看看,哈哈
接着我们看一看Vmp_GetVmHandleIndex的调用


ida的有点乱,把这个函数整理之后

void _func_101()
{
    _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex( esi->_var1_vm_mnemonic, 0, esi->_var3_lval, (esi->ispushfw) != 0);
}

void _func_104()
{
    _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex( esi->_var1_vm_mnemonic, 0, esi->_var3_lval, 0));
}

void _func_3(}
{
    _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex( esi->_var1_vm_mnemonic, 0, esi->_var3_lval, 1));
}

int _getindex( int _n)
{
    switch(_n)
    {
    case 1:
      return 0;
    case 2:
      return 1;
    case 3:
      return 2;
    case 5:
      return 4;
    case 6:
      return 5;
    default:
      return 3;
    }
}

_DWORD *__usercall Vmp_FindAndSetTOStruct@<eax>(struct_esi *a1@<eax>, int _size@<ebx>, int _i@<esi>)
{
    esi->_esi_size = 0;
    if( esi->_var1_vm_mnemonic > 0xc4)
    {
      switch(esi->_var1_vm_mnemonic)
      {
      case 0xC6:
      case 0xC8:
      case 0xC9:
      case 0xCF:
      case 0xD0:
      case 0xD1:
      case 0xD2:
      case 0xD3:
      case 0xD4:
      case 0xD6:
      case 0xD7:
      case 0xD8:
      case 0xD9:
      case 0xDB:
      case 0xDD:
      case 0xDF:
      case 0xE0:
      case 0xE1:
      case 0xE3:
      case 0xE5:
      case 0xE6:
      case 0xEE:
      case 0xF8:
            {
                _func_104();
                return;
            }
      case 0xF6:
            {
                _func_101();
                return;
            }
      case 0xF7:
            {
                _func_3();
                break;
            }
      default:
            return;
      }
    }

    if( esi->_var1_vm_mnemonic == 0xC4)
    {
      _func_104();
      return;
    }
    if( esi->_var1_vm_mnemonic > 0x40)
    {
      if( esi->_var1_vm_mnemonic > 0xb6)
      {
            if( esi->_var1_vm_mnemonic != 0xb8 && esi->_var1_vm_mnemonic - 0xbb >= 2)
            {
                return;
            }
      }
      else if( esi->_var1_vm_mnemonic != 0xb6)
      {
            if( esi->_var1_vm_mnemonic == 0x8b)
            {
                esi->_hex = esi->_displacement_immediate;
                esi->size += 4;
                return;
            }
            if( esi->_var1_vm_mnemonic - 0xA0 >= 2 && esi->_var1_vm_mnemonic - 0xA3 >= 4)
            {
                return ;
            }
      }
      _func_104();
      return;
    }
    if ( esi->_var1_vm_mnemonic == 0x40 )          // mul
      _func_104();
    return;
    if ( esi->_var1_vm_mnemonic > 0x2E )
    {
      if ( esi->_var1_vm_mnemonic != 0x3D )
      {
            if ( esi->_var1_vm_mnemonic == 0x3E )      // pop dx
                _func_101();
            return;
            if ( esi->_var1_vm_mnemonic != 0x3F )
                return;
      }
      _func_104();
      return;
    }
    if ( esi->_var1_vm_mnemonic == 0x2E )          // wait
      _func_104();
    return;
    if ( esi->_var1_vm_mnemonic - 1 >= 2 )
    {
      if ( esi->_var1_vm_mnemonic != 4 && esi->_var1_vm_mnemonic - 28 >= 2 )// !=4 || >= 0x1E
            return;
      _func_101();
      return;
    }
    if ( esi->_var1_vm_mnemonic - 1 != 0 )
    {
      if ( esi->_var1_vm_mnemonic == 2 )                              // pop
      {
            switch ( _esi->_var2_addressing_mode )
            {
            case 1:
                {
                  _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex( 2, 1, esi->_var3_lval, 0));// pop eax|ax
                  break;
                }
            case 2:   
                {
                  if ( _esi->_var3_lval >= 3 || _esi->_REG_Index != 4 )
                  {
                        int flag = !_esi->_var3_lval && (_esi->_REG_Index & 4) == 4;
                        _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex(2, 2, _esi->_var3_lval, flag);
                        _hex2 = Vmp_GetEmptyVMContext(_esi->Struct_vtable_477C54,_esi->_var3_lval,_esi->_REG_Index,1);
                        saveToStruct(_esi, _hex2);
                  }
                  else
                  {
                        _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex(2, 2, _esi->_var3_lval, 1));// pop sp|esp
                  }
                  break;
                }
            case 3:
                {
                  _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex(2, 3, _esi->_var3_lval, _getindex(esi->var5));
                  break;
                }
            case 5:
                {
                  _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex(2, 5, 1, _esi->_REG_Index));// pop prefiexreg_index
                  break;
                }
            case 6:
                {
                  _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex(2, 6, 2, _esi->_REG_Index));
                  break;
                }
            case 7:
                {
                  _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex(2, 7, 2, _esi->_REG_Index));
                  break;
                }
            default:
                break;
            }
      }
    }
    else if ( _esi->_var2_addressing_mode == 1 )
    {
      switch ( _esi->_rand_switch )
      {
      case 1:
            {
                do
                v5 = rand()%(-1);
                while ( !v5 && 0 == *_esi->_Displacement_Immediate );
                _lval_disp_imm = *_esi->_Displacement_Immediate - v5;
                v6 = sub_47817C(_esi);
                v7 = getStruct_1(_esi->Struct_vtable_477C54, v6 + 1);
                *v7->_Displacement_Immediate = v5;
                Vmp_FindAndSetTOStruct(v7, v5, _lval_disp_imm);
            }
            break;
      case 2:
            {
                do
                v8 = ~*_esi->_Displacement_Immediate & rand()%(-1);
                while ( !v8 && 0 == ~*_esi->_Displacement_Immediate );
                _lval_disp_imm = v8 | ~*_esi->_Displacement_Immediate & ~v8;
                v9 = sub_47817C(_esi);
                v10 = getStruct_1(_esi->Struct_vtable_477C54, v9 + 1);
                *v10->_Displacement_Immediate = v8;
                Vmp_FindAndSetTOStruct(v10, v8, _lval_disp_imm);
            }
            break;
      case 3:
            {
                v11 = 0;
                v12 = *_esi->_Displacement_Immediate;
                while ( !(v12 & 1) ) //偶数
                {
                  v12 >>= 1;
                  ++v11;
                }
                v13 = System::__linkproc__ RandInt(v11);
                _lval_disp_imm = v13 + 1;
                v14 = *_esi->_Displacement_Immediate >> (v13 + 1);
                v15 = sub_47817C(_esi);
                v16 = getStruct_1(_esi->Struct_vtable_477C54, v15 + 1);
                *v16->_Displacement_Immediate = v14;
                Vmp_FindAndSetTOStruct(v16, v14, _lval_disp_imm);
                break;
            }
      case 4:
            {
                v17 = 0;
                while ( _esi->__var4 == 2 && *_esi->_Displacement_Immediate >= 0 || _esi->__var4 == 1 && (*_esi->_Displacement_Immediate & 0x8000) == 0 )
                {
                  *_esi->_Displacement_Immediate *= 2;
                  ++v17;
                }
                v19 = System::__linkproc__ RandInt(v17);
                _lval_disp_imm = v19 + 1;
                v20 = *_esi->_Displacement_Immediate << (v19 + 1);
                v21 = sub_47817C(_esi);
                v22 = getStruct_1(_esi->Struct_vtable_477C54, v21 + 1);
                *v22->_Displacement_Immediate = v20;
                Vmp_FindAndSetTOStruct(v22, v20, _lval_disp_imm);
                break;
            }
      default:
            {
                _lval_disp_imm = *_esi->_Displacement_Immediate;
                break;
            }
      }
      if ( _esi->_rand_switch )
      {
            setAddress(&_esi->_esi_hex, *(&off_4CE17C + _esi->_var1_vm_interpreter_mnemonic));
            if ( _esi->_var3_lval == 1 )
            {
                a2a = _lval_disp_imm;
                LOBYTE(v66) = 0;
                sub_409984(&str____4x, &a2a, 0, v64);
                System::__linkproc__ LStrCat(&_esi->_esi_hex, *v64);
            }
            else if ( _esi->_var3_lval == 2 )
            {
                a2a = _lval_disp_imm;
                LOBYTE(v66) = 0;
                sub_409984(&str____8x, &a2a, 0, v67);
                System::__linkproc__ LStrCat(&_esi->_esi_hex, *v67);
            }
            if ( _esi->__var4 == 1 )
            {
                a2a = *_esi->_Displacement_Immediate;
                LOBYTE(v66) = 0;
                sub_409984(&str___4x, &a2a, 0, v62);
                setAddress(&_esi->_esi_hex, *v62);
            }
            else if ( _esi->__var4 == 2 )
            {
                a2a = *_esi->_Displacement_Immediate;
                LOBYTE(v66) = 0;
                sub_409984(&str___8x, &a2a, 0, v63);
                setAddress(&_esi->_esi_hex, *v63);
            }
      }
      else
      {
            Free_Mem(&_esi->_esi_hex);
      }
      if ( _esi->_var3_lval == 1 )
      {
            if ( _lval_disp_imm & 0xFF00 )
            {
                _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex( 1, 1, 1, 0);// LODS WORD PTR DS: ADD AX,BX ADD BX,AX PUSH AX
                Move_Word(_esi, _lval_disp_imm);
            }
            else
            {
                _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex( 1, 1, 0, 0);// LODS BYTE PTR DS: ADD AL,BL ADD BL,AL PUSH AX
                saveToStruct(_esi, _lval_disp_imm);
            }
      }
      else if ( _esi->_var3_lval == 2 )
      {
            if ( _esi->_ispushfw & 2 || _lval_disp_imm != Byte_Extension(_lval_disp_imm) )
            {
                if ( _esi->_ispushfw & 2 || _lval_disp_imm != Word_Extension(_lval_disp_imm) )
                {
                  _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex( 1, 1, 2, 0);// LODS DWORD PTR DS: ADD EAX,EBX ADD EBX,EAX PUSH EAX
                  Move_Dword(_esi, _lval_disp_imm);
                }
                else
                {
                  _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex( 1, 1, 1, 1);// LODS WORD PTR DS: ADD AX,BX ADD BX,AX CWDE PUSH EAX
                  Move_Word(_esi, _lval_disp_imm);
                }
            }
            else
            {
                _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex( 1, 1, 0, 1);// LODS BYTE PTR DS: ADD AL,BL ADD BL,AL CBW CWDE PUSH EAX
                saveToStruct(_esi, _lval_disp_imm);
            }
      }
      else
      {
            _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex( 1, 1, 0, 0);// LODS BYTE PTR DS: ADD AL,BL ADD BL,AL PUSH AX
            saveToStruct(_esi, _lval_disp_imm);
      }
    }
    else
    {
      switch ( _esi->_var2_addressing_mode )
      {
      case 2:
            {
                if ( _esi->_var3_lval >= 3 || _esi->_REG_Index != 4 )
                {
                  _vmp_setIndexToStruct( esi,_vmp_getVmHandlerIndex(1, 2, _esi->_var3_lval, _esi->_var3_lval == 0 && (_esi->_REG_Index & 4) == 4);//利用空间push _context[]
                  v34 = Vmp_GetEmptyVMContext(_esi->Struct_vtable_477C54,_esi->_var3_lval,_esi->_REG_Index,0);//选择index
                  saveToStruct(_esi, v34);
                }
                else
                {
                  _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex( 1, 2, _esi->_var3_lval, 1);//// push sp|esp
                }
                break;
            }
      case 3:
            {
                _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex(1,3,_esi->_var3_lval,_getindex(_esi->_var5));// pop e?x push ? ptr ?
                break;
            }
      case 5:
            {
                _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex( 1, 5, 1, _esi->_REG_Index));//push prefix_reg
                break;
            }
      case 6:
            {
                _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex( 1, 6, 2, _esi->_REG_Index));//mov eax,cr_index push eax
                break;
            }
      case 7:
            {
                _vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex( 1, 7, 2, _esi->_REG_Index));// mov eax,dr_index push eax
                break;
            }
      default:
            {
                break;
            }
      }
    }
}


1.       判断vm_mnemonic
2.       再判断寻址方式以及类型
继续,我们看看vm_mnemonic怎么得到的

char __fastcall Vmp_SetEsiStruct(struct_vtable_477C54 *var1, char _var1_interpreter_mnemonic, char _var2_addressing_mode, unsigned __int8 _3_lval_type, int _var5_index, int var6, int var7)
{
    v8 = (var1->Vtable_477C54->SetCapacity)();
    if ( var6 & 8 )
      Classes::TList::Add(_var1->Ptr_Struct_Vtable_40F3B8, v8);
    v8->_var1_vm_interpreter_mnemonic = _var1_vm_mnemonic;
    v8->_var2_addressing_mode = _var2_addressing_mode;
    v8->_var3_lval_type_byte_word_dword_or_vm_displacement = _3_lval_type;
    if ( var6 & 0x20 )
      v8->_ispushfw |= 0x20u;
    switch ( _var2_addressing_mode )               // 第3个参数进行switch
    {
    case 0:
      if ( _var5_index == 1 )
            v8->_ispushfw |= 1u;
      else
            v8->_ispushfw &= 0xFEu;
      break;
    case 1:                                     // 先判断类型 第4个参数进行判断
      if ( _3_lval_type < 1u )                  //
      {
            *v8->_Displacement_Immediate = (char)_var5_index;
      }
      else if ( _3_lval_type == 1 )             //
      {
            *v8->_Displacement_Immediate = (short)_var5_index;
      }
      else                                    //
      {
            *v8->_Displacement_Immediate = _var5_index;
      }
      if ( var6 & 0x10 )
      {
            v8->_ispushfw |= 8u;
            v9 = var7;
            v8->_init0xffff_oppositecondition = var7;
      }
      if ( var6 & 2 )
            v8->_ispushfw |= 2u;
      if ( var6 & 1 )
      {
            LOBYTE(v9) = 1;
            v31 = 1;
      }
      else
      {
            LOBYTE(v9) = 0;
            v31 = 0;
      }
      if ( var6 & 0x40 )
            v31 |= 0x40u;
      if ( var6 & 4 )
      {
            if ( _3_lval_type >= 3 )                              // qword的拆分吗
            {
                if ( _var1->Struct_Vtable_477E80->Struct_Vtable_477F00->_vm_type & 4 )
                {
                  v8->__var4 = _3_lval_type;
                  _rand_type = 1;
                  _rand_type = 1;
                  if ( statisticsbinaryis1count(~*v8->_Displacement_Immediate, _3_lval_type) >= 3u )// 统计奇数为 大于3
                  {
                        _rand_type = 2;
                        _rand_type = 2;
                  }
                  else
                  {
                        _rand_type = 1;
                        _rand_type = 1;
                  }
                  if ( !(v8->_ispushfw & 2) && *v8->_Displacement_Immediate )
                  {
                        if ( !(v8->_Displacement_Immediate & 1) )
                            _rand_type = 3;
                        if ( _3_lval_type == 2 && v8->_Displacement_Immediate >= 0
                            || _3_lval_type == 1 && v8->_Displacement_Immediate >= 0 )
                        {
                            _rand_type = 4;
                        }
                  }
                  v8->_rand_switch = _rand_type;
                  switch ( v8->_rand_switch )
                  {
                  case 1:
                        {
                            Vmp_SetEsiStruct(_var1, 1, 1, _3_lval_type, 0, v31 | 2, -1);// LODS DWORD PTR DS: PUSH EAX
                            Vmp_SetEsiStruct(_var1, 4, 0, _3_lval_type, 0, v31, -1);// POP EAX ADD DWORD PTR SS:,EAX
                            break;
                        }
                  case 2:
                        {
                            Vmp_SetEsiStruct(_var1, 1, 1, _3_lval_type, 0, v31 | 2, -1);
                            Vmp_SetEsiStruct(_var1, 0xF6, 0, _3_lval_type, 0, v31, -1);// POP EAX NOT EAX NOT DWORD PTR SS: AND DWORD PTR SS:,EAX
                            break;
                        }
                  case 3:
                        {
                            v8->_var3_lval_type_byte_word_dword_or_vm_displacement = 1;
                            Vmp_SetEsiStruct(_var1, 1, 1, _3_lval_type, 0, v31 | 2, -1);
                            LOBYTE(v9) = Vmp_SetEsiStruct(_var1, 0x1C, 0, _3_lval_type, 0, v31, -1);// POP EAX POP CX SHL EAX,CL PUSH EAX
                            break;
                            default:
                            if ( v8->_rand_switch == 4 )
                            {
                              v8->_var3_lval_type_byte_word_dword_or_vm_displacement = 1;
                              Vmp_SetEsiStruct(_var1, 1, 1, _3_lval_type, 0, v31|2, -1);//LODS DWORD PTR DS: PUSH EAX
                              Vmp_SetEsiStruct(_var1, 0x1D, 0, _3_lval_type, 0, v31, -1);// POP EAX POP CX SHR EAX,CL PUSH EAX
                            }
                            break;
                        }
                  }
                }
            }
      }
    }
    if ( _3_lval_type == 2 && var6 & 0x10 && _1_interpreter_mnemonic != 0x8Bu )//
    {
      if ( var7 == -1 )
      {
            v9 = 3;
      }
      else
      {
            v9 = sub_479128(*&_var1->Struct_Vtable_477E80->Struct_Vtable_477F00->Struct_table_477E80->field_60, var7)->field_C;
      }
      switch(v9)
      {
      case 3:
            {
                Vmp_SetEsiStruct(_var1, 1, 2, 2, 10, v31, -1);//LODS BYTE PTR DS: PUSH DWORD PTR DS:
                Vmp_SetEsiStruct(_var1, 4, 0, 2, 0, v31, -1);//POP EAX ADD DWORD PTR SS:,EAX
                break;
            }
      case 2:
            {
                Vmp_SetEsiStruct(_var1, 1, 1, 1, 0, v31, -1);//LODS WORD PTR DS: PUSH AX
                Vmp_SetEsiStruct(_var1, 1, 2, 1, 10, v31, -1);//LODS BYTE PTR DS: PUSH WORD PTR DS:
                Vmp_SetEsiStruct(_var1, 4, 0, 2, 0, v31, -1);//POP EAX ADD DWORD PTR SS:,EAX
                break;
            }
      case 1:
            {
                Vmp_SetEsiStruct(_var1, 1, 2, 2, 10, v31, -1);// LODS BYTE PTR DS: PUSH DWORD PTR DS:
                Vmp_SetEsiStruct(_var1, 2, 1, 1, 0, v31, -1);// LODS BYTE PTR DS: POP WORD PTR DS:
                Vmp_SetEsiStruct(_var1, 1, 1, 1, 0, v31, -1);// LODS WORD PTR DS: PUSH AX
                Vmp_SetEsiStruct(_var1, 4, 0, 2, 0, v31, -1);// POP EAX ADD DWORD PTR SS:,EAX
                break;
            }
      }
      if ( !(var6 & 0x40) && !(var6 & 8) && _1_interpreter_mnemonic == 1 )
      {
            if ( _var1->Struct_Vtable_477E80->Struct_Vtable_477F00->_vm_type & 0x20 )
            {
                v9 = rand()%2 - 1;
                if ( !v9 )//(int) += []
                {
                  v31 |= 0x40u;
                  v23 = sub_48BC1C(_var1->Struct_Vtable_477E80->Struct_Vtable_477F00, &v30);
                  Vmp_SetEsiStruct(_var1, 1, 1, 2, v30, v31 | 0x14, -1);// LODS DWORD PTR DS: PUSH EAX
                  Vmp_SetEsiStruct(_var1, 1, 3, _3_lval_type, 0, v31, -1);// POP EAX PUSH DWORD PTR SS:
                  Vmp_SetEsiStruct(_var1, 1, 1, _3_lval_type, -v23, v31 | 4, -1);// LODS DWORD PTR DS: PUSH EAX
                  Vmp_SetEsiStruct(_var1, 4, 0, _3_lval_type, 0, v31, -1);// POP EAX
                  Vmp_SetEsiStruct(_var1, 4, 0, _3_lval_type, 0, v31, -1);// POP EAX ADD DWORD PTR SS:,EAX
                }
            }
      }
      break;
      case 2:
      case 5:
      case 6:
      case 7:
            v8->_REG_Index = _var5_index;
            break;
      case 3:
            v8->field_F = _var5_index;
            break;
      default:
            break;
    }
    if ( var6 & 1 )                               // 奇数成立
      Vmp_FindAndSetTOStruct(v8, var6, v8);// Make
    return v9;
}


可以发现由传参决定并对于某些方式递归调用
继续寻找怎么来的



定位到cmp。看看vmp是如何实现对cmp,jcc的膨胀的


首先可以很直观的看到,在早期版本中
把sub cmp sbb放在一起来处理
那么看看是如何usedisasmstruct的


char __usercall _get_prefix@<al>(int index@<eax>, int a2)
{
    _operand = ( _disasm + 21 * _operand_index + 24)
    if ( _disasm.About_Prefixes == 4 )
      return 0;
    if ( _disasm.About_Prefixes == 0
      && (v2->FirstVar_Trans_ModRM_mod & 0x10
      && (v2->ThirdVar_SIB__Base_Index - 4) < 2
      || v2->FirstVar_Trans_ModRM_mod & 4
      && (v2->SecondVar_Trans_ModRM_rm_Index - 4) < 2) )
    {
      return 3;
    }
    return _disasm.About_Prefixes;
}



int __usercall Vmp_UseDisasmStruct@<eax>(int _operand_index@<eax>, char a2@<dl>, int a3@<ecx>, int a4@<ebx>, int a5)
{
    _operand = ( _disasm + 21 * _operand_index + 24);
    if ( _operand.FirstVar_Trans_ModRM.mod == 0 )               // FirstVar_Trans_ModRM.mod == 0return
      return 0;
    int ret = 1;
    if ( a2 & 4 )
    {
      _Type = 1;
    }
    else if ( a2 & 8 )
    {
      _Type = 2;
    }
    else
    {
      _Type = _operand->About_Lval_Byte_Word_Dword;
    }
    BYTE1(__n) = 0;
    if ( _operand->FirstVar_Trans_ModRM_mod == 0x24 )// prefix
    {
      if ( a2 & 1 && (__n = *(a5 - 4), *(__n + 22) != 1) )// != push
      {
            _vmp_SetEsiStruct(*(a5 - 4), 2, 5, 1, _operand->SecondVar_Trans_ModRM_rm_Index, 0, -1);// POP PREFIX
            if ( _Type == 2 )
            {
                _vmp_SetEsiStruct(*(a5 - 4), 2, 1, 1, 0, 0, -1);// POP AX
            }
      }
      else                                        // pop
      {
            if ( _Type == 2 )
            {
                _vmp_SetEsiStruct(*(a5 - 4), 1, 1, 1, 0, 0, -1);// LODS WORD PTR DS: PUSH AX
            }
            _vmp_SetEsiStruct(*(a5 - 4), 1, 5, 1, _operand->SecondVar_Trans_ModRM_rm_Index, 0, -1);// PUSH PREFIX
      }
    }
    else if ( _operand->FirstVar_Trans_ModRM_mod == 0x84 )// DR?
    {
      if ( a2 & 1 && _disasm->Mnemonic_Counter_4CE17C != 1 )   // Mnemonic_Counter_4CE17C != 1 push
      {
            _vmp_SetEsiStruct(*(a5 - 4), 2, 7, 2, _operand->SecondVar_Trans_ModRM_rm_Index, 0, -1);// POP EAX MOV DR?,EAX
      }
      else
      {
            _vmp_SetEsiStruct(*(a5 - 4), 1, 7, 2, _operand->SecondVar_Trans_ModRM_rm_Index, 0, -1);// MOV EAX,DR? PUSH EAX
      }
    }
    else
    {
      if ( _operand->FirstVar_Trans_ModRM_mod == 0x44 )// CR?
      {
            if ( a2 & 1 && _disasm->Mnemonic_Counter_4CE17C != 1 )   // push
            {
                _vmp_SetEsiStruct(*(a5 - 4), 2, 6, 2, _operand->SecondVar_Trans_ModRM_rm_Index, 0, -1);// POP EAX MOV CR?,EAX
            }
            else
            {
                _vmp_SetEsiStruct(*(a5 - 4), 1, 6, 2, _operand->SecondVar_Trans_ModRM_rm_Index, 0, -1);// MOV CR?,EAX PUSH EAX
            }
      }
      else
      {
            if ( _operand->FirstVar_Trans_ModRM_mod & 2 )
            {
                if ( _operand->FirstVar_Trans_ModRM_mod & 8 )
                  _Size = 2;                            // 0xC 0xE
                else
                  _Size = _Type;
                v15 = _operand->RestHex_Lval_Displacement_Immediate;
                RestHex_Displacement_Immediate = _operand->RestHex_Lval_Displacement_Immediate;
                if ( _operand->Lavl_Btye_Word_Dword )                              // if(v8->Lavl_Btye_Word_Dword != 0)
                {
                  if ( _operand->Lavl_Btye_Word_Dword == 1 && _Size == 2 )         // word
                  {
                        RestHex_Displacement_Immediate = Word_Extension(_operand->RestHex_Lval_Displacement_Immediate);
                  }
                }
                else if ( _Size == 2 )                  // dword
                {
                  RestHex_Displacement_Immediate = Byte_Extension(_operand->RestHex_Lval_Displacement_Immediate);
                }
                else if ( _Size == 1 )                  // word
                {
                  RestHex_Displacement_Immediate = Byte_Extension_Word(_operand->RestHex_Lval_Displacement_Immediate);
                }
                if ( !(_operand->FirstVar_Trans_ModRM_mod & 8) && _a2 & 2 )
                {
                  if ( _disasm->Mnemonic_Counter_4CE17C != 0x13 && _disasm->Mnemonic_Counter_4CE17C != 0x43 )// sbb 0x44不算
                        // Opcode_counter_4CE17C != 19 || != 67
                        //                  _str_sub || _str_cmp
                        RestHex_Displacement_Immediate = ~RestHex_Displacement_Immediate;// 反码
                  else
                        RestHex_Displacement_Immediate = -RestHex_Displacement_Immediate;//
                  // sub || cmp
                  // 补码
                }
                if ( _operand->Lavl_Btye_Word_Dword == 2 )
                {
                  __Type1 = 4;
                  v16 = *(*(a5 - 4) + 0x80);
                  if ( v16 && *(v16 + 8) )
                        __Type1 = 0xE;
                }
                else
                {
                  __Type1 = 0;
                }
                if ( _operand->Fix > 0xFFFFFFFF || (_disasm->Mnemonic_Counter_4CE17C + 0xC) < 2u && !_operand_index && _operand->FirstVar_Trans_ModRM_mod == 2 )// _disasm->Mnemonic_Counter_4CE17C <===> mnemonic
                {
                  __Type1 |= 0x10u;
                }                                       // 到时候好从读出补码或反码
                // 在push
                // 那么下面就是与输入的数进行and
                _vmp_SetEsiStruct(*(a5 - 4), 1, 1, _Size, RestHex_Displacement_Immediate, __Type1, _operand->Fix);
            }                                       // lods immediate push eax
            if ( _operand->FirstVar_Trans_ModRM_mod & 4 )
            {
                if ( _operand->FirstVar_Trans_ModRM_mod & 8 )
                {
                  if ( _operand->SibFirstVar_SIB_Scable_Index )
                  {
                        _vmp_SetEsiStruct(*(a5 - 4), 1, 1, 1, _operand->SibFirstVar_SIB_Scable_Index, 0, -1);// LODS WORD PTR DS: PUSH EAX
                  }
                  if ( _operand->About_RegType_8_16_32 == 1 )
                  {
                        _vmp_SetEsiStruct(*(a5 - 4), 1, 1, 1, 0, 0, -1);// LODS WORD PTR DS: PUSH AX
                  }
                  _vmp_SetEsiStruct( *(a5 - 4), 1, 2, _operand->About_RegType_8_16_32, _operand->SecondVar_Trans_ModRM_rm_Index,0,-1);
                  if ( _operand->SecondVar_Trans_ModRM_rm_Index == 4 )// sp
                        sub_486A30(2u, a5);
                }
                else
                {
                  if ( _a2 & 1 && _disasm->Mnemonic_Counter_4CE17C != 1 )
                  {
                        _vmp_SetEsiStruct(*(a5 - 4), 2, 2, _Type, _operand->SecondVar_Trans_ModRM_rm_Index, 0, -1);// LODS BYTE PTR DS: POP DWORD PTR DS:
                  }
                  else
                  {
                        _vmp_SetEsiStruct(*(a5 - 4), 1, 2, _Type, _operand->SecondVar_Trans_ModRM_rm_Index, 0, -1);// LODS BYTE PTR DS: PUSH DWORD PTR DS:
                  }
                  if ( _Type < 3 && _operand->SecondVar_Trans_ModRM_rm_Index == 4 && !(_a2 & 1) )
                        sub_486A30(_Type, a5);//ADD DWORD PTR SS:,LODSD DS:
                }
            }
            if ( _operand->FirstVar_Trans_ModRM_mod & 8 )
            {
                if ( _operand->FirstVar_Trans_ModRM_mod & 4 && _operand->SibFirstVar_SIB_Scable_Index )
                {
                  _vmp_SetEsiStruct(*(a5 - 4), 28, 0, 2u, 0, 0, -1);
                }
                if ( _operand->FirstVar_Trans_ModRM_mod & 0x10 )
                {
                  if ( _operand->About_RegType_8_16_32 == 1 )
                  {
                        _vmp_SetEsiStruct(*(a5 - 4), 1, 1, 1u, 0, 0, -1);
                  }
                  _vmp_SetEsiStruct(*(a5 - 4), 1, 2, _operand->About_RegType_8_16_32, _operand->ThirdVar_SIB__Base_Index, 0, -1);
                  if ( _operand->ThirdVar_SIB__Base_Index == 4 )
                        sub_486A30(2, a5);//ADD DWORD PTR SS:,LODSD DS:
                  if ( _operand->FirstVar_Trans_ModRM_mod & 4 )
                  {
                        _vmp_SetEsiStruct(*(a5 - 4), 4, 0, 2u, 0, 0, -1);
                  }
                }
                if ( _operand->FirstVar_Trans_ModRM_mod & 2 && (_operand->FirstVar_Trans_ModRM_mod & 4 || _operand->FirstVar_Trans_ModRM_mod & 0x10) )
                {
                  _vmp_SetEsiStruct(*(a5 - 4), 4, 0, 2u, 0, 0, -1);
                }
                if ( !(_a2 & 0x10) )//addressing prefix:
                {
                  if ( _a2 & 1 )
                  {
                        v25 = _get_prefix(__operand_index, a5) & 0x7F;
                        _vmp_SetEsiStruct(*(a5 - 4), 2, 3, _Type, v25, 0, -1);//POP EAX POP DWORD PTR prefix:
                  }
                  else
                  {
                        v27 = _get_prefix(__operand_index, a5) & 0x7F;
                        _vmp_SetEsiStruct(*(a5 - 4), 1, 3, _Type, v27, 0, -1);//POP EAX PUSH DWORD PTR prefix:
                  }
                }
            }
      }
    }
    return ret;
}



结合刚开始给的,则有先读operand
注意到:


if ( _disasm->Mnemonic_Counter_4CE17C != 0x13 && _disasm->Mnemonic_Counter_4CE17C != 0x43 )
// sbb 0x44不算 Opcode_counter_4CE17C != 19 || != 67_str_sub || _str_cmp
    RestHex_Displacement_Immediate = ~RestHex_Displacement_Immediate;// 反码
else
    RestHex_Displacement_Immediate = -RestHex_Displacement_Immediate;// sub || cmp 补码


然后其他的对应膨胀规则看看就明白了


分析sub_485884


分析sub_4857DC


可以看到这整套就是一个计算好初始eflags,然后压入_context的过程
分析sub_4858E0
这里就没注释了,可以对照规则



至此,早期版本中的cmp就这样vm了
一个细节的地方
注意到Vmp_SetEsiStruct函数


v8 = (var1->Vtable_477C54->SetCapacity)();
if ( var6 & 8 )
Classes::TList::Add(_var1->Ptr_Struct_Vtable_40F3B8, v8);


那么我们可以这样理解,在早期版本
vm的基本单位是指令,而指令通过反编译得到 ----> _struct_disasm
加上一个list,抽象出来


_struct_disasm
{
    ……
    …..
    list<?> ls;
};


注意到esi是怎样生成的,通过那些规则,故


_struct_disasm
{
    ……
   …..
    list<_struct_esi> ls;
};


同时我们可以猜一猜vmp设计的思路
一开始应该是vm的各种运算(add sub mul xor)
这个不难,如果叫我们来实现,直接将代码替换就可以了


稍微面向一点
switch(mnemonic)
{
case _sub:
case _cmp
}
再面向一些,查表
int _table[] = {1,2,3,4……}
switch(mnemonic)
{
case _sub:
index = 1;
case _cmp:
index = 2;
}


最后在进行匹配
我不知道其他的vm引擎是怎么设计的,如果是我写的话应该也会这样。
第一步可以看成写编译器的语法分析


另外
{0xF6,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"POP EAX NOT EAX NOT DWORD PTR SS: AND DWORD PTR SS:,EAX"}
这个0xf6取得蛮有意思的


在说说jcc


注意到


这几个参数,已上个帖子提到




恩,很多人爆破提到的shr。这个我想动态跟一跟,因为我觉得设计得很好

push add1

push 0
add ,0
stack_top   0042fbcd

push addr2
push 0
add ,0 //这两个地址很有意思
stack_top   0042fb9b
            0042fbcd

lodw
push not(0x40
lodb
push _context ----> push eflags
stack_top ffbf0287


not ---> 0040fd78
pop ax
and ,ax
stack_top   fb9b0040
            fbcd0042
                0042

losb
pop _context ---> 0x40
stack_top   42fb9b
            42fbcb
            001848

losb
push 4
stack_top   fb9b0004
            fbcd0042
                0042

Lodb
Push _context
Stack_top   00040040
            0042fb9b
            0042fbcd

Pop ax
Pop cx
Shr ax,cl---> result == 0x4
Push ax
Stack_top   fb9b0004
            Fbcd0042
                0042

//这个4很有意思
Lodb
Pop _context ---> 4
stack_top   0042fb9b
            0042fbcd


Push esp //注意到这里
stack_top   0018FE98(addr_42fb9b)
            0042FB9B
            0042FBCD


Lodsb
Push ax--> 0
Stack_top   fe98000
            Fb9b0018
            Fbcd0042
            Ff480042


Lodsb
Push _context ---> 0x4
Stack_top   00000004
            0018fe98
Pop eax   --->       eax == 0x4
add ,eax
stack_top   0018FE98(addr_42fb9b)
            0042FB9B
            0042FBCD


注意到这里,很重要
vmp先压了两个地址然后取eflags运算进行shr,通常会得到4
那么这个4是用来干什么的
我们看看这两个地址的内容





恩,没错。实现了分支
在注意到这里的地址

Stack_top   0018fe9c(addr_0042fbcd)
            0042fb9b
            0042fbcd

Pop eax
Push
Stack_top   0042fbcd
            0042fb9b
            0042fbcd

但是有个问题,vmp怎么修改esi
Lodsd
Push vmp_entry
Stack_top   0042F000(vmp_entry)
            00000000(_addressing)
            0042fbcd

Pop eax
Add ,eax
Stack_top   0042f000
            0042fbcd

保存环境

Stack_top   00000000
            0018FEF4
            00000000
            0018FEF4
            0018FE84
            7EFDE000
            00000000
            00425036
            00000001
            00000287
            0042F000
            0042FBCD





这样就返回vm_entry,改变esi了
看到这,相信大家应该有很多爆破的思路了吧

0x11 结束语
就这样,先写到这里



pklong007 发表于 2018-3-27 17:19:01

好贴,菜鸟来学习了。

飞天 发表于 2018-3-27 18:48:46

支持楼主分享好的分析文章。

0xcb 发表于 2018-3-28 20:39:04

先读一遍学习下,等忙过去了,自己实践实践,感谢分享

ADYYADYY 发表于 2018-4-4 15:05:59

        PYG有你更精彩!

xxhaishixx 发表于 2018-4-5 23:49:54

估计没几个人看得懂。很详细,不过3.x的重构代码比这个要复杂多了。

Bu弃 发表于 2018-4-8 18:14:59

一脸懵逼的进来,一脸懵逼的出去。看不懂,还需学习。膜拜下。

gujin162 发表于 2018-4-11 08:25:51

还需学习。膜拜

killer5 发表于 2018-5-8 18:29:16

非常感谢分享,给力

517724473 发表于 2018-5-18 21:13:02

谢您的分享谢谢您的分享
页: [1] 2 3
查看完整版本: 谈谈vmp的还原(2)