VT 是先开为大,谁先开谁上层,谁上层 谁权限大。
1 判断是否支持 VMX
intel 白皮书 第3卷
传入 参数eax =1, 返回值 ecx 的第5位 = 1 则 surpported VMX。
使用 x32dbg 测试:
测试结果: 支持!
开启进入 VMX操作的准备工作:
即:
Cr4.[13] =1 ;不然会产生一个 非法代码异常
这个相当于一把锁,软件可操作:使用VT过程中 这个不能改动,默认一般没开,需要手动开开启;待VT结束,就可以将此位 置为0。
MSR 3Ah 的 0,1,2 位 必须 是1 ;否则会产生保护异常。
第0 位 如果被请0 则表示 在BIOS 中被禁用。而且 只能在开机的时候修改,在关机复位之前都不能修改。
此外 VMX 还要求这些位在过程中固定值为1:
所以 CR0.[PE]、 CR0.[PG] 必须为 1; 标识着处于页保护模式,VMX 在此模式中支持。
2 MSR
后面添加的特殊寄存器 都是MSR; 不同 CPU 对应不同数目的MSR。
要用的时候去查就行了
总结 并梳理代码:
DriverEntry.c:
#include "stdafx.h"
EXTERN_C void Asm_xx();
EXTERN_C BOOLEAN IsVTEnabled();
VOID DriverUnLoad(PDRIVER_OBJECT driver)
{
__asm
{
int 3;
}
DbgPrint("Driver is unloading...r ");
}
NTSTATUS DriverEntry(
PDRIVER_OBJECT driver ,
PUNICODE_STRING RegistryPath)
{
IsVTEnabled(); // 这个 函数检测 是否 开启并支持 VMX;
DbgPrint("Driver Entered! ");
driver->DriverUnload = DriverUnLoad;
return STATUS_SUCCESS;
}
Check.cpp
#include "stdafx.h"
BOOLEAN IsVTEnabled()
{
ULONG uRet_EAX, uRet_RCX,uRet_EDX,uRet_EBX;
_CPUID_ECX uCPUID;
_CR0 uCr0;
_CR4 uCr4;
IA32_FEATURE_CONTROL_MSR msr;
// 1. check CPUID .[5] VMXON is enabled?
Asm_CPUID(1,&uRet_EAX,&uRet_EBX,&uRet_RCX,&uRet_EDX); // eax-->1 ; cpuid; check retRegValues;
*((PULONG)&uCPUID) = uRet_RCX;
if(uCPUID.VMX !=1)
{
Log("ERROR:当前 CPU 不支持VT",0);
return FALSE;
}
// 2. check MSR 3ah
*((PULONG)&msr) = (ULONG) Asm_ReadMsr(MSR_IA32_FEATURE_CONTROL);// 0x3ah
if(msr.Lock!=1)
{
Log("ERROR:VT 指令未被锁定",0);
return FALSE;
}
// 3. check CR0CR4
*((PULONG)&uCr0) = Asm_GetCr0();
*((PULONG)&uCr4) = Asm_GetCr4();
if(uCr0.PE!=1 || uCr0.PG!=1 || uCr0.NE!=1)
{
Log("ERROR:这个CPU 所处的环境不是页保护模式",0);
return FALSE;
}
if(uCr4.VMXE ==1)
{
Log("ERROR:这个CPU 已经开启了VT,可能有别的驱动占用;请检查关闭再试!",0);
return FALSE;
}
else
{
// 这里 可以手动开启;也可以后面封装函数开启;
}
Log("Checked, the Env is Prepared!",0);
return TRUE;
}
// 还有一些使用汇编封装的函数; 这里篇幅限制就不贴了。
结果展示:
感谢 周壑老师的讲解