3

mac2026-01-03  8

原理参考 3卷 23.7节等

本节实施流程参考Intel手册: 3卷 31.5节

1 vt整体框架;

 

首先 开锁:

1 开启 Cr4.[VMXE]:

上一节,检测了 VMX 需要的环境;最后一个 CR4.[13/VMXE] 只检测了是否已经被开启(有别的虚拟机);

但是 没有在 CR4.[13/VMXE] ==0 的时候去开启。

所以 这里 开始 开锁;打开 CR4.[13]

放在 驱动加载函数中。

代码:

NTSTATUS StartVirtualTechnology() {_CR4 uCr4;if(!IsVTEnabled()){return STATUS_UNSUCCESSFUL;}*((PULONG)&uCr4) = Asm_GetCr4();// 获取原来的 cr4;uCr4.VMXE =1;// VMXE =1 开启。Asm_SetCr4(*(PULONG)&uCr4); // 设置回去return STATUS_SUCCESS;}

 

 

2开始 进入 VMXON:

接下来的最简流程:(参考白皮书 3卷31.5节)

这里 红色部分是需要实现的部分:

即:

需要申请一块最大4kb对齐的非分页内存;并且 确保大小够(直接申请4kb,先不考虑效率)

用 VMCS revision identifier (在capability MSRs // MSR 480h 的低32位) 初始化 WMXON region (the first 31 bits)

清理 第 31 bit 位0

 

首先需要一开内存来管理 host 信息(cpu 管理;我们提供内存即可)

然后需要设置版本号

代码:

NTSTATUS StartVirtualTechnology() {_CR4 uCr4;_EFLAGS uEflags;if(!IsVTEnabled()){return STATUS_UNSUCCESSFUL;}*((PULONG)&uCr4) = Asm_GetCr4();//get cr4;uCr4.VMXE =1;// VMXE =1 enableAsm_SetCr4(*(PULONG)&uCr4); // setg_VMXCPU.pVMXONRegion = ExAllocatePoolWithTag(NonPagedPool,0x1000,'vmx');// para@3 is digit valueRtlZeroMemory(g_VMXCPU.pVMXONRegion,0x1000);// initial memory*(PULONG)g_VMXCPU.pVMXONRegion =1;//set revision; -- the first 32bits of VMXONRegion; clear the no.32bitg_VMXCPU.pVMXONRegion_PA = MmGetPhysicalAddress(g_VMXCPU.pVMXONRegion);// get physical addressVmx_VmxOn(g_VMXCPU.pVMXONRegion_PA.LowPart,g_VMXCPU.pVMXONRegion_PA.HighPart);*((PULONG)&uEflags) = Asm_GetEflags();if(uEflags.CF!=0)// the flag to identify state of success or not{Log("ERROR:VMXON指令调用失败!",0);ExFreePool(g_VMXCPU.pVMXONRegion);return STATUS_UNSUCCESSFUL;}return STATUS_SUCCESS; }

 

最后 关锁:

1 关闭 VMXOFF:

 

2 恢复 CR4.[VMXE]:

设置 CR4.[13/VMXE] ==0 的时候关闭;

放在驱动卸载函数中

代码:

NTSTATUS StopVirtualTechnology() {_CR4 uCr4;Vmx_VmxOff();*((PULONG)&uCr4) = Asm_GetCr4();// get cr4;uCr4.VMXE =0;// VMXE =0 disableAsm_SetCr4(*(PULONG)&uCr4); // set;// free page; in kernel nonpage its not freed automatic;ExFreePool(g_VMXCPU.pVMXONRegion);return  STATUS_SUCCESS; }

 

 

初步效果:

 

整体代码:

.cpp(开启 、关闭 VMX的函数实现)

#include "stdafx.h"

VMX_CPU g_VMXCPU;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);// 0x3ahif(msr.Lock!=1){Log("ERROR:VT 指令未被锁定",0);return FALSE;}// 3. check CR0\CR4*((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;}NTSTATUS StartVirtualTechnology(){_CR4 uCr4;_EFLAGS uEflags;if(!IsVTEnabled()){return STATUS_UNSUCCESSFUL;}*((PULONG)&uCr4) = Asm_GetCr4();//get cr4;uCr4.VMXE =1;// VMXE =1 enableAsm_SetCr4(*(PULONG)&uCr4); // setg_VMXCPU.pVMXONRegion = ExAllocatePoolWithTag(NonPagedPool,0x1000,'vmx');// para@3 is digit valueRtlZeroMemory(g_VMXCPU.pVMXONRegion,0x1000);// initial memory*(PULONG)g_VMXCPU.pVMXONRegion =1;//set revision; -- the first 32bits of VMXONRegion; clear the no.32bitg_VMXCPU.pVMXONRegion_PA = MmGetPhysicalAddress(g_VMXCPU.pVMXONRegion);// get physical addressVmx_VmxOn(g_VMXCPU.pVMXONRegion_PA.LowPart,g_VMXCPU.pVMXONRegion_PA.HighPart);*((PULONG)&uEflags) = Asm_GetEflags();if(uEflags.CF!=0)// the flag to identify state of success or not{Log("ERROR:VMXON指令调用失败!",0);ExFreePool(g_VMXCPU.pVMXONRegion);return STATUS_UNSUCCESSFUL;}return STATUS_SUCCESS;}NTSTATUS StopVirtualTechnology(){_CR4 uCr4;Vmx_VmxOff();*((PULONG)&uCr4) = Asm_GetCr4();// get cr4;uCr4.VMXE =0;// VMXE =0 disableAsm_SetCr4(*(PULONG)&uCr4); // set;// free page; in kernel nonpage its not freed automatic;ExFreePool(g_VMXCPU.pVMXONRegion);return  STATUS_SUCCESS;

}

.c (驱动文件,调用VMX开启关闭函数)

#include "stdafx.h"

EXTERN_C void Asm_xx();EXTERN_C BOOLEAN IsVTEnabled();EXTERN_C NTSTATUS StartVirtualTechnology();EXTERN_C NTSTATUS StopVirtualTechnology();VOID DriverUnLoad(PDRIVER_OBJECT driver){StopVirtualTechnology();DbgPrint("VT stopping ....!\r\n");DbgPrint("Driver is unloading...r\n");}NTSTATUS DriverEntry(PDRIVER_OBJECT driver ,PUNICODE_STRING RegistryPath){Asm_xx();DbgPrint("Driver Entered!\r\n");StartVirtualTechnology();DbgPrint("VT running....!\r\n");driver->DriverUnload = DriverUnLoad;return STATUS_SUCCESS;}

感谢 周壑老师的讲解

最新回复(0)