Hyper-V How To: Detect if you are inside a VM


Sometimes, when troubleshooting or for forensic reasons, you may have to determine if an application is running inside a virtual machine. John Kelbley, co-author of Windows Server 2008 Hyper-V : Insiders Guide to Microsoft’s Hypervisor, shares how.


One (relatively) simple way to detect key virtualization information is via WMI / WBEM.  You can use the root\CIM2 namespace and access  the Baseboard class (full of interesting BIOS information) to get a description of the “physical” system.  This class often includes information about the motherboard and chassis  – manufacture, model, serial number, other.   You can run the following VBS to get this info.



On Error Resume Next


Const wbemFlagReturnImmediately = &h10
Const wbemFlagForwardOnly = &h20


arrComputers = Array(“.”)
For Each strComputer In arrComputers
   WScript.Echo
   WScript.Echo “==========================================”
   WScript.Echo “Computer: ” & strComputer
   WScript.Echo “==========================================”


   Set objWMIService = GetObject(“winmgmts:\\” & strComputer & “\root\CIMV2”)
   Set colItems = objWMIService.ExecQuery(“SELECT * FROM Win32_BaseBoard”, “WQL”, _
                                          wbemFlagReturnImmediately + wbemFlagForwardOnly)


   For Each objItem In colItems
      WScript.Echo “Caption: ” & objItem.Caption
      strConfigOptions = Join(objItem.ConfigOptions, “,”)
         WScript.Echo “ConfigOptions: ” & strConfigOptions
      WScript.Echo ”   CreationClassName: ” & objItem.CreationClassName
      WScript.Echo ”         Description: ” & objItem.Description
      WScript.Echo ”        HostingBoard: ” & objItem.HostingBoard
      WScript.Echo ”         InstallDate: ” & WMIDateStringToDate(objItem.InstallDate)
      WScript.Echo ”        Manufacturer: ” & objItem.Manufacturer
      WScript.Echo ”               Model: ” & objItem.Model
      WScript.Echo ”                Name: ” & objItem.Name
      WScript.Echo “OtherIdentifyingInfo: ” & objItem.OtherIdentifyingInfo
      WScript.Echo ”          PartNumber: ” & objItem.PartNumber
      WScript.Echo ”             Product: ” & objItem.Product
      WScript.Echo ”        SerialNumber: ” & objItem.SerialNumber
      WScript.Echo ”                 SKU: ” & objItem.SKU
      WScript.Echo ”              Status: ” & objItem.Status
      WScript.Echo ”                 Tag: ” & objItem.Tag
      WScript.Echo ”             Version: ” & objItem.Version
      WScript.Echo
   Next
Next


Function WMIDateStringToDate(dtmDate)
WScript.Echo dtm:
    WMIDateStringToDate = CDate(Mid(dtmDate, 5, 2) & “/” & _
    Mid(dtmDate, 7, 2) & “/” & Left(dtmDate, 4) _
    & ” ” & Mid (dtmDate, 9, 2) & “:” & Mid(dtmDate, 11, 2) & “:” & Mid(dtmDate,13, 2))
End Function


Here is a screen capture of the script results for a physical system running Windows Server 2008. 


image


NOTE the motherboard was manufactured by Intel  (model DG45ID).


Running the same script in a virtual machine returns similar information:


image


NOTE On the virtual machine, the “motherboard” appears to be made by Microsoft (we don’t make motherboards!) and is of a virtual type.


The version number shown reflects the version of Hyper-V (Server 2008 RTM), and the Serial Number matches that found in the VM configuration file (XML file on the physical host).


The Perl script version for this is:



use strict;
use Win32::OLE(‘in’);


use constant wbemFlagReturnImmediately => 0x10;
use constant wbemFlagForwardOnly => 0x20;


my @computers = (“.”);
foreach my $computer (@computers) {
   print “\n”;
   print “==========================================\n”;
   print “Computer: $computer\n”;
   print “==========================================\n”;


   my $objWMIService = Win32::OLE->GetObject(“winmgmts:\\\\$computer\\root\\CIMV2”) or die “WMI connection failed.\n”;
   my $colItems = $objWMIService->ExecQuery(“SELECT * FROM Win32_BaseBoard”, “WQL”,
                  wbemFlagReturnImmediately | wbemFlagForwardOnly);


   foreach my $objItem (in $colItems) {
      print ”          Caption: $objItem->{Caption}\n”;
      print ”       ConfigOptions: ” . join(“,”, (in $objItem->{ConfigOptions})) . “\n”;
      print ”   CreationClassName: $objItem->{CreationClassName}\n”;
      print ”         Description: $objItem->{Description}\n”;
      print ”        HostingBoard: $objItem->{HostingBoard}\n”;
      print ”         InstallDate: $objItem->{InstallDate}\n”;
      print ”        Manufacturer: $objItem->{Manufacturer}\n”;
      print ”               Model: $objItem->{Model}\n”;
      print ”                Name: $objItem->{Name}\n”;
      print “OtherIdentifyingInfo: $objItem->{OtherIdentifyingInfo}\n”;
      print ”             Product: $objItem->{Product}\n”;
      print ”        SerialNumber: $objItem->{SerialNumber}\n”;
      print ”                 SKU: $objItem->{SKU}\n”;
      print ”              Status: $objItem->{Status}\n”;
      print ”                 Tag: $objItem->{Tag}\n”;
      print ”             Version: $objItem->{Version}\n”;
      print “\n”;
   }
}sub WMIDateStringToDate(strDate)
{
   return “blah”;
}


For additional reference, within Windows I could also access  the same information in a single command line (in Windows XP or newer) by typing  the following:



     wmic baseboard get manufacturer, product, Serialnumber, version


image


For info on how to use Hper-V PS cmdlets see: http://www.microsoft.com/technet/scriptcenter/topics/msh/cmdlets/index.mspx


See also James O’Neil’s New and improved PowerShell Library for Hyper-V. Now with more functions and… documentation!


For 35 sample Hyper-V PS1 scripts in a zipfile, go to: Hyper-V%20PowerShell%20Example%20Scripts.zip-download


And buy John(et al)’s book!


image


Update: John’s blogging now and has an updated method to detect the hypervisor: http://blogs.technet.com/enterprise_admin/archive/2009/10/20/detecting-the-virtualization-layer-from-within-a-guest-child-instance.aspx

Comments (1)

  1. John Kelbley says:

    I wasn’t super clear when I provided this information to Tony – this shows a VM running on a Microsoft virtualization layer like Hyper-V.  A Windows virtual machine on VMWare does not report the same information (it may show that it has a 440BX chipset motherboard due to emulation).

    You can detect a VMware physical host by interrogating the WMI Win32_BIOS and looking at the serialnumber.  My buddy Ben Herman (you know who you are you scripting master!) helped me with that since I didn’t have a VMware host handy.

    I’ll send Tony some more info on all this that he can post.