- 注册时间
 - 2010-7-27
 
- 最后登录
 - 2017-5-28
 
- 在线时间
 - 5 小时
 
 
 
 
 
编程入门 
  
	- 魔鬼币
 - 541 
 
 
 
 | 
 
 
1、检测你的CPU是否支持VMX 
MOV EAX,1 
CPUID 
检测ECX的第5位,如果为1则支持VMX 
 
2、初始化VMXON region 
pVMXONRegion = MmAllocateNonCachedMemory( 4096 ); 
RtlZeroMemory( pVMXONRegion, 4096 ); 
PHYSICAL_ADDRESS       PhysicalVMXONRegionPtr=MmGetPhysicalAddress( pVMXONRegion ); 
__asm 
{ 
MOV             ECX, IA32_VMX_BASIC_MSR_CODE //0x480 
RDMSR 
LEA              EBX, vmxBasicMsr 
MOV             [EBX+4], EDX 
MOV             [EBX], EAX 
} 
*(pVMXONRegion) = vmxBasicMsr.RevId; 
3、设置VMXE位(CR4) 
CR4_REG                                         cr4_reg = {0}; 
__asm 
{ 
PUSH     EAX 
_emit      0x0F       // MOV   EAX, CR4 
_emit      0x20 
_emit      0xE0 
MOV             cr4_reg, EAX 
POP        EAX 
} 
cr4_reg.VMXE = 1; 
__asm 
{ 
PUSH     EAX 
MOV             EAX, cr4_reg 
_emit      0x0F       // MOV   CR4, EAX 
_emit      0x22 
_emit      0xE0 
POP        EAX 
} 
 
4、执行VMXON指令  
__asm 
{ 
PUSH     DWORD PTR PhysicalVMXONRegionPtr.HighPart 
PUSH     DWORD PTR PhysicalVMXONRegionPtr.LowPart 
_emit      0xF3       // VMXON [ESP] 
_emit      0x0F 
_emit      0xC7 
_emit      0x34 
_emit      0x24 
PUSHFD 
POP        eFlags 
ADD              ESP, 8 
} 
if( eFlags.CF == 1 ) 
{ 
Log( "ERROR : VMXON operation failed." , 0 ); 
return 0; 
} 
//到这里说明已经进入了VMX模式,并且工作在ROOT下了 
 
5、初始化VMCS region 
//这是个4K大小的内存块 
ULONG *pVMCSRegion = MmAllocateNonCachedMemory( 4096 ); 
RtlZeroMemory( pVMCSRegion, 4096 ); 
PHYSICAL_ADDRESS  PhysicalVMCSRegionPtr = MmGetPhysicalAddress( pVMCSRegion ); 
*(pVMCSRegion) = vmxBasicMsr.RevId; 
__asm 
{ 
PUSH     DWORD PTR PhysicalVMCSRegionPtr.HighPart 
PUSH     DWORD PTR PhysicalVMCSRegionPtr.LowPart 
_emit      0x66       // VMCLEAR [ESP] 
_emit      0x0F 
_emit      0xc7 
_emit      0x34 
_emit      0x24 
ADD       ESP, 8 
PUSHFD 
POP        eFlags 
} 
if( eFlags.CF != 0 || eFlags.ZF != 0 ) 
{ 
Log( "ERROR : VMCLEAR operation failed." , 0 ); 
return 0; 
} 
//到这里,说明VMCS region初始化完成了 
 
6、装载VMCS region 
__asm 
{ 
PUSH     DWORD PTR PhysicalVMCSRegionPtr.HighPart 
PUSH     DWORD PTR PhysicalVMCSRegionPtr.LowPart 
_emit      0x0F       // VMPTRLD [ESP] 
_emit      0xC7 
_emit      0x34 
_emit      0x24 
ADD       ESP, 8 
} 
 
7、设置VMCS region中的相关域  
这些域包括: 
A、Guest的各个段寄存器的selector,base,limit,access right 
B、Host的各个段寄存器的selector,base,limit,access right 
C、Guest的CR0,CR3,CR4,IDTR,GDTR,LDTR,Rflag,SYSENTER_CS,SYSENTER_EIP,SYSENTER_ESP 
D、Host的CR0,CR3,CR4,IDTR,GDTR,LDTR,Rflag,SYSENTER_CS,SYSENTER_EIP,SYSENTER_ESP 
如: 
USHORT    seg_selector = 0; 
__asm  MOV      seg_selector, ES 
Log( "Setting Guest ES Selector" , seg_selector ); 
WriteVMCS( 0x00000800, seg_selector ); 
//Guest CS selector                                                             00000802H 
__asm  MOV      seg_selector, CS 
Log( "Setting Guest CS Selector" , seg_selector ); 
WriteVMCS( 0x00000802, seg_selector ); 
 
E、Exception bitmap 
作为调试器,我们需要拦截INT1和INT3中断,因此,Exception bitmap起码要这样设置: 
ULONG        temp32 = 0x00000000; 
SetBit( &temp32, 1 );                                              // Single Step (INT 1) int1 
SetBit( &temp32, 3 );                                              // Software Interrupt (INT 3) 
WriteVMCS( 0x00004004, temp32 ); 
 
F、VMX Abort Error Code域 
这个域需要清成0 
RtlZeroMemory( (pVMCSRegion + 4), 4 ); 
 
G、Guest的ESP和EIP 
WriteVMCS( 0x0000681C, (ULONG)GuestStack ); 
WriteVMCS( 0x0000681E, (ULONG)GuestReturn ); 
 
H、Host的ESP和EIP 
PVOID   HostStack = ExAllocatePoolWithTag( NonPagedPool , 0x8000, 'kSkF' ); 
If(HostStack == NULL) 
{ 
//…出错… 
} 
WriteVMCS( 0x00006C14, ((ULONG)HostStack + 0x7FFF) ); 
WriteVMCS( 0x00006C16, (ULONG)VMExitProc );// VMExitProc就是VMM的程序入口 
 
8、执行VMLAUNCH 
__asm 
{ 
_emit      0x0F       // VMLAUNCH 
_emit      0x01 
_emit      0xC2 
}  
 
// 如果成功,就不会到这里了! 
__asm 
{ 
PUSHFD 
POP        eFlags 
} 
Log( "VMLAUNCH Failure" , 0xDEADDEAD ); 
if( eFlags.CF != 0 || eFlags.ZF != 0 || TRUE ) 
{ 
ULONG  ErrorCode= VMRead_ULONG(0x00004400); 
Log( "VM Instruction Error" , ErrorCode ); 
} 
 
VMMExitProc 
extern "C" 
__declspec( naked ) VOID VMMExitProc( ) 
{ 
__asm CLI  
__asm PUSHAD 
 
  //保存通用寄存器 
__asm MOV GuestEAX, EAX 
__asm MOV GuestEBX, EBX 
__asm MOV GuestECX, ECX 
__asm MOV GuestEDX, EDX 
__asm MOV GuestEDI, EDI 
__asm MOV GuestESI, ESI 
__asm MOV GuestEBP, EBP 
 
  //保存调试寄存器 
__asm  
{ 
push eax 
mov eax,dr0 
mov GuestDr0,eax 
mov eax,dr1 
mov GuestDr1,eax 
mov eax,dr2 
mov GuestDr2,eax 
mov eax,dr3 
mov GuestDr3,eax 
mov eax,dr6 
mov GuestDr6,eax 
pop eax 
} 
 
GuestDr7 = VMRead_ULONG(VMX_VMCS_GUEST_DR7);//0x681A 
GuestEIP = VMRead_ULONG(VMX_VMCS_GUEST_RIP);//0x681E 
GuestEFlags = VMRead_ULONG(VMX_VMCS_GUEST_RFLAGS);//0x6820 
 
//获取本次Exit的详细信息 
ULONG ExitReason = VMRead_ULONG(VMX_VMCS_RO_EXIT_REASON);//0x4402 
ULONG ExitInterruptionInformation = VMRead_ULONG(VMX_VMCS_RO_EXIT_INTERRUPTION_INFO);//0x4404 
ULONG ExitInstructionLength = VMRead_ULONG(VMX_VMCS_RO_EXIT_INSTR_LENGTH);//0x440C 
ULONG ExitQualification = VMRead_ULONG(VMX_VMCS_RO_EXIT_QUALIFICATION);//0x6400 
 
  if(ExitReason==0)//是个Exception 
{ 
int IntrNo = ExitInterruptionInformation & 0xFF; 
if(IntrNo==1 || IntrNo==3)//是INT1或者INT3 
{ 
if(IsMyBreakPoint()) 
{//是我们自己设置的断点 
DoSomeThing(); 
} 
else 
{//我们该向Guest注入一个异常,让Guest的中断处理程序能够继续处理,仿佛一切都没发生 
ULONG InjectIrqInfo = 0x80000300 | IntrNo; 
// 设置 VM-Entry Exception域 
WriteVMCS( VMX_VMCS_CTRL_ENTRY_INSTR_LENGTH, ExitInstructionLength); 
WriteVMCS( VMX_VMCS_CTRL_ENTRY_IRQ_INFO, InjectIrqInfo); 
} 
} 
} 
if(ExitReason==0x12)//VMMCALL 
{//我们用一个VMMCALL指令来通知VMM结束VMX 
if(GuestEAX == 0x12345678)//我们自己约定的规则 
{ 
GuestEIP += ExitInstructionLength; 
goto Exit; 
} 
} 
goto Resume; 
Exit: 
//  关闭VMX. 
DbgPrint("Terminating VMX Mode."); 
__asm 
{ 
_emit 0x0F  // VMXOFF 
_emit 0x01 
_emit 0xC4 
POPAD 
MOV   ESP, GuestESP 
STI 
JMP   GuestEIP 
}  
 
  Resume:     
//  Need to execute the VMRESUME without having changed 
//  the state of the GPR and ESP et cetera. 
__asm 
{ 
push      eax 
mov       eax,GuestDr0 
mov       DR0,eax 
mov       eax,GuestDr1 
mov       DR1,eax 
mov       eax,GuestDr2 
mov       DR2,eax 
mov       eax,GuestDr3 
mov       DR3,eax 
mov       eax,GuestDr6 
mov       DR6,eax 
pop       eax 
POPAD 
MOV   EAX, GuestEAX 
MOV   EBX, GuestEBX 
MOV   ECX, GuestECX 
MOV   EDX, GuestEDX 
MOV   ESI, GuestESI 
MOV   EDI, GuestEDI 
MOV   EBP, GuestEBP 
STI 
_emit 0x0F  // VMRESUME 
_emit 0x01 
_emit 0xC3 
 
//永远不会到这里 
} 
 |   
 
 
 
 |