如何检测我的应用程序是否在虚拟机中运行?

问题描述 投票:0回答:12

如何检测(.NET 或 Win32)我的应用程序是否在虚拟机中运行?

.net winapi virtualization
12个回答
49
投票

这就是我用的:

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。


20
投票

根据Virtual PC Guy的博文“检测微软虚拟机”,您可以使用WMI来检查主板的制造商。在 PowerShell 中:

 (gwmi Win32_BaseBoard).Manufacturer -eq "Microsoft Corporation"

5
投票

此 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;
    }

4
投票

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;
        }
    }

3
投票

记住你不应该只检查流行的虚拟机型号,来自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


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;
}

2
投票

对于较低级别的测试,我建议查看 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/


1
投票

我发现确定我的 C# 应用程序是否在 vmware 虚拟机上运行的最简单方法是检查 NIC 卡的 MAC 地址。如果它是 VMware VM,则始终为:00:50:56:XX:YY:ZZ

您可以通过 NIC 进行枚举,如此处所解决。


1
投票
此 C++ 代码将检测 Vmware 产品,例如express、esx、fusion 或工作站

// 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"); }
    

0
投票
我测试了 3 种类型 - VirtualBox、Wmware 和 Huper-V

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;
    

0
投票
我想让这个可配置,所以我将 @RobSiklos 答案转换为 WMI 查询。现在我可以将查询放在配置位置并在需要时更改它。

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


0
投票
来自

超级用户,这是答案: 查看显卡驱动程序。 这是代码:

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
    
© www.soinside.com 2019 - 2024. All rights reserved.