注册表检测

虚拟机软件会在系统注册表中留下特定键值,可通过查询这些注册表项判断是否存在虚拟机。

检测点位

VMware:

1
2
3
4
5
6
HKEY_LOCAL_MACHINE\SOFTWARE\VMware, Inc.\VMware Tools
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\vmdebug
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\vmmouse
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\vmci
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\VMnetAdapter
HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0\Identifier = "VMware Virtual IDE Hard Drive"

VirtualBox:

1
2
3
4
5
6
7
8
HKEY_LOCAL_MACHINE\SOFTWARE\Oracle\VirtualBox Guest Additions
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\VBoxGuest
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\VBoxMouse
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\VBoxService
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\VBoxSF
HKEY_LOCAL_MACHINE\HARDWARE\ACPI\DSDT\VBOX__
HKEY_LOCAL_MACHINE\HARDWARE\ACPI\FADT\VBOX__
HKEY_LOCAL_MACHINE\HARDWARE\ACPI\RSDT\VBOX__

Parallels:

1
2
3
4
5
HKEY_LOCAL_MACHINE\SOFTWARE\Parallels
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\prl_tools
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\prl_sound
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\prl_vid
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\prl_dd

检测代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 检测VMware注册表项
BOOL CheckVMRegistry() {
HKEY hKey;
const WCHAR* vmRegistryPaths[] = {
L"SOFTWARE\\VMware, Inc.\\VMware Tools",
L"SOFTWARE\\Oracle\\VirtualBox Guest Additions",
L"SYSTEM\\CurrentControlSet\\Services\\VBoxGuest",
L"SYSTEM\\CurrentControlSet\\Services\\vmdebug",
L"SYSTEM\\CurrentControlSet\\Services\\vmmouse",
L"HARDWARE\\ACPI\\DSDT\\VBOX__",
L"HARDWARE\\ACPI\\FADT\\VBOX__",
L"HARDWARE\\ACPI\\RSDT\\VBOX__"
};

for (int i = 0; i < _countof(vmRegistryPaths); i++) {
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, vmRegistryPaths[i], 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
RegCloseHandle(hKey);
return TRUE;
}
}
return FALSE;
}

进程检测

虚拟机软件通常会在客户机(Guest OS)中运行一些特定的进程,这些进程用于提供虚拟机与宿主机之间的集成服务。

检测点位

VMware 进程

1
2
3
4
5
vmware.exe - VMware 主程序
vmware-vmx.exe - VMware 虚拟机进程
vmware-tray.exe - VMware 托盘程序
vmware-user.exe - VMware 用户服务
vmtoolsd.exe - VMware Tools 守护进程

VirtualBox 进程

1
2
3
4
VBoxService.exe - VirtualBox 服务
VBoxTray.exe - VirtualBox 托盘程序
VBoxHeadless.exe - VirtualBox 无头模式进程
VBoxControl.exe - VirtualBox 控制程序

Parallels 进程

1
2
3
4
prl_cc.exe - Parallels 控制中心
prl_tools.exe - Parallels 工具
prl_srv.exe - Parallels 服务
prl_disp_service.exe - Parallels 显示服务

检测代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
#include <stdio.h>

// 虚拟机相关进程名列表(宽字符)
const WCHAR* g_vmProcesses[] = {
L"vmware.exe", // VMware主程序
L"vmware-vmx.exe", // VMware虚拟机进程
L"VBoxService.exe", // VirtualBox服务
L"VBoxTray.exe", // VirtualBox托盘程序
L"VBoxHeadless.exe", // VirtualBox无头模式
L"prl_cc.exe", // Parallels虚拟机
L"prl_tools.exe", // Parallels工具
L"vmware-authd.exe", // VMware认证服务
L"VBoxManage.exe" // VirtualBox命令行工具
};

// 检测是否存在虚拟机相关进程
BOOL DetectVMProcesses() {
// 创建系统进程快照
HANDLE hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnapshot == INVALID_HANDLE_VALUE) {
printf("创建进程快照失败,错误码: %d\n", GetLastError());
return FALSE;
}

PROCESSENTRY32W processEntry = {0};
processEntry.dwSize = sizeof(PROCESSENTRY32W);

// 获取第一个进程信息
if (!Process32FirstW(hProcessSnapshot, &processEntry)) {
printf("获取进程信息失败,错误码: %d\n", GetLastError());
CloseHandle(hProcessSnapshot);
return FALSE;
}

// 遍历所有进程
do {
// 比对当前进程名与虚拟机进程列表
for (size_t i = 0; i < _countof(g_vmProcesses); i++) {
// 不区分大小写比较宽字符字符串
if (_wcsicmp(processEntry.szExeFile, g_vmProcesses[i]) == 0) {
wprintf(L"检测到虚拟机进程: %s (PID: %d)\n",
processEntry.szExeFile,
processEntry.th32ProcessID);
CloseHandle(hProcessSnapshot);
return TRUE;
}
}
} while (Process32NextW(hProcessSnapshot, &processEntry));

// 清理资源
CloseHandle(hProcessSnapshot);
return FALSE;
}

文件系统检测

虚拟机软件的安装目录、系统文件或环境变量会留下痕迹。

检测点位

VMware 文件

1
2
3
4
5
6
7
8
C:\Program Files\VMware\VMware Tools\
C:\Windows\System32\drivers\vmmouse.sys
C:\Windows\System32\drivers\vm3dmp.sys
C:\Windows\System32\drivers\vmci.sys
C:\Windows\System32\drivers\vmx86.sys
C:\Windows\System32\vmtray.dll
C:\Windows\System32\vmGuestLib.dll
C:\Windows\System32\vmhgfs.dll

VirtualBox 文件

1
2
3
4
5
6
7
8
C:\Program Files\Oracle\VirtualBox Guest Additions\
C:\Windows\System32\drivers\VBoxGuest.sys
C:\Windows\System32\drivers\VBoxMouse.sys
C:\Windows\System32\drivers\VBoxSF.sys
C:\Windows\System32\drivers\VBoxVideo.sys
C:\Windows\System32\VBoxControl.exe
C:\Windows\System32\VBoxDisp.dll
C:\Windows\System32\VBoxHook.dll

Parallels 文件

1
2
3
4
5
6
7
8
C:\Program Files\Parallels\
C:\Windows\System32\drivers\prl_eth.sys
C:\Windows\System32\drivers\prl_fs.sys
C:\Windows\System32\drivers\prl_mouf.sys
C:\Windows\System32\drivers\prl_pv.sys
C:\Windows\System32\drivers\prl_sound.sys
C:\Windows\System32\drivers\prl_tg.sys
C:\Windows\System32\drivers\prl_vid.sys

检测代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
BOOL CheckVMFiles() {
const WCHAR* vmFiles[] = {
L"C:\\Program Files\\VMware\\VMware Tools\\",
L"C:\\Program Files\\Oracle\\VirtualBox Guest Additions\\",
L"C:\\Windows\\System32\\drivers\\vmmouse.sys",
L"C:\\Windows\\System32\\drivers\\vm3dmp.sys",
L"C:\\Windows\\System32\\drivers\\vmtray.dll",
L"C:\\Windows\\System32\\drivers\\VBoxMouse.sys",
L"C:\\Windows\\System32\\drivers\\VBoxGuest.sys",
L"C:\\Windows\\System32\\drivers\\prl_sound.sys" // Parallels
};

for (int i = 0; i < _countof(vmFiles); i++) {
if (GetFileAttributesW(vmFiles[i]) != INVALID_FILE_ATTRIBUTES) {
return TRUE;
}
}
return FALSE;
}

服务检测

虚拟机会安装一些特定的服务。

检测点位

VMware 服务
VMware Physical Disk Helper Service
VMware Tools
vmicheartbeat
vmickvpexchange
vmicrdv
vmicshutdown
vmictimesync
vmicvmsession
vmicvss

VirtualBox 服务
VBoxService
VBoxGuest
VBoxMouse
VBoxSF

Parallels 服务
prl_tools
prl_sound
prl_dd
prl_vid
prl_disp_service

检测代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
BOOL CheckVMServices() {
SC_HANDLE scManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
if (!scManager) return FALSE;

const WCHAR* vmServices[] = {
L"VBoxService",
L"VBoxGuest",
L"VMware Physical Disk Helper Service",
L"VMware Tools",
L"vmicheartbeat",
L"vmicshutdown",
L"vmictimesync",
L"PrlTools", // Parallels
L"prl_sound" // Parallels
};

for (int i = 0; i < _countof(vmServices); i++) {
SC_HANDLE service = OpenServiceW(scManager, vmServices[i], SERVICE_QUERY_STATUS);
if (service) {
CloseServiceHandle(service);
CloseServiceHandle(scManager);
return TRUE;
}
}

CloseServiceHandle(scManager);
return FALSE;
}

硬件检测

虚拟机的虚拟硬件(如主板、网卡、磁盘控制器等)会包含特定标识,可通过枚举硬件信息识别。

检测点位

硬件标识符

1
2
3
4
5
6
7
PCI\VEN_80EE&DEV_CAFE          VirtualBox 显卡
PCI\VEN_15AD&DEV_0405 VMware SVGA 显卡
PCI\VEN_15AD&DEV_0740 VMware VMXNET3 网卡
PCI\VEN_15AD&DEV_07E0 VMware PVSCSI 控制器
PCI\VEN_1AB8&DEV_4000 Parallels 网卡
PCI\VEN_1AF4&DEV_1000 VirtIO 网卡 (QEMU/KVM)
PCI\VEN_1AF4&DEV_1041 VirtIO 块设备 (QEMU/KVM)

检测代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <windows.h>
#include <setupapi.h>
#include <initguid.h>
#include <devguid.h>
#include <stdio.h>
#pragma comment(lib, "setupapi.lib")

// 检查设备名称是否包含虚拟机特征字符串
BOOL CheckDeviceName(HDEVINFO hDevInfo, SP_DEVINFO_DATA* pDevInfoData) {
TCHAR szDeviceName[256] = {0};
if (!SetupDiGetDeviceRegistryProperty(
hDevInfo, pDevInfoData, SPDRP_FRIENDLYNAME,
NULL, (PBYTE)szDeviceName, sizeof(szDeviceName), NULL)) {
// 尝试读取另一种名称属性
SetupDiGetDeviceRegistryProperty(
hDevInfo, pDevInfoData, SPDRP_DEVICEDESC,
NULL, (PBYTE)szDeviceName, sizeof(szDeviceName), NULL);
}

// 检查虚拟机特征字符串
if (_tcschr(szDeviceName, _T('VMware')) ||
_tcschr(szDeviceName, _T('VirtualBox')) ||
_tcschr(szDeviceName, _T('QEMU')) ||
_tcschr(szDeviceName, _T('VirtIO'))) {
_tprintf(_T("检测到虚拟设备: %s\n"), szDeviceName);
return TRUE;
}
return FALSE;
}

// 枚举设备检测虚拟机
BOOL DetectVMByDevice() {
// 枚举磁盘控制器(GUID_DEVINTERFACE_DISK)
HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_DISK, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hDevInfo == INVALID_HANDLE_VALUE) return FALSE;

SP_DEVINFO_DATA devInfoData = {0};
devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

for (DWORD i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &devInfoData); i++) {
if (CheckDeviceName(hDevInfo, &devInfoData)) {
SetupDiDestroyDeviceInfoList(hDevInfo);
return TRUE;
}
}

SetupDiDestroyDeviceInfoList(hDevInfo);
return FALSE;
}

WMI检测

通过 Windows 管理规范(WMI)查询系统信息,虚拟机的硬件 / 系统描述会包含特征。

检测点位

查询WMIWin32_ComputerSystemWin32_BaseBoard
Win32_ComputerSystem.ManufacturerVMware返回VMware, Inc.VirtualBox返回Oracle Corporation
Win32_BaseBoard.Product:虚拟机通常返回Virtual Machine或厂商名(如 VMware Virtual Platform

检测代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")

BOOL CheckVMWMI() {
HRESULT hres;

// 初始化COM
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres)) return FALSE;

// 设置COM安全级别
hres = CoInitializeSecurity(NULL, -1, NULL, NULL,
RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);

// 创建WMI连接
IWbemLocator* pLoc = NULL;
hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID*)&pLoc);

IWbemServices* pSvc = NULL;
hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc);

// 执行查询
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_ComputerSystem"),
WBEM_FLAG_FORWARD_ONLY, NULL, &pEnumerator);

IWbemClassObject* pclsObj = NULL;
ULONG uReturn = 0;
BOOL isVM = FALSE;

while (pEnumerator) {
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if (0 == uReturn) break;

VARIANT vtManufacturer, vtModel;
VariantInit(&vtManufacturer);
VariantInit(&vtModel);

hr = pclsObj->Get(L"Manufacturer", 0, &vtManufacturer, 0, 0);
hr = pclsObj->Get(L"Model", 0, &vtModel, 0, 0);

// 检查制造商和型号
if (VT_BSTR == vtManufacturer.vt && VT_BSTR == vtModel.vt) {
if (wcsstr(vtManufacturer.bstrVal, L"VMware") ||
wcsstr(vtModel.bstrVal, L"VirtualBox") ||
wcsstr(vtManufacturer.bstrVal, L"innotek") || // VirtualBox旧名称
wcsstr(vtModel.bstrVal, L"Virtual Machine") ||
wcsstr(vtManufacturer.bstrVal, L"Parallels")) {
isVM = TRUE;
}
}

VariantClear(&vtManufacturer);
VariantClear(&vtModel);
pclsObj->Release();

if (isVM) break;
}

// 清理资源
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
CoUninitialize();

return isVM;
}

CPU 指令与行为检测

通过执行特定 CPU 指令(如 CPUID),虚拟机的返回结果与物理机存在差异。

检测点位

1.CPUID指令特征执行CPUID指令(功能号0x40000000及以上),虚拟机可能返回特定厂商字符串:
VMwareCPUID返回VMwareVMware
VirtualBox:返回 VBoxVBox
2.时间戳差异虚拟机中某些指令的执行时间与物理机不同(如 RDTSC 指令),可通过测量指令耗时判断是否在虚拟机中运行。

检测代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <cstdint>
#include <stdio.h>

// 执行CPUID指令并获取结果
void cpuid(uint32_t eax, uint32_t* eax_out, uint32_t* ebx_out,
uint32_t* ecx_out, uint32_t* edx_out) {
__asm {
mov eax, [eax]
cpuid
mov [eax_out], eax
mov [ebx_out], ebx
mov [ecx_out], ecx
mov [edx_out], edx
}
}

// 通过CPUID检测虚拟机
BOOL DetectVMByCPUID() {
uint32_t eax, ebx, ecx, edx;
char vendor[13] = {0};

// 查询厂商ID(CPUID eax=0)
cpuid(0, &eax, &ebx, &ecx, &edx);
*(uint32_t*)&vendor[0] = ebx;
*(uint32_t*)&vendor[4] = edx;
*(uint32_t*)&vendor[8] = ecx;

// 检查虚拟机特定厂商字符串
if (strcmp(vendor, "VMwareVMware") == 0) {
printf("CPUID检测到VMware\n");
return TRUE;
}
if (strcmp(vendor, "VBoxVBox") == 0) {
printf("CPUID检测到VirtualBox\n");
return TRUE;
}
if (strcmp(vendor, "KVMKVMKVM") == 0) {
printf("CPUID检测到KVM/QEMU\n");
return TRUE;
}

return FALSE;
}

虚拟机官网

更具体的信息可以去查阅官网。
1.VMware
全球官网:https://www.vmware.com/
提供 Workstation Pro(Windows/Linux)、Fusion(macOS)等产品,覆盖个人和企业级虚拟化解决方案。
2.VirtualBox
官方网站:https://www.virtualbox.org/
3.Parallels
全球官网:https://www.parallels.com/