虚拟机的设计
这里说的虚拟机是一种解释执行的系统,类似现在许多解释执行的语言,它可以将自定义的中间字节码当作机器码来执行,仿佛就是在一台机器上执行的一样。而虚拟机保护技术就是基于这样的思想,软件作者通过设计一个虚拟机来执行关键算法和代码,这样,破解人员想要还原出算法,就必须要先对这个解释器进行全方位的分析,最后找出自定义的指令集,才能还原出伪汇编代码,这样使得逆向分析的工作量大大增加,再配合上诸多反跟踪技术,完全是分析人员的噩梦。
框架
1.VstartVM,初始化虚拟机及其必要环境
2.将Bytecode通过VMDispatch分配到各个Handler
3.由Handler来完成一条指令
VstartVM
VstartVM对虚拟机进行初始化,主要包括分配虚拟CPU环境(通常只是所有通用寄存器以及栈)
约定:(在整个循环中总是遵守)
- esp表示当前虚拟栈顶
- edi表示VMContext(寄存器变量)
- esi表示虚拟eip(字节码地址)
- ebp表示真实的栈底
struct VMContext //edi指向这个结构的开头,esp在这个结构的后方
{
DWORD v_eax;
DWORD v_ebx;
DWORD v_ecx;
DWORD v_edx;
DWORD v_esi;
DWORD v_edi;
DWORD v_ebp;
DWORD v_efl;
}
要初始化虚拟机,先将一系列寄存器压栈存储起来,然后分配一个较大的空间用来保存VMContext,之后,然后初始化VMContext,再进行实际的堆栈平衡,跳转到VMDispatcher
示例代码:
VStartVM:
push eax
push ebx
push ecx
push edx
push esi
push edi
push ebp
pushfd
mov esi,offset Bytecode
mov ebp,esp
sub esp,0x200
mov edi,esp
sub esp,0x40
mov eax,dword ptr [ebp]
mov [edi+0x1c],eax
add ebp,4
mov eax,dword ptr [ebp]
mov [edi+0x18],eax
add ebp,4
mov eax,dword ptr [ebp]
mov [edi+0x14],eax
add ebp,4
mov eax,dword ptr [ebp]
mov [edi+0x10],eax
add ebp,4
mov eax,dword ptr [ebp]
mov [edi+0x0c],eax
add ebp,4
mov eax,dword ptr [ebp]
mov [edi+0x08],eax
add ebp,4
mov eax,dword ptr [ebp]
mov [edi+0x04],eax
add ebp,4
mov eax,dword ptr [ebp]
mov [edi],eax
add ebp,4 ;平衡堆栈
jmp VMDispatcher
VMDispatcher
VMDispatcher根据操作码进行Handler的跳转即可
VMDispatcher:
movzx eax,byte ptr [esi]
inc esi
jmp dword ptr [eax*4+JUMPADDR]
Handler
Handler是一段小程序或一段过程,它由VM中的调度器来调用。Handler通常可分为辅助Handler和普通Handler,普通Handler通常对应一条指令,而辅助Handler会在普通Handler中调用,一般是栈操作。
Handler的设计一般有两种思路,一是在辅助Handler中只进行栈操作,然后在普通Handler中栈数据进行处理,这种方式的辅助Handler有如下几种,vPushReg、vPopReg、vPushImm、vPushMem、vPopMem,指令实现如:
vPushReg32:
mov eax,dword ptr [esi]
add esi,4
mov eax,dword ptr [edi+eax]
push eax
ret
vPopReg32:
mov eax,dword ptr [esi]
add esi,4
pop ecx
mov dword ptr [edi+eax],ecx
ret
add_reg1_reg2:
vPushReg32 Reg1_index
vPushReg32 Reg2_index
mov eax,[esp+4]
mov ebx,[esp]
add ebx,eax
add esp,8 ;平衡栈
push ebx
vPopReg32 Reg1_index
ret
另一种实现的辅助Handler如下,vRetReg、vMov_Imm2Reg
vRetReg:
mov eax,dword ptr [esi]
add esi,4
mov eax,dword ptr [edi+eax]
ret
vMov_Imm2Reg:
mov eax,dword ptr [esi]
add esi,4
mov ecx,dword ptr [esi]
add esi,4
mov [esi+eax],ecx
ret
add_reg1_reg2:
vRetReg eax
vRetReg ebx
vMov_Imm2Reg eax,ebx
ret