2009-01-31 31 views
31

¿Cómo puedo detectar (.NET o Win32) si mi aplicación se está ejecutando en una máquina virtual?¿Cómo detectar si mi aplicación se está ejecutando en una máquina virtual?

+0

Ejecuté una aplicación el otro día, y no se ejecutaría en una máquina virtual ... dijo que no podría. Me preguntaba cómo lo sabía. – Jason

+5

Hay una serie de cosas que no funcionan en las máquinas virtuales: algunas partes de MS SQL Server, C# para dispositivos emulator y * gasp * Virtual PC/Server. Ser capaz de planificar eso en programas y scripts es valioso. –

+1

... por lo tanto, si tiene una dependencia en algo que no funciona en algunos entornos (es decir, VM), debe consultar esa dependencia para ver si funciona en el entorno actual. O tal vez me perdí tu punto? – reuben

Respuesta

17

Según Virtual PC Guy 's blog 'Detecting Microsoft virtual machines', se puede utilizar WMI para comprobar el fabricante de la placa base. En PowerShell:

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

Er, ¿qué hay de las máquinas virtuales que no son de MS? –

+4

Además, como lo mencionó el comentarista @ ErikFunkenbusch en mi respuesta a esta pregunta, esta verificación identificará incorrectamente al MS Surface Pro como máquina virtual. – RobSiklos

+0

Para ser justos, para MS Virtual Machines, la variedad Surface de productos fue lanzada _después_ esta respuesta fue publicada. –

12

Aquí hay un ejemplo de una forma de hacerlo. Sólo funciona con Virtual PC de Microsoft y VMware, pero es un comienzo: http://www.codeproject.com/KB/system/VmDetect.aspx

+0

Eso es muy interesante ... viendo cómo las máquinas reaccionan al uso de comandos de ensamblaje no válidos. ¡Increíble! – Jason

+1

Busqué "detectar si se ejecuta en una máquina virtual" (sin las comillas) en Google y fue el primer resultado. –

+1

En realidad, la mejor manera es la "huella digital de hardware": http://blogs.msdn.com/virtual_pc_guy/archive/2005/10/27/484479.aspx –

0

La manera más fácil que he encontrado para averiguar si mi C# aplicación se está ejecutando en una máquina virtual de VMware o no es comprobar la dirección MAC de la tarjeta (s) de la NIC. Si se trata de una máquina virtual de VMware siempre sería: 00: 50: 56: XX: YY: ZZ

Es posible enumerar las NIC as resolved here.

+4

-1: por supuesto VMware es libre de cambiar su formato de dirección MAC cuando lo desee, sin avisarle por adelantado –

+1

Según http://standards.ieee.org VMWare utiliza: 00:05:69, 00: 0C: 29 , 00: 1C: 14, así como 00:50:56 para la parte de organización de la dirección MAC. Y como dijo @John_Saunders, pueden agregar un nuevo número a la lista cuando lo deseen. –

3

Jay Abuzi mostró la solución en PowerShell. Aquí es lo mismo que aC# función:

/// <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; 
     } 
    } 
+0

Lamentablemente, esta y otras técnicas similares no funcionan en mi sistema W7 que ejecuta un ThinApp de VMWare para probar. ** queryObj.Properties ** son idénticos en ambos entornos. –

+1

@JesseChisholm: no solo eso, sino que informará falsamente que el hardware de Microsoft no vm es una VM, como Surface Pro. Sugeriría que tiene una configuración incorrecta si su ThinApp está virtualizando los datos de WMI. –

+0

@ErikFunkenbusch - El objetivo de ** virtualización ** es que el código no necesita saber ni importa si es en vivo o virtual. Entonces, cada fabricante de VM trabaja muy duro para que sea imposible saberlo. Hasta ahora, la única forma que he encontrado para que mi aplicación lo sepa, es hacer que la ejecución de VM pase en un parámetro de línea de comando diciéndome que me estoy ejecutando virtual. Suspiro. –

36

Esto es lo que yo uso:

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; 

Edición 02/12/2014: Código actualizada de forma que ya no se detecta una superficie Pro Microsoft como Av M. Gracias a Erik Funkenbusch por señalar esto.

Modificar 2017-06-29: Código actualizado para que también compruebe el valor de la propiedad HypervisorPresent.

Editar 2018-02-05: eliminado comprobar para la propiedad HypervisorPresent ya que es incorrecto. Esta propiedad podría volverse verdadera si se ejecuta en las O/S del host en un servidor hyper-V.

+2

Algunas pruebas rápidas parecen que la expresión de prueba se puede simplificar (para una definición de 'simplificado') a 'elemento [" Modelo "]. ToString(). ToLower(). Contiene (" virtual ")'. –

+0

Puede convertir "elementos" como '' IEnumerable '' como este: 'var managementItems = items.OfType ();' para usar con los métodos de extensión 'IEnumerable'. –

+2

Creo que este código detectaría el hardware de la computadora de Microsoft como máquinas virtuales, como Surface Pro. –

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

Lamentablemente, esta y otras técnicas similares no funcionan en mi sistema W7 que ejecuta un ThinApp de VMWare para probar. * queryObj.Properties ** son idénticos en ambos entornos. –

1

Para pruebas de nivel inferior, recomiendo mirar ScoopyNG [1]. Es una colección de conocidos métodos de detección de vM de bajo nivel y que funcionan bien, aunque están un poco anticuados.

Si realmente desea confiar en otras cosas, como las herramientas instaladas (VM * Additions), estas son mucho más fáciles de "falsificar".

Esta publicación de blog [2] también tiene una visión general bastante buena, desde cosas de bajo nivel asm, buscando archivos DLL específicos, rutas de archivos y claves de registro para verificar.

[1] http://trapkit.de/research/vmm/scoopyng/index.html

[2] http://securitykitten.github.io/vm-checking-and-detecting/

2

Esta función C detectará VM SO Huésped: (probado en Windows, compilado con Visual Studio)

#include <intrin.h> 

    bool isGuestOSVM() 
    { 
     unsigned int cpuInfo[4]; 
     __cpuid((int*)cpuInfo,1); 
     return ((cpuInfo[2] >> 31) & 1) == 1; 
    } 
+0

Para aclarar, este fragmento de código utiliza la instrucción 'cpuid' para detectar si el bit de función está configurado que indica que el código se está ejecutando en un hipervisor. no es necesario que un hipervisor real establezca siempre este bit, especialmente para hipervisores de software. –

0

este código C++ detectará productos de VMware tales como express, esx, fusión o estación de trabajo

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