VM启动框架


VStartVM:
00402230 >    50            PUSH EAX
00402231      53            PUSH EBX
00402232      51            PUSH ECX
00402233      52            PUSH EDX
00402234      56            PUSH ESI
00402235      57            PUSH EDI
00402236      55            PUSH EBP
00402237      9C            PUSHFD
00402238      8B7424 20     MOV ESI,DWORD PTR SS:[ESP+20]   ;参数 字节码开始的地址
0040223C      8BEC          MOV EBP,ESP			    ;ebp就是堆栈
0040223E      81EC 00020000 SUB ESP,200              
00402244      8BFC          MOV EDI,ESP                     edi就是VMContext
00402246      83EC 40       SUB ESP,40
VMDispatcher:
00402249      0FB606        MOVZX EAX,BYTE PTR DS:[ESI]      获得bytecode
0040224C      8D76 01       LEA ESI,DWORD PTR DS:[ESI+1]     跳过这个字节
0040224F      EB 00         JMP SHORT APIhash.00402251       跳刀Handler  这里简写   jmp dword ptr [eax*4+JUMPADDR]
Vbegin:
00402251      8B45 00       MOV EAX,DWORD PTR SS:[EBP]
00402254      8947 1C       MOV DWORD PTR DS:[EDI+1C],EAX     ;v_dfl
00402257      83C5 04       ADD EBP,4		
0040225A      83C5 04       ADD EBP,4	                      ;这里省略  v_ebp   mov [edi+0x18],eax
0040225D      83C5 04       ADD EBP,4 		     	      ;这里省略  v_edi   mov [edi+0x14],eax
00402260      83C5 04       ADD EBP,4                         ;这里省略  v_esi   mov [edi+0x10],eax
00402263      83C5 04       ADD EBP,4                         ;这里省略  v_edx   mov [edi+0x0C],eax
00402266      83C5 04       ADD EBP,4                         ;这里省略  v_ecx   mov [edi+0x08],eax
00402269      83C5 04       ADD EBP,4                         ;这里省略  v_ebx   mov [edi+0x04],eax
0040226C      83C5 04       ADD EBP,4                         ;这里省略  v_eax   mov [edi],eax
0040226F      83C5 04       ADD EBP,4	                      ;这里是省略参数  最开始的返回函数被弹出 
00402272    ^ EB D5         JMP SHORT APIhash.00402249	      ;跳回VMDispatcher:
之后  堆栈就平衡了    	VMContext结构存放在当前使用的堆栈更靠下面的一部分  所以应该避免VMContext被覆盖的情况


正常的话   edi 表示 VMContext 应该 在  ebp表示的堆栈的  上面!    也就是 edi 比 ebp 小很多

但是如果不小很多  的话就会在某条指令后改写  VMContext的内容  所以设计了下面的:

VCheckESP:
00402274      8D87 00010000 LEA EAX,DWORD PTR DS:[EDI+100]      VMContext +0x100  就是往堆栈下走 跟 真实的ESP比 小于继续执行  否则就要执行JL后面的内容
0040227A      3BC5          CMP EAX,EBP
0040227C    ^ 7C D1         JL SHORT APIhash.0040224F
0040227E      8BD7          MOV EDX,EDI                         EDX = VMContext
00402280      8BCC          MOV ECX,ESP                         ECX = 当前假的的ESP 这个就更小了   VMContext在ESP上面
00402282      2BCA          SUB ECX,EDX                         ECX-EDX
00402284      56            PUSH ESI                            保存IP指针            
00402285      8BF4          MOV ESI,ESP                         ESI = 当前IP指针 
00402287      83EC 60       SUB ESP,60                         
0040228A      8BFC          MOV EDI,ESP                         把它赋值给 VMContext
0040228C      57            PUSH EDI                           保存新的edi 地址
0040228D      83EC 40       SUB ESP,40                         假个esp 再往上走
00402290      FC            CLD                                 
00402291      F3:A4         REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]      ESI往上跑
00402293      5F            POP EDI				还原VMContext
00402294      5E            POP ESI                              还原IP指针
00402295    ^ EB B2         JMP SHORT APIhash.00402249
00402297      90            NOP

一些会涉及堆栈的Handler在执行后跳转到VCheckESP判断ESP是否接近 VMContext  如果是就将VMContext赋值到更远的位置存放



原文地址:https://www.cnblogs.com/zcc1414/p/3982542.html