》 根据 进入VM_EXIT 的原因处理异常
// 获取 进入 VMExit 的 原因
ExitReason = Vmx_VmRead(VM_EXIT_REASON);
// 获取导致 VMExit 的 Opcode 的长度
ExitInstructionLength = Vmx_VmRead(VM_EXIT_INSTRUCTION_LEN);
// 获取关键 现场环境
g_GuestRegs.eflags = Vmx_VmRead(GUEST_EFLAGS);
g_GuestRegs.esp = Vmx_VmRead(GUEST_RSP);
g_GuestRegs.eip = Vmx_VmRead(GUEST_EIP);
?
// 根据 Exit 原因类型,进行处理:
switch(ExitReason)
{
case EXIT_REASON_CPUID:// Handle CPUID
HandleCPUID();
Log("EXIT_REASON_CPUID",0);
break;
case EXIT_REASON_VMCALL:// Handle VMCALL
HandleVmCall();
Log("EXIT_REASON_VMCALL",0);
break;
case EXIT_REASON_CR_ACCESS:
HandleCrAccess();
Log("EXIT_REASON_CR_ACCESS!",0);
break;
default:// As so far, the Exit_Reasons not gonna deal!
Log("No setted Handler of Reason:%p",ExitReason);
__asm int 3;
}
//Resume: 设置Guest 继续执行的位置环境
// prepare for VM Resuming
GuestResumeEIP = g_GuestRegs.eip + ExitInstructionLength;
Vmx_VmWrite(GUEST_RIP, GuestResumeEIP);
Vmx_VmWrite(GUEST_RSP, g_GuestRegs.esp);
Vmx_VmWrite(GUEST_RFLAGS, g_GuestRegs.eflags);
save the context to resume the VM
__asm{
// 保存来时的环境
mov g_GuestRegs.eax, eax
mov g_GuestRegs.ecx, ecx
mov g_GuestRegs.edx, edx
mov g_GuestRegs.ebx, ebx
mov g_GuestRegs.esp, esp
mov g_GuestRegs.ebp, ebp
mov g_GuestRegs.esi, esi
mov g_GuestRegs.edi, edi
?
pushfd
pop eax
mov g_GuestRegs.eflags, eax
?
mov ax, fs// 通过切换段选择子,刷新段选择子对应的隐藏部分
mov fs, ax
mov ax, gs
mov gs, ax
}
// **************************************************
?
// between save and restore!
// we can run the handler!!!*******************
VMMEntryPointEbd();// In this function , it concluds the main operations.
?
// **************************************************
// Resume
__asm{
// 恢复来时的环境
mov eax, g_GuestRegs.eax
mov ecx, g_GuestRegs.ecx
mov edx, g_GuestRegs.edx
mov ebx, g_GuestRegs.ebx
mov esp, g_GuestRegs.esp
mov ebp, g_GuestRegs.ebp
mov esi, g_GuestRegs.esi
mov edi, g_GuestRegs.edi
?
// vmresume -- Guest 继续执行 , 这里硬编码而不是call vmx_vmresume()的好处是可以避免栈的变化
__emit 0x0f
__emit 0x01
__emit 0xc3
}
When Calls StopVt Func, set the VtEnd FlagVar
NTSTATUS StopVirtualTechnology()
{
_CR4 uCr4;
if(g_VMXCPU.bVTStartSuccess)
{
g_vmcall_arg = ‘SVT‘;
__asm{
pushad
pushfd
mov g_stop_esp, esp
mov g_stop_eip, offset LLL
}
Vmx_VmCall();// to query VmOff() from Handler System
// when it handled ,it ret to LLL.
LLL:
__asm{
popfd
popad
}
g_VMXCPU.bVTStartSuccess = FALSE;
*((PULONG)&uCr4) = Asm_GetCr4();
uCr4.VMXE = 0;
Asm_SetCr4(*((PULONG)&uCr4));
?
ExFreePool(g_VMXCPU.pVMXONRegion);
ExFreePool(g_VMXCPU.pVMCSRegion);
ExFreePool(g_VMXCPU.pStack);
?
Log("SUCCESS:关闭VT成功!",0);
Log("SUCCESS:现在这个CPU退出了VMX模式.",0);
}
?
return STATUS_SUCCESS;
}
In handler frame(see 1), the handle func:
void HandleVmCall()
{
// A global FlagVar to Verify End or not
if (g_vmcall_arg == ‘SVT‘)
{// Done the End Flag, Then End VM
Vmx_VmClear(g_VMXCPU.pVMCSRegion_PA.LowPart,g_VMXCPU.pVMCSRegion_PA.HighPart);
Vmx_VmxOff();// Turn off the VM
__asm{
mov esp, g_stop_esp
jmp g_stop_eip// return to the StopVT func()/*
//inside the func,after VmCall
}
} else {
__asm int 3
}
}
原文:https://www.cnblogs.com/leibso-cy/p/11755655.html