先上代码:
#pragma warning (disable : 4996)
#include <wdm.h>
#include <intrin.h>
PHYSICAL_ADDRESS MmGetPhysicalAddress(PVOID BaseAddress);
#define IA32_FEATURE_CONTROL 0x3A
#define BOOL unsigned char
// 0000000080050033
// 1000 0000 0000 0101 0000 0000 0011 0011
struct _STRUCT_CR0 {
unsigned int PE : 1;
unsigned int MP : 1;
unsigned int EM : 1;
unsigned int TS : 1;
unsigned int NOUSE1 : 1;
unsigned int NE : 1;
unsigned int RESERVED1 : 10;
unsigned int WP : 1;
unsigned int NOUSE2 : 1;
unsigned int AM : 1;
unsigned int RESERVED2 : 10;
unsigned int NW : 1;
unsigned int CD : 1;
unsigned int PG : 1;
unsigned int RESERVED3 : 32;
};
PVOID virtualAddress = NULL;
BOOL startSuccess = FALSE;
NTSTATUS StartVirtualTechnology()
{
NTSTATUS Status = STATUS_SUCCESS;
unsigned __int64 _cr4 = 0;
PHYSICAL_ADDRESS pPhysical = {0};
unsigned char ret = 0;
_cr4 = __readcr4(); // bit13 0010 0000 0000 0000 0x2000
_cr4 = _cr4 | 0x2000;
__writecr4(_cr4);
virtualAddress = ExAllocatePoolWithTag(NonPagedPool,0x1000,'vmx');
RtlZeroMemory(virtualAddress,0x1000);
pPhysical = MmGetPhysicalAddress(virtualAddress);
ret = __vmx_on((unsigned __int64*) & pPhysical.QuadPart);
if (ret)
{
if (ret == 1)
{
KdPrintEx((77, 0, "VMXON操作失败,当前 VMCS 的 VM-instruction error field 中提供了扩展状态。\r\n"));
goto Fail;
}
else if (ret == 2)
{
KdPrintEx((77, 0, "VMXON操作失败,无可用状态。\r\n"));
goto Fail;
}
}
else
{
KdPrintEx((77, 0, "VMXON 成功\r\n"));
}
return Status;
Fail:
_cr4 = __readcr4(); // bit13 1101 0000 0000 0000 0xFFFFFFFFFFFFDFFF
_cr4 = _cr4 & 0xFFFFFFFFFFFFDFFF;
__writecr4(_cr4);
ExFreePoolWithTag(virtualAddress, 'vmx');
return STATUS_UNSUCCESSFUL;
}
NTSTATUS StoptVirtualTechnology()
{
NTSTATUS Status = STATUS_SUCCESS;
unsigned __int64 _cr4 = 0;
KdPrintEx((77, 0, "StoptVirtualTechnology 关闭VMX\r\n"));
__vmx_off();
_cr4 = __readcr4(); // bit13 1101 0000 0000 0000 0xFFFFFFFFFFFFDFFF
_cr4 = _cr4 & 0xFFFFFFFFFFFFDFFF;
__writecr4(_cr4);
ExFreePoolWithTag(virtualAddress,'vmx');
return Status;
}
NTSTATUS checkCpu()
{
NTSTATUS Status = STATUS_SUCCESS;
int cpuidRet[4] = {0};
unsigned __int64 _cr0 = 0;
unsigned __int64 _cr4 = 0;
unsigned __int64 _msr = 0;
__cpuid(cpuidRet,1);
if (cpuidRet[2] & 0x20) // bit5 0000 0000 0010 0000 | 0020
{
KdPrintEx((77, 0, "checkCpu 支持VT\r\n"));
}
else
{
KdPrintEx((77, 0, "checkCpu 不支持VT\r\n"));
Status = STATUS_UNSUCCESSFUL;
return Status;
}
_cr0 = __readcr0();
_cr4 = __readcr4(); // bit13 0000 0010 0000 0000 0000 0x2000
if (!(_cr0 & 0x1) || !(_cr0 & 0x80000000) || !(_cr0 & 0x20))
{
KdPrintEx((77, 0, "checkCpu BIOS未开启VT\r\n"));
//KdPrintEx((77, 0, "checkCpu cr0 [%p]\r\n", (unsigned __int64*)_cr0));
Status = STATUS_UNSUCCESSFUL;
return Status;
}
else
{
KdPrintEx((77, 0, "checkCpu BIOS已开启VT\r\n"));
}
if (_cr4 & 0x2000)
{
KdPrintEx((77, 0, "checkCpu VT被占用\r\n"));
Status = STATUS_UNSUCCESSFUL;
return Status;
}
else
{
KdPrintEx((77, 0, "checkCpu VT未被占用\r\n"));
}
_msr = __readmsr(IA32_FEATURE_CONTROL);
if (!(_msr & 0x1))
{
KdPrintEx((77, 0, "checkCpu VMXON 一般保护异常\r\n"));
Status = STATUS_UNSUCCESSFUL;
return Status;
}
else
{
KdPrintEx((77, 0, "checkCpu VMXON 没有一般保护异常\r\n"));
}
return Status;
}
VOID
unloadDriver(
_In_ struct _DRIVER_OBJECT* DriverObject
)
{
UNREFERENCED_PARAMETER(DriverObject);
KdPrintEx((77, 0, "Driver unload\r\n"));
if (startSuccess)
{
StoptVirtualTechnology();
}
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING Name)
{
NTSTATUS Status = STATUS_SUCCESS;
UNREFERENCED_PARAMETER(Name);
UNREFERENCED_PARAMETER(Status);
DriverObject->DriverUnload = unloadDriver;
KdPrintEx((77,0,"Driver Entry\r\n"));
Status = checkCpu();
if (NT_SUCCESS(Status))
{
Status = StartVirtualTechnology();
if (NT_SUCCESS(Status))
{
startSuccess = TRUE;
}
}
return STATUS_SUCCESS;
}
对着手册对是否支持VT进行检查是支持的,但是调用VMXON并未成功。
↑这是运行后Windbg的输出
目标机为 windows 10 1903 x64
谢谢!
【以下回答由 ChatGPT 生成】
删除掉与问题无关的说明性文字后的最终问题:
"我在使用C语言学习虚拟化技术(VT)时遇到了一个问题。尽管我按照手册进行检查,我的代码调用VMXON却失败。我使用的是Windows 10 1903 x64系统。这是我的代码:"
```c
PHYSICAL_ADDRESS MmGetPhysicalAddress(PVOID BaseAddress);
// ...
PVOID virtualAddress = NULL; BOOL startSuccess = FALSE;
NTSTATUS StartVirtualTechnology() { // ...
return Status;
}
NTSTATUS StoptVirtualTechnology() { // ...
return Status;
}
NTSTATUS checkCpu() { // ...
return Status;
}
VOID unloadDriver( In struct _DRIVER_OBJECT* DriverObject ) { // ...
if (startSuccess)
{
StoptVirtualTechnology();
}
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,
通过阅读文档得知VMXON提供的内存空间前几个字节是有固定结构的。
前四个字节需要设置为VMCS修订标识符