VT 学习的问题,VMXON错误

先上代码:

#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并未成功。

img

↑这是运行后Windbg的输出

目标机为 windows 10 1903 x64

谢谢!

【以下回答由 ChatGPT 生成】

删除掉与问题无关的说明性文字后的最终问题:

"我在使用C语言学习虚拟化技术(VT)时遇到了一个问题。尽管我按照手册进行检查,我的代码调用VMXON却失败。我使用的是Windows 10 1903 x64系统。这是我的代码:"

```c

pragma warning (disable : 4996)

include

include

PHYSICAL_ADDRESS MmGetPhysicalAddress(PVOID BaseAddress);

define IA32_FEATURE_CONTROL 0x3A

define BOOL unsigned char

// ...

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提供的内存空间前几个字节是有固定结构的。

img

img

前四个字节需要设置为VMCS修订标识符

img