最可靠方式是先调用__cpuid(0)确认支持,再查0x40000000叶子获取vendor ID(如"VMwareVMware"),匹配整数而非字符串;VirtualBox不实现该叶子,需fallback至DMI/SMBIOS或设备型号等辅助信号。

直接查 CPUID 叶子 0x40000000 是最轻量、最可靠的起点,只要返回的 vendor ID 匹配 "VMwareVMware" 或 "VirtualBox"(注意:VirtualBox 实际不填该字段,需 fallback),就能高置信判定;单靠设备名、注册表或进程列表容易被绕过或误报。
用 __cpuid 读取 VMware 的硬编码 vendor ID
VMware 在 CPUID 扩展叶子 0x40000000 中固定写入 12 字节字符串 "VMwareVMware",物理 CPU 绝不会返回这个值,因此无误报。调用前必须先确认 CPUID 基础支持:
- 先调用
__cpuid(info, 0),若info[0] == 0,说明 CPU 不支持 CPUID,直接跳过 - 再调用
__cpuid(info, 0x40000000)(MSVC)或__cpuid_count(0x40000000, 0, a, b, c, d)(GCC/Clang) - vendor ID 存在
info[1](EBX)、info[2](ECX)、info[3](EDX)中,按小端拼接为 12 字节:EBX 是低 4 字节,“VMwa” →0x61774d56 - 别用
strcmp比字符串,直接比整数更安全:info[1] == 0x61774d56 && info[2] == 0x7265566d && info[3] == 0x6d4d5672(对应 "VMwareVMware")
VirtualBox 没有 CPUID vendor ID,改查 DMI 和设备模型
VirtualBox 不实现 0x40000000 叶子,返回 EAX=0,此时不能认为“不是虚拟机”,而应 fallback 到其他信号。Linux 下优先读 /sys/class/dmi/id/product_name 或 /sys/class/dmi/id/sys_vendor;Windows 下查 WMI Win32_ComputerSystem 的 Manufacturer 和 Model 字段:
- 常见匹配值:
"innotek GmbH"(旧版 VBox)、"Oracle Corporation"(新版)、"VirtualBox"(Model 字段) - Linux 用户态可直接读
/sys/class/dmi/id/下文件,无需 root;但某些加固镜像(如 Cloud-init 镜像)会清空这些字段,返回空字符串 - Windows 上若 WMI 不可用(如 WinPE、容器、权限受限),可退到注册表路径
HKEY_LOCAL_MACHINE\SYSTEM\HardwareConfig\Current,读SystemBiosVersion,其中常含"VirtualBox"
辅助验证:查 SCSI/IDE 设备型号字符串(Linux 专用)
这是 VirtualBox 最难屏蔽的痕迹之一,适合 Linux 环境下交叉验证。它不依赖 root 权限,且比 CPUID 更稳定(因为设备模拟层更难动态隐藏):
- 读
/proc/scsi/scsi:VMware 通常显示Vendor: VMware, Model: VMware Virtual S SCSI - 读
/proc/ide/hd*/model:VirtualBox 显示VBOX HARDDISK(注意空格和大小写) - 用
lspci -v输出过滤"VirtualBox Graphics Adapter"或"VMware SVGA",但该命令依赖外部工具,不适合嵌入式或最小系统 - 注意:部分云环境(如 Azure Nested Virtualization)可能透传真实 PCI 设备,导致该方法失效;仅作辅助,不可单独依赖
为什么不能只看进程名或注册表键?
这类检测方式极易被绕过,且在现代环境中可靠性急剧下降:
-
vmtoolsd.exe或VBoxService.exe进程名可被重命名、不启动,或根本未安装增强工具 - 注册表路径
HKEY_LOCAL_MACHINE\Software\Microsoft\Virtual Machine\Guest是旧版 Virtual PC 痕迹,VMware/VirtualBox 均不写入 - 设备管理器中“VMware SATA Controller”等名称可通过驱动签名伪造或禁用设备模拟来抹除
- 所有纯软件层信号(进程、服务、注册表)都可在启动时由用户手动清理,而 CPUID 和 DMI 是固件/微码级特征,更难篡改
真正难处理的是那些主动隐藏 CPUID 和 DMI 的环境,比如 AWS Nitro、Azure Shielded VM 或启用了 hypervisor.cpuid.v0 = "FALSE" 的 VMware 配置——这时你得接受“无法确定”,而不是强行用易伪造的指标凑答案。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











