[KMTESTS] Add the ability to detect a virtual machine

This allows the tests to interact directly with hardware
CORE-20078
This commit is contained in:
Dmitry Borisov
2025-04-19 11:07:05 +06:00
committed by Stanislav Motylkov
parent 18290a7b6b
commit 4a3a446ba7
6 changed files with 129 additions and 0 deletions

View File

@@ -44,6 +44,7 @@ list(APPEND KMTEST_DRV_SOURCE
kmtest_drv/kmtest_drv.c
kmtest_drv/structs.c
kmtest_drv/testlist.c
kmtest_drv/vm_detect.c
example/Example.c
example/KernelType.c
@@ -119,6 +120,13 @@ list(APPEND KMTEST_DRV_SOURCE
kmtest_drv/kmtest_drv.rc)
if(ARCH STREQUAL "i386" OR ARCH STREQUAL "amd64")
add_asm_files(KMTEST_DRV_ASM
kmtest_drv/vm_detect.S)
list(APPEND KMTEST_DRV_SOURCE
${KMTEST_DRV_ASM})
endif()
add_library(kmtest_drv MODULE ${KMTEST_DRV_SOURCE})
set_module_type(kmtest_drv kernelmodedriver)
target_link_libraries(kmtest_drv kmtest_printf chkstk memcmp ntoskrnl_vista ${PSEH_LIB})

View File

@@ -156,6 +156,7 @@ typedef struct
extern BOOLEAN KmtIsCheckedBuild;
extern BOOLEAN KmtIsMultiProcessorBuild;
extern BOOLEAN KmtIsVirtualMachine;
extern PCSTR KmtMajorFunctionNames[];
extern PDRIVER_OBJECT KmtDriverObject;

View File

@@ -14,6 +14,7 @@
BOOLEAN KmtIsCheckedBuild;
BOOLEAN KmtIsMultiProcessorBuild;
BOOLEAN KmtIsVirtualMachine;
PCSTR KmtMajorFunctionNames[] =
{
"Create",

View File

@@ -36,6 +36,10 @@ typedef struct _KMT_USER_WORK_LIST
KEVENT NewWorkEvent;
} KMT_USER_WORK_LIST, *PKMT_USER_WORK_LIST;
extern
BOOLEAN
KmtDetectVirtualMachine(VOID);
/* Prototypes */
DRIVER_INITIALIZE DriverEntry;
static DRIVER_UNLOAD DriverUnload;
@@ -88,6 +92,7 @@ DriverEntry(
Prcb = KeGetCurrentPrcb();
KmtIsCheckedBuild = (Prcb->BuildType & PRCB_BUILD_DEBUG) != 0;
KmtIsMultiProcessorBuild = (Prcb->BuildType & PRCB_BUILD_UNIPROCESSOR) == 0;
KmtIsVirtualMachine = KmtDetectVirtualMachine();
KmtDriverObject = DriverObject;
RtlInitUnicodeString(&DeviceName, KMTEST_DEVICE_DRIVER_PATH);

View File

@@ -0,0 +1,53 @@
/*
* PROJECT: ReactOS Kernel-Mode Tests
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: ASM helper functions for VM detection
* COPYRIGHT: Copyright 2025 Dmitry Borisov <di.sean@protonmail.com>
*/
#include <asm.inc>
#define VMWARE_SIGNATURE HEX(564D5868) // 'VMXh'
#define VMWARE_PORT HEX(5658) // 'VX'
.code
/*
* BOOLEAN
* VmIsVMware(VOID);
*/
#ifdef _M_IX86
PUBLIC _VmIsVMware
_VmIsVMware:
push ebx
push ecx
push edx
#else
PUBLIC VmIsVMware
VmIsVMware:
push rbx
push rcx
push rdx
#endif
mov eax, VMWARE_SIGNATURE
mov ebx, 0
mov ecx, 10
mov edx, VMWARE_PORT
in eax, dx
cmp ebx, VMWARE_SIGNATURE
sete al
#ifdef _M_IX86
pop edx
pop ecx
pop ebx
#else
pop rdx
pop rcx
pop rbx
#endif
ret
END

View File

@@ -0,0 +1,61 @@
/*
* PROJECT: ReactOS Kernel-Mode Tests
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: VM detection code
* COPYRIGHT: Copyright 2025 Dmitry Borisov <di.sean@protonmail.com>
*/
/* INCLUDES *******************************************************************/
#include <kmt_test.h>
/* FUNCTIONS ******************************************************************/
#if defined(_M_IX86) || defined(_M_AMD64)
extern BOOLEAN VmIsVMware(VOID);
static
BOOLEAN
VmIsHypervisorPresent(VOID)
{
INT CpuInfo[4];
__cpuid(CpuInfo, 1);
return !!(CpuInfo[2] & 0x80000000);
}
static
BOOLEAN
VmIsVbox(VOID)
{
ULONG PciId, BytesRead;
PCI_SLOT_NUMBER Slot;
Slot.u.AsULONG = 0;
Slot.u.bits.DeviceNumber = 4;
Slot.u.bits.FunctionNumber = 0;
BytesRead = HalGetBusDataByOffset(PCIConfiguration,
0,
Slot.u.AsULONG,
&PciId,
FIELD_OFFSET(PCI_COMMON_HEADER, VendorID),
sizeof(PciId));
return (BytesRead == sizeof(PciId)) && (PciId == 0xCAFE80EE);
}
#endif // defined(_M_IX86) || defined(_M_AMD64)
/*
* NOTE: We make no attempt to support every software in existence.
* Only VMs used by Testman are checked.
*/
BOOLEAN
KmtDetectVirtualMachine(VOID)
{
#if defined(_M_IX86) || defined(_M_AMD64)
return VmIsHypervisorPresent() || VmIsVbox() || VmIsVMware();
#else
return FALSE;
#endif
}