首页
论坛
专栏
课程

[原创]谈谈vmp的还原(2)

waiWH
3
2018-3-25 12:27 2285
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:[EBP-0x4],0x233
75 09            JNZ SHORT zf.00401062
被用来vm的两条指令:
817DFC33020000          cmp dword ptr [ebp-04],00000233
7509                    jnz 00401062

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

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

3.lodsb [disp]
  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]
  
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 [pushfw],result
	
stack_top	fe480296 <==> 0296+result
	
13.lodsb [index]
   pop _context[index]

_context[index] == 0296
stack_top   fffffe48

14.pop a

eax == a <==> fffffe48
stack_top ebp

15.push lodsw[esi]
   push 0x11
	
stack_top	FF48FFEE
		    0018

16.push [pushfw]
stack_top	FFEE0296
	        0018FF48
17.push [pushfw]
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 [index]
   push _context[index] <===> push [pushfw]
	
stack_top    	02870296
		0018FF48
			
24.lodb [index]
   push _context[index] <===> push [pushfw]
	
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 [esp],result
   
stack_top	FF480287
		00000018
			 
29.lodsb [index]
     pop _context[index] <==> result save to context
	
stack_top	0018FF48

28.lodsb [index]
     push _context[index]
   
stack_top	00000000
                0018FF48

以上就是cmp的vm流程

hex如下
0042FB21  6C CD FD CF 05 38 FC 69  l妄?8黫
0042FB29  C4 C1 B6 08 0C 8E 99 57  牧?.帣W
0042FB31  FF FB 99 3B 5D 08 08 57  麢;]W
0042FB39  EE FF B6 08 FA 08 99 99  ???櫃
0042FB41  E9 08 A0 11 99 99 B6 08  ??櫃?
0042FB49  B6 08 99 57 FF FB 99 3B  ?橶麢;
0042FB51  5D 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:[ESI]

PUSH DWORD PTR DS:[EDI+EAX*4]

对应

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:[ESI] PUSH DWORD PTR DS:[EDI+EAX*4]" }
	,{0x1,0x1,0x2,0x0,0x0,0x0,0x0,0x0,"LODS DWORD PTR DS:[ESI] 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:[EAX]" }
	,{0x1,0x3,0x2,0x0,0x1,0x0,0x0,0x0,"POP EAX PUSH DWORD PTR CS:[EAX]" }
	,{0x1,0x3,0x2,0x0,0x2,0x0,0x0,0x0,"POP EAX PUSH DWORD PTR SS:[EAX]" }
	,{0x1,0x3,0x2,0x0,0x3,0x0,0x0,0x0,"POP EAX PUSH DWORD PTR DS:[EAX]" }
	,{0x1,0x3,0x2,0x0,0x4,0x0,0x0,0x0,"POP EAX PUSH DWORD PTR FS:[EAX]" }
	,{0x1,0x3,0x2,0x0,0x5,0x0,0x0,0x0,"POP EAX PUSH DWORD PTR GS:[EAX]" }
	,{0x1,0x2,0x1,0x0,0x0,0x0,0x0,0x0,"LODS BYTE PTR DS:[ESI] PUSH WORD PTR DS:[EDI+EAX*4]" }
	,{0x1,0x1,0x1,0x0,0x0,0x0,0x0,0x0,"LODS WORD PTR DS:[ESI] ADD AX,BX ADD BX,AX PUSH AX"}
	,{0x1,0x1,0x1,0x0,0x1,0x0,0x0,0x0,"LODS WORD PTR DS:[ESI] ADD AX,BX ADD BX,AX CWDE PUSH EAX"}
	,{0x1,0x3,0x1,0x0,0x0,0x0,0x0,0x0,"POP EDX PUSH WORD PTR ES:[EDX]" }
	,{0x1,0x3,0x1,0x0,0x1,0x0,0x0,0x0,"POP EDX PUSH WORD PTR CS:[EDX]" }
	,{0x1,0x3,0x1,0x0,0x2,0x0,0x0,0x0,"POP EDX PUSH WORD PTR SS:[EDX]" }
	,{0x1,0x3,0x1,0x0,0x3,0x0,0x0,0x0,"POP EDX PUSH WORD PTR DS:[EDX]" }
	,{0x1,0x3,0x1,0x0,0x4,0x0,0x0,0x0,"POP EDX PUSH WORD PTR FS:[EDX]" }
	,{0x1,0x3,0x1,0x0,0x5,0x0,0x0,0x0,"POP EDX PUSH WORD PTR GS:[EDX]" }
	,{0x1,0x2,0x0,0x0,0x0,0x0,0x0,0x0,"LODS BYTE PTR DS:[ESI] ADD AL,BL ADD BL,AL MOV AL,BYTE PTR DS:[EDI+EAX*4] PUSH AX"}
	,{0x1,0x2,0x0,0x0,0x1,0x0,0x0,0x0,"LODS BYTE PTR DS:[ESI] ADD AL,BL ADD BL,AL MOV AL,BYTE PTR DS:[EDI+EAX*4+0x1] PUSH AX"}
	,{0x1,0x1,0x0,0x0,0x0,0x0,0x0,0x0,"LODS BYTE PTR DS:[ESI] ADD AL,BL ADD BL,AL PUSH AX"}
	,{0x1,0x1,0x0,0x0,0x1,0x0,0x0,0x0,"LODS BYTE PTR DS:[ESI] 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:[EDX] PUSH AX"}
	,{0x1,0x3,0x0,0x0,0x1,0x0,0x0,0x0,"POP EAX MOV AL,BYTE PTR CS:[EDX] PUSH AX"}
	,{0x1,0x3,0x0,0x0,0x2,0x0,0x0,0x0,"POP EAX MOV AL,BYTE PTR SS:[EDX] PUSH AX"}
	,{0x1,0x3,0x0,0x0,0x3,0x0,0x0,0x0,"POP EAX MOV AL,BYTE PTR DS:[EDX] PUSH AX"}
	,{0x1,0x3,0x0,0x0,0x4,0x0,0x0,0x0,"POP EAX MOV AL,BYTE PTR FS:[EDX] PUSH AX"}
	,{0x1,0x3,0x0,0x0,0x5,0x0,0x0,0x0,"POP EAX MOV AL,BYTE PTR GS:[EDX] 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:[ESI] ADD AL,BL ADD BL,AL POP DWORD PTR DS:[EDI+EAX*4]"}
	,{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:[EAX]"}
	,{0x2,0x3,0x2,0x0,0x1,0x0,0x0,0x0,"POP EAX POP DWORD PTR CS:[EAX]"}
	,{0x2,0x3,0x2,0x0,0x2,0x0,0x0,0x0,"POP EAX POP DWORD PTR SS:[EAX]" }
	,{0x2,0x3,0x2,0x0,0x3,0x0,0x0,0x0,"POP EAX POP DWORD PTR DS:[EAX]" }
	,{0x2,0x3,0x2,0x0,0x4,0x0,0x0,0x0,"POP EAX POP DWORD PTR FS:[EAX]" }
	,{0x2,0x3,0x2,0x0,0x5,0x0,0x0,0x0,"POP EAX POP DWORD PTR GS:[EAX]" }
	,{0x2,0x2,0x1,0x0,0x0,0x0,0x0,0x0,"LODS BYTE PTR DS:[ESI] POP WORD PTR DS:[EDI+EAX*4]" }
	,{0x2,0x1,0x1,0x0,0x0,0x0,0x0,0x0,"POP AX" }
	,{0x2,0x3,0x1,0x0,0x0,0x0,0x0,0x0,"POP EAX POP WORD PTR ES:[EAX]" }
	,{0x2,0x3,0x1,0x0,0x1,0x0,0x0,0x0,"POP EAX POP WORD PTR CS:[EAX]" }
	,{0x2,0x3,0x1,0x0,0x2,0x0,0x0,0x0,"POP EAX POP WORD PTR SS:[EAX]" }
	,{0x2,0x3,0x1,0x0,0x3,0x0,0x0,0x0,"POP EAX POP WORD PTR DS:[EAX]" }
	,{0x2,0x3,0x1,0x0,0x4,0x0,0x0,0x0,"POP EAX POP WORD PTR FS:[EAX]" }
	,{0x2,0x3,0x1,0x0,0x5,0x0,0x0,0x0,"POP EAX POP WORD PTR GS:[EAX]" }
	,{0x2,0x2,0x0,0x0,0x0,0x0,0x0,0x0,"POP DX LODS BYTE PTR DS:[ESI] ADD AL,BL ADD BL,AL MOV BYTE PTR DS:[EDI+EAX*4],DL"}
	,{0x2,0x2,0x0,0x0,0x1,0x0,0x0,0x0,"POP DX LODS BYTE PTR DS:[ESI] ADD AL,BL ADD BL,AL MOV BYTE PTR DS:[EDI+EAX*4+1],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:[EDX],AL"}
	,{0x2,0x3,0x0,0x0,0x1,0x0,0x0,0x0,"POP EDX POP AX MOV BYTE PTR CS:[EDX],AL"}
	,{0x2,0x3,0x0,0x0,0x2,0x0,0x0,0x0,"POP EDX POP AX MOV BYTE PTR SS:[EDX],AL"}
	,{0x2,0x3,0x0,0x0,0x3,0x0,0x0,0x0,"POP EDX POP AX MOV BYTE PTR DS:[EDX],AL"}
	,{0x2,0x3,0x0,0x0,0x4,0x0,0x0,0x0,"POP EDX POP AX MOV BYTE PTR FS:[EDX],AL"}
	,{0x2,0x3,0x0,0x0,0x5,0x0,0x0,0x0,"POP EDX POP AX MOV BYTE PTR GS:[EDX],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:[ESP],EAX"}
	,{0x4,0x0,0x2,0x0,0x1,0x0,0x0,0x0,"POP EAX ADD DWORD PTR SS:[ESP],EAX PUSHFW"}
	,{0x4,0x0,0x1,0x0,0x0,0x0,0x0,0x0,"POP AX ADD DWORD PTR SS:[ESP],AX" }
	,{0x4,0x0,0x1,0x0,0x1,0x0,0x0,0x0,"POP AX ADD DWORD PTR SS:[ESP],AX PUSHFW" }
	,{0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,"POP AX ADD BYTE PTR SS:[ESP],AL" }
	,{0x4,0x0,0x0,0x0,0x1,0x0,0x0,0x0,"POP AX ADD BYTE PTR SS:[ESP],AL PUSHFW" }
	,{0xF6,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"POP EAX NOT EAX NOT DWORD PTR SS:[ESP] AND DWORD PTR SS:[ESP],EAX"}
	,{0xF6,0x0,0x2,0x0,0x1,0x0,0x0,0x0,"POP EAX NOT EAX NOT DWORD PTR SS:[ESP] AND DWORD PTR SS:[ESP],EAX PUSHFW"}
	,{0xF6,0x0,0x1,0x0,0x0,0x0,0x0,0x0,"NOT DWORD PTR SS:[ESP] POP AX AND WORD PTR SS:[ESP],AX" }
	,{0xF6,0x0,0x1,0x0,0x1,0x0,0x0,0x0,"NOT DWORD PTR SS:[ESP] POP AX AND WORD PTR SS:[ESP],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:[ESP]" }
	,{0xB6,0x0,0x3,0x0,0x0,0x0,0x0,0x0,"FILD QWORD PTR SS:[ESP]" }
	,{0xBB,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FLD DWORD PTR SS:[ESP]" }
	,{0xBB,0x0,0x3,0x0,0x0,0x0,0x0,0x0,"FLD QWORD PTR SS:[ESP]" }
	,{0xBB,0x0,0x4,0x0,0x0,0x0,0x0,0x0,"FLD TBYTE PTR SS:[ESP]" }
	,{0xA0,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FADD DWORD PTR SS:[ESP]" }
	,{0xA0,0x0,0x3,0x0,0x0,0x0,0x0,0x0,"FADD QWORD PTR SS:[ESP]" }
	,{0xA4,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FSUB DWORD PTR SS:[ESP]" }
	,{0xA4,0x0,0x3,0x0,0x0,0x0,0x0,0x0,"FSUB QWORD PTR SS:[ESP]" }
	,{0xA5,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FSUBR DWORD PTR SS:[ESP]" }
	,{0xA5,0x0,0x3,0x0,0x0,0x0,0x0,0x0,"FSUBR QWORD PTR SS:[ESP]" }
	,{0xBC,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FSTP DWORD PTR SS:[ESP]" }
	,{0xBC,0x0,0x3,0x0,0x0,0x0,0x0,0x0,"FSTP QWORD PTR SS:[ESP]" }
	,{0xBC,0x0,0x4,0x0,0x0,0x0,0x0,0x0,"FSTP TBYTE PTR SS:[ESP]" }
	,{0xA6,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FDIV DWORD PTR SS:[ESP]" }
	,{0xA6,0x0,0x3,0x0,0x0,0x0,0x0,0x0,"FDIV QWORD PTR SS:[ESP]" }
	,{0xA1,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FMUL DWORD PTR SS:[ESP]" }
	,{0xA1,0x0,0x3,0x0,0x0,0x0,0x0,0x0,"FMUL QWORD PTR SS:[ESP]" }
	,{0xA3,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FCOMP DWORD PTR SS:[ESP]" }
	,{0xA3,0x0,0x3,0x0,0x0,0x0,0x0,0x0,"FCOMP QWORD PTR SS:[ESP]" }
	,{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:[ESP]" }
	,{0xC4,0x0,0x1,0x0,0x0,0x0,0x0,0x0,"FLDCW WORD PTR SS:[ESP]" }
	,{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:[ESP]" }
	,{0xB8,0x0,0x2,0x0,0x0,0x0,0x0,0x0,"FISTP DWORD PTR SS:[ESP]" }
	,{0xB8,0x0,0x3,0x0,0x0,0x0,0x0,0x0,"FISTP QWORD PTR SS:[ESP]" }
};

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[8], *(&off_4CE17C + _esi->_var1_vm_interpreter_mnemonic));
			if ( _esi->_var3_lval == 1 )
			{
				a2a = _lval_disp_imm;
				LOBYTE(v66) = 0;
				sub_409984(&str____4x[1], &a2a, 0, v64);
				System::__linkproc__ LStrCat(&_esi->_esi_hex[8], *v64);
			}
			else if ( _esi->_var3_lval == 2 )
			{
				a2a = _lval_disp_imm;
				LOBYTE(v66) = 0;
				sub_409984(&str____8x[1], &a2a, 0, v67);
				System::__linkproc__ LStrCat(&_esi->_esi_hex[8], *v67);
			}
			if ( _esi->__var4 == 1 )
			{
				a2a = *_esi->_Displacement_Immediate;
				LOBYTE(v66) = 0;
				sub_409984(&str___4x[1], &a2a, 0, v62);
				setAddress(&_esi->_esi_hex[12], *v62);
			}
			else if ( _esi->__var4 == 2 )
			{
				a2a = *_esi->_Displacement_Immediate;
				LOBYTE(v66) = 0;
				sub_409984(&str___8x[1], &a2a, 0, v63);
				setAddress(&_esi->_esi_hex[12], *v63);
			}
		}
		else
		{
			Free_Mem(&_esi->_esi_hex[12]);
		}
		if ( _esi->_var3_lval == 1 )
		{
			if ( _lval_disp_imm & 0xFF00 )
			{
				_vmp_setIndexToStruct( esi, _vmp_getVmHandlerIndex( 1, 1, 1, 0);// LODS WORD PTR DS:[ESI] 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:[ESI] 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:[ESI] 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:[ESI] 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:[ESI] 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:[ESI] 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 )                  // [base]
		{
			*v8->_Displacement_Immediate = (char)_var5_index;
		}
		else if ( _3_lval_type == 1 )             // [base + disp8]
		{
			*v8->_Displacement_Immediate = (short)_var5_index;
		}
		else                                      // [base + disp32]
		{
			*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[0] = 1;
					_rand_type[2] = 1;
					if ( statisticsbinaryis1count(~*v8->_Displacement_Immediate, _3_lval_type) >= 3u )// 统计奇数为 大于3
					{
						_rand_type[1] = 2;
						_rand_type[3] = 2;
					}
					else
					{
						_rand_type[1] = 1;
						_rand_type[3] = 1;
					}
					if ( !(v8->_ispushfw & 2) && *v8->_Displacement_Immediate )
					{
						if ( !(v8->_Displacement_Immediate[0] & 1) )
							_rand_type[2] = 3;
						if ( _3_lval_type == 2 && v8->_Displacement_Immediate[3] >= 0
							|| _3_lval_type == 1 && v8->_Displacement_Immediate[1] >= 0 )
						{
							_rand_type[3] = 4;
						}
					}
					v8->_rand_switch = _rand_type[rand()%4];
					switch ( v8->_rand_switch )
					{
					case 1:
						{
							Vmp_SetEsiStruct(_var1, 1, 1, _3_lval_type, 0, v31 | 2, -1);// LODS DWORD PTR DS:[ESI] PUSH EAX
							Vmp_SetEsiStruct(_var1, 4, 0, _3_lval_type, 0, v31, -1);// POP EAX ADD DWORD PTR SS:[ESP],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:[ESP] AND DWORD PTR SS:[ESP],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:[ESI] 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 )// [base + disp32]
	{
		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:[ESI] PUSH DWORD PTR DS:[EDI+EAX*4]
				Vmp_SetEsiStruct(_var1, 4, 0, 2, 0, v31, -1);//POP EAX ADD DWORD PTR SS:[ESP],EAX
				break;
			}
		case 2:
			{
				Vmp_SetEsiStruct(_var1, 1, 1, 1, 0, v31, -1);//LODS WORD PTR DS:[ESI] PUSH AX
				Vmp_SetEsiStruct(_var1, 1, 2, 1, 10, v31, -1);//LODS BYTE PTR DS:[ESI] PUSH WORD PTR DS:[EDI+EAX*4]
				Vmp_SetEsiStruct(_var1, 4, 0, 2, 0, v31, -1);//POP EAX ADD DWORD PTR SS:[ESP],EAX
				break;
			}
		case 1:
			{
				Vmp_SetEsiStruct(_var1, 1, 2, 2, 10, v31, -1);// LODS BYTE PTR DS:[ESI] PUSH DWORD PTR DS:[EDI+EAX*4]
				Vmp_SetEsiStruct(_var1, 2, 1, 1, 0, v31, -1);// LODS BYTE PTR DS:[ESI] POP WORD PTR DS:[EDI+EAX*4]
				Vmp_SetEsiStruct(_var1, 1, 1, 1, 0, v31, -1);// LODS WORD PTR DS:[ESI] PUSH AX
				Vmp_SetEsiStruct(_var1, 4, 0, 2, 0, v31, -1);// POP EAX ADD DWORD PTR SS:[ESP],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)[esp] += [[esi]]
				{
					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:[ESI] PUSH EAX
					Vmp_SetEsiStruct(_var1, 1, 3, _3_lval_type, 0, v31, -1);// POP EAX PUSH DWORD PTR SS:[EAX]
					Vmp_SetEsiStruct(_var1, 1, 1, _3_lval_type, -v23, v31 | 4, -1);// LODS DWORD PTR DS:[ESI] 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:[ESP],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 == 0  return
		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:[ESI] 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;
				}										// 到时候好从[esi]读出补码或反码
				// 在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:[ESI] PUSH EAX
					}
					if ( _operand->About_RegType_8_16_32 == 1 )
					{
						_vmp_SetEsiStruct(*(a5 - 4), 1, 1, 1, 0, 0, -1);// LODS WORD PTR DS:[ESI] 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:[ESI] POP DWORD PTR DS:[EDI+EAX*4]
					}
					else
					{
						_vmp_SetEsiStruct(*(a5 - 4), 1, 2, _Type, _operand->SecondVar_Trans_ModRM_rm_Index, 0, -1);// LODS BYTE PTR DS:[ESI] PUSH DWORD PTR DS:[EDI+EAX*4]
					}
					if ( _Type < 3 && _operand->SecondVar_Trans_ModRM_rm_Index == 4 && !(_a2 & 1) )
						sub_486A30(_Type, a5);//ADD DWORD PTR SS:[ESP],LODSD DS:[ESI]
				}
			}
			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:[ESP],LODSD DS:[ESI]
					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:[eax]
				{
					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:[EAX]
					}
					else
					{
						v27 = _get_prefix(__operand_index, a5) & 0x7F;
						_vmp_SetEsiStruct(*(a5 - 4), 1, 3, _Type, v27, 0, -1);//POP EAX PUSH DWORD PTR prefix:[EAX]
					}
				}
			}
		}
	}
	return ret;
}

结合刚开始给的,则有先读operand[1]

注意到:

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:[ESP] AND DWORD PTR SS:[ESP],EAX"}
这个0xf6取得蛮有意思的


在说说jcc


注意到


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


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

push add1

push 0
add [add1],0  
stack_top   0042fbcd

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

lodw [not(0x40)]
push not(0x40
lodb [index]
push _context[index] ----> push eflags
stack_top ffbf0287


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

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

losb [4]
push 4
stack_top   fb9b0004
            fbcd0042
                0042

Lodb [index]
Push _context[_index]
Stack_top   00040040
            0042fb9b
            0042fbcd

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

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


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


Lodsb [index]
Push ax  --> 0
Stack_top   fe98000
            Fb9b0018
            Fbcd0042
            Ff480042


Lodsb [index]
Push _context[index] ---> 0x4
Stack_top   00000004
            0018fe98
Pop eax   --->       eax == 0x4
add [esp],eax
stack_top   0018FE98(addr_42fb9b)
            0042FB9B
            0042FBCD
注意到这里,很重要
vmp先压了两个地址然后取eflags运算进行shr,通常会得到4
那么这个4是用来干什么的
我们看看这两个地址的内容
恩,没错。实现了分支
在注意到这里的地址

Stack_top   0018fe9c(addr_0042fbcd)
            0042fb9b
            0042fbcd

Pop eax
Push [eax]
Stack_top   0042fbcd
            0042fb9b
            0042fbcd

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

Pop eax
Add [esp],eax
Stack_top   0042f000
            0042fbcd

保存环境

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


这样就返回vm_entry,改变esi了

看到这,相信大家应该有很多爆破的思路了吧


0x11 结束语

就这样,先写到这里





[推荐]看雪企服平台,提供APP等级保护加固等安全服务!

最后于 2019-1-11 19:09 被kanxue编辑 ,原因:
最新回复 (8)
destnity 2018-3-25 13:18
2

0

感谢大神分享,看不懂呀,太难了。
AperOdry 2018-3-25 14:23
3

0

mark  收藏学习 
Ps:除了膜拜还能有什么  !
fatecaster 1 2018-3-25 14:28
4

0

感谢分享
jjjackup 2018-3-25 17:54
5

0

感谢分享。
chixiaojie 2018-3-25 18:42
6

0

这是留给博士看的吗?我们小学生根本看不懂。
yangya 2018-3-25 22:26
7

0

mark下
zbzb 2018-3-26 10:18
8

0

不错,  支持下.  多年前就听过大牛们玩vmp/tmd主程序,还能加出不带垃圾代码的vmp试练品.
junkboy 2019-1-11 20:16
9

0

#寻宝大战#祝看雪19岁快乐!
返回