如何检测(.NET 或 Win32)我的应用程序是否在虚拟机中运行?
这就是我用的:
using (var searcher = new System.Management.ManagementObjectSearcher("Select * from Win32_ComputerSystem"))
{
using (var items = searcher.Get())
{
foreach (var item in items)
{
string manufacturer = item["Manufacturer"].ToString().ToLower();
if ((manufacturer == "microsoft corporation" && item["Model"].ToString().ToUpperInvariant().Contains("VIRTUAL"))
|| manufacturer.Contains("vmware")
|| item["Model"].ToString() == "VirtualBox")
{
return true;
}
}
}
}
return false;
编辑 2014-12-02:更新了代码,使其不再将 Microsoft Surface Pro 检测为虚拟机。感谢 Erik Funkenbusch 指出了这一点。
编辑 2017-06-29:更新了代码,以便它还检查
HypervisorPresent
属性的值。
编辑 2018-02-05:删除了对
HypervisorPresent
属性的检查,因为它不正确。如果在 Hyper-V 服务器上的主机操作系统上运行,则此属性可能返回 true。
根据Virtual PC Guy的博文“检测微软虚拟机”,您可以使用WMI来检查主板的制造商。在 PowerShell 中:
(gwmi Win32_BaseBoard).Manufacturer -eq "Microsoft Corporation"
此 C 函数将检测 VM Guest OS: (在Windows上测试,使用Visual Studio编译)
#include <intrin.h>
bool isGuestOSVM()
{
unsigned int cpuInfo[4];
__cpuid((int*)cpuInfo,1);
return ((cpuInfo[2] >> 31) & 1) == 1;
}
Jay Abuzi 在 powershell 中展示了解决方案。这与 C# 函数相同:
/// <summary>
/// Detect if this OS runs in a virtual machine
///
/// http://blogs.msdn.com/b/virtual_pc_guy/archive/2005/10/27/484479.aspx
///
/// Microsoft themselves say you can see that by looking at the motherboard via wmi
/// </summary>
/// <returns>false</returns> if it runs on a fysical machine
public bool DetectVirtualMachine()
{
bool result = false;
const string MICROSOFTCORPORATION ="microsoft corporation";
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2","SELECT * FROM Win32_BaseBoard");
foreach (ManagementObject queryObj in searcher.Get())
{
result = queryObj["Manufacturer"].ToString().ToLower() == MICROSOFTCORPORATION.ToLower();
}
return result;
}
catch (ManagementException ex)
{
return result;
}
}
记住你不应该只检查流行的虚拟机型号,来自wmi的制造商名称,你还应该检查现实和虚拟化之间的差异。
VM没有太多功能。
1) 检查CPU温度信息是否可用
wmic /namespace:\\root\WMI path MSAcpi_ThermalZoneTemperature get CurrentTemperature
//On Real PC
//CurrentTemperature
//3147
//On VM
//Node - Admin
//Error:
//Description not supported
在 vmware、virtualbox、windows 服务器、app.any.run 沙箱上测试。
2) Win32_PortConnector
Get-WmiObject Win32_PortConnector
//On Vm it is null
//On real pc it looks something like that
Tag : Port Connector 0
ConnectorType : {23, 3}
SerialNumber :
ExternalReferenceDesignator :
PortType : 2
public static bool isVirtualMachine()
{
const string MICROSOFTCORPORATION = "microsoft corporation";
const string VMWARE = "vmware";
foreach (var item in new ManagementObjectSearcher("Select * from Win32_ComputerSystem").Get())
{
string manufacturer = item["Manufacturer"].ToString().ToLower();
// Check the Manufacturer (eg: vmware, inc)
if (manufacturer.Contains(MICROSOFTCORPORATION) || manufacturer.Contains(VMWARE))
{
return true;
}
// Also, check the model (eg: VMware Virtual Platform)
if (item["Model"] != null)
{
string model = item["Model"].ToString().ToLower();
if (model.Contains(MICROSOFTCORPORATION) || model.Contains(VMWARE))
{
return true;
}
}
}
return false;
}
对于较低级别的测试,我建议查看 ScoopyNG [1]。它是已知的低级、运行良好的虚拟机检测方法的集合,尽管有点过时。
如果您确实想依赖其他东西,例如安装的工具(VM* Additions),那么这些更容易“伪造”。
这篇 [2] 博客文章也有一个非常好的概述,从低级 asm 内容开始,检查特定的 DLL、文件路径和注册表项。
[1] http://trapkit.de/research/vmm/scoopyng/index.html
[2] http://securitykitten.github.io/vm-checking-and-detecting/
// VMWareDetector.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "windows.h"
#include <conio.h>
void CheckVM(void);
int main()
{
CheckVM();
_getch();
return 0;
}
void CheckVM(void)
{
unsigned int a, b;
__try {
__asm {
// save register values on the stack
push eax
push ebx
push ecx
push edx
// perform fingerprint
mov eax, 'VMXh' // VMware magic value (0x564D5868)
mov ecx, 0Ah // special version cmd (0x0a)
mov dx, 'VX' // special VMware I/O port (0x5658)
in eax, dx // special I/O cmd
mov a, ebx // data
mov b, ecx // data (eax gets also modified
// but will not be evaluated)
// restore register values from the stack
pop edx
pop ecx
pop ebx
pop eax
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {}
printf("\n[+] Debug : [ a=%x ; b=%d ]\n\n", a, b);
if (a == 'VMXh') { // is the value equal to the VMware magic value?
printf("Result : VMware detected\nVersion : ");
if (b == 1)
printf("Express\n\n");
else if (b == 2)
printf("ESX\n\n");
else if (b == 3)
printf("GSX\n\n");
else if (b == 4)
printf("Workstation\n\n");
else
printf("unknown version\n\n");
}
else
printf("Result : Not Detected\n\n");
}
foreach (var mo in "Select * from Win32_ComputerSystem")
{
var model = (string)mo["Model"];
if (model == "VirtualBox" ||
model == "Virtual Machine" ||
model.StartsWith("VMware"))
{
return true;
}
}
return false;
private static bool IsVirtual()
{
using (var searcher = new System
.Management
.ManagementObjectSearcher(@"SELECT * from Win32_ComputerSystem
WHERE (Manufacturer LIKE '%microsoft corporation%' AND Model LIKE '%virtual%')
OR Manufacturer LIKE '%vmware%'
OR Model LIKE '%VirtualBox%'"))
{
using (System.Management.ManagementObjectCollection items = searcher.Get())
{
if (items.Count > 0)
{
return true;
}
}
}
return false;
}
WQL 参考:
https://learn.microsoft.com/en-us/windows/win32/wmisdk/wql-sql-for-wmi
Dim driver As New ManagementObjectSearcher("Select * from Win32_PnPSignedDriver")
Dim driver_info As ManagementObject
Dim name As String
For Each driver_info In driver.Get()
caption = driver_info("DeviceName").ToString()
If caption.Contains("Standard") and caption.Contains("VGA") Then
' it's virtual machine
' do anything you need
End If
Next