VMProtect基础教程(一)VM堆栈

2016-12-21 17:34    112人浏览    标签:,     0 条评论

VMProtect的VM是基于堆栈的虚拟家,理解好VM的堆栈空间划分和操作,是理解整个VM运行的基础。VMProtect2.12加壳程序是从TLS开始运行的,首先点击OD的options菜单,修改Startup and exit选项,让OD中断在TLS callback里。加壳程序运行后,VMP初始化VM,并进入DISPATCH部分。这里就以初始化后的堆栈为例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
EDI=0013F8BC
EBP=0013F9B0
CPU Stack
Locked    Value      ASCII Comments
0013F8BC   009539E8  9.          ;这里是EDI指向
0013F8C0   00950000  ...
0013F8C4   00150000  ...
0013F8C8   00000080  ...
0013F8CC   019314D6 
0013F8D0   0013F8A8  .
0013F8D4   7C92E920   |
0013F8D8   00000000  ....
0013F8DC   00000000  ....
0013F8E0   00000000  ....
0013F8E4   FFFFFFFF
0013F8E8   7C98FEFF  |    
0013F8EC   7C00ADE7  .|
0013F8F0   00000000  ....
0013F8F4   00150000  ...
0013F8F8   0013F6F0  .
0013F8FC   0013F940  @.
0013F900   0013F944  D.
0013F904   7C92E920   |
0013F908   7C9301E0  |
0013F90C   FFFFFFFF
0013F910   7C9301DB  |   
0013F914   7C9314D6  |   
0013F918   7C931514  |  
0013F91C   7C99E120   |
0013F920   7C9314EA  |   
0013F924   5ADF1158  XZ
0013F928   00000001  ...
0013F92C   00000000  ....
0013F930   7FFDA000  .
0013F934   7FFDF000  .
0013F938   00158070  p.
0013F93C   0013F890  .
0013F940   00000000  ....
0013F944   0043D759  YC.  
0013F948   0000E9ED  ..
0013F94C   409B0002  .@
0013F950   00000020   ...
0013F954   0013F9CC  .
0013F958   0013F96C  l.
0013F95C   0043E9ED  C.   
0013F960   000359F4  Y.
0013F964   00000020   ...
0013F968   004253CD  SB.  
0013F96C   409B0000  ..@
0013F970   00000020   ...
0013F974   0013F9CC  .
0013F978   0013F98C  .
0013F97C   00000000  ....          ;这里是EBP指向
0013F980   00000000  ....          ;这里是VM初始化保存的各个寄存器
0013F984   00000246  F..
0013F988   000359F4  Y.
0013F98C   00000020   ...
0013F990   00000000  ....
0013F994   0013F9CC  .
0013F998   004253CD  SB.  
0013F99C   000359F4  Y.
0013F9A0   00400000  ..@. 
0013F9A4   0013F9C0  .
0013F9A8   C456C619  V          ;这里是VMP的2个加密数据
0013F9AC   2EF6420A  .B.
0013F9B0   7C92118A  |    ; RETURN to ntdll.7C92118A  ;(这里是TLS进来时的栈顶)

VM的堆栈一共使用61个DWORD,上下分别有2个堆栈指针,下面为EBP指针,上面为EDI指针。下面是VM初始化时,给EDI和EBP指针赋值后的堆栈。

在这里把上面的EDI指向的堆栈称为EDISTACK,把EBP指向的堆栈称为EBPSTACK。在VM中,EBPSTACK是运算区,各类数据的运算操作在这里完成;EDISTACK是存储区包括长期存储数据和临时存储EBPSTACK的运算数。

接下来来看一条数据移动伪指令:

1
2
3
4
5
6
7
8
9
0043DC19  |.  F6D8          NEG AL                                 
0043DC26  |.  C0C8 07       ROR AL,7                                
0043DC34  |.  2C 20         SUB AL,20                               
0043DC41  |.  24 3C         AND AL,3C                             
0043E080  |$  8B55 00       MOV EDX,DWORD PTR SS:[EBP]             
0043E086  |.  83C5 04       ADD EBP,4                             
0043D3D7  /> /891438        MOV DWORD PTR DS:[EDI+EAX],EDX

指令说明:把1个dword的数据从EBPSTAK栈顶移动到EDISTACK,使用EAX作为偏移量。

在EDISTACK的数据移动中,使用[EDI+EAX]的方式来存储与获取各个值。通过计算不同的EAX的值,可以到达EDISTACK中不同位置。在计算EAX值时,实际真正计算的是AL的值,例如:
AL最大值: AL=00时[EDI+EAX]=[0013F8BC+00000000]=0013F8BC
AL最小值:AL=FF时[EDI+EAX]=[0013F8BC+000000FF]=0013F9BB
这一对最值就是使用[EDI+EAX]可以读取的上下限。但是,在VM的AL值计算过程中,最后有一条AND AL,0x3C指令,0x3C=00111100bit由于这条指令的限制,无论AL为任何值(从00000000bit到11111111bit),通过AND操作,只能有1111bit的活动空间大小,1111bit相当于16,所以EDISTACK最多可以读取16个dword;由于00111100bit最后两个00位的限制,任何数字与它AND后,后两位都必然为0,变成与4对齐的值,说明VM都是按照0013F8BC 0013F8C0 0013F8C4 0013F8C8这样的4对齐来读取。在读取时,VM可以读取byte word dword,但是VM将不会去读取0013F8BE。
由于EDISTACK堆栈向下发展,EBPSTACK堆栈向上发展,EDISTACK有0x3C控制着范围,而EBPSTACK是操作区,没有硬性的范围控制。为了预防两个空间相撞,在每次往EBPSTACK移动数据后,VM都有相应的边界检测指令如下:

1
2
3
0043CE5A  |.  8D47 50       LEA EAX,[EDI+50]              
0043EE5D  |.  39C5          CMP EBP,EAX                            
0043F08C  |.^\0F87 29F6FFFF JA 0043E6BB 

执行此指令后得到的结果是“>”,如果是“<”, 也就是EBPSTACK栈顶已经到达[EDI+50]位置,VM将会重新分配堆栈空间。0x50的偏移量比0x3C的偏移量多5个dword的缓冲区。

相关资讯

留言评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注

慧都2016年终促销
系统推荐