More VM Detection!

Hiyo!

Defcon was awesome this year. It always gives me inspiration for things to blog about. That said, I want to go over something simple today – more VM detection.

I’ll be hitting vmware because I have it, also OpenVZ and KVM because that’s what my old hosts worked on.

In my humble opinion, the best way to determine if you’re running on a VM is to read the SMBios information. Doing this on Linux is easy-peasy. Just use dmidecode. It works great.

Here we see KVM listed under ‘Product Info’.

This is fine and all for Linux, but the main focus of this blog post is on Windows and the VM’s employed by anti-malware appliances which run Windows for behavior analysis. How the hell do we read SMBios information on Windows?

Well, DMIDecode does exist for windows. How would we go about this programatically though? The GetSystemFirmwareTable API allows us to read the bios table. DmiDecode’s source tells me it does pretty much the same thing. I had to clean it up a little because GNU code is cray…

#include <windows.h>
#include <stdio.h>

int num_structures = 0;
typedef struct RawSMBIOSData
{
    BYTE    Used20CallingMethod;
    BYTE    SMBIOSMajorVersion;
    BYTE    SMBIOSMinorVersion;
    BYTE    DmiRevision;
    DWORD    Length;
    BYTE    SMBIOSTableData[];
} RawSMBIOSData, *PRawSMBIOSData;

PRawSMBIOSData get_raw_smbios_table(void){

    void *buf = NULL;
    DWORD size = 0;
    size = GetSystemFirmwareTable('RSMB', 0, buf, size);
    buf = (void *)malloc(size);
    GetSystemFirmwareTable('RSMB', 0, buf, size);        
    return buf;
}

int main(void)
{
PRawSMBIOSData smb = NULL;
smb=get_raw_smbios_table();
printf("SMBIOS %u.%u present.\r\n", smb->SMBIOSMajorVersion, smb->SMBIOSMinorVersion);
getchar();
return 1;
}

Does malwr.com flag this query information as suspicious? See for yourself:

There’s more than 1 way to query this information. This means we don’t have to rely on 1 thing (which might be spoofed or used as a behavior indicator).

The registry (command is reg query HKEY_LOCAL_MACHINE\Hardware\Description\System /v SystemBiosVersion):

The other key worth noting is HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\BIOS seen here:

This info can be gleaned with PowerShell via the command Get-WmiObject win32_bios

There are a shitload of other win32 classes with tons of info to sift through in powershell. Too much info, not enough time. Take a peek if you have infinite resolve.

System Info pane (msinfo32 in run box) will tell you bios info:

Finally you can grab this info from the command line again running either the systeminfo command or the wmi command line client.

But Joe, what if I’m a sadist, and want to use WMI in plain old C? I got your back:

#include <stdio.h>
#include <windows.h>
#include <wbemidl.h>
#include <Objbase.h>

int main(int argc, char* argv[])
{
    HRESULT hr = 0;
    IWbemLocator         *locator  = NULL;
    IWbemServices        *services = NULL;
    IEnumWbemClassObject *results  = NULL;
    BSTR resource = SysAllocString(L"ROOT\\CIMV2");
    BSTR language = SysAllocString(L"WQL");
    BSTR query    = SysAllocString(L"SELECT * FROM Win32_BIOS");

    hr = CoInitializeEx(0, COINIT_MULTITHREADED);
    hr = CoInitializeSecurity(NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
    hr = CoCreateInstance(&CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, &IID_IWbemLocator, (LPVOID *) &locator);
    hr = locator->lpVtbl->ConnectServer(locator, resource, NULL, NULL, NULL, 0, NULL, NULL, &services);
    hr = services->lpVtbl->ExecQuery(services, language, query, WBEM_FLAG_BIDIRECTIONAL, NULL, &results);
    if (results != NULL) 
	{
        IWbemClassObject *result = NULL;
        ULONG returnedCount = 0;
        while((hr = results->lpVtbl->Next(results, WBEM_INFINITE, 1, &result, &returnedCount)) == S_OK) 
		{
            VARIANT Manufacturer;
            hr = result->lpVtbl->Get(result, L"Manufacturer", 0, &Manufacturer, 0, 0);
			char prop[128];
			wcstombs(prop,Manufacturer.bstrVal,SysStringByteLen(Manufacturer.bstrVal));
			char *vm1 = "QEMU";
			char *vm2 = "VMware";
			char *vm3 = "vbox";

			if(strstr(prop,vm1))
			{
				printf("I see qemu!\r\n");
			}

			if(strstr(prop,vm2))
			{
				printf("I see vmware!\r\n");
			}

			if(strstr(prop,vm3))
			{
				printf("I see virtualbox!\r\n");
			}

            printf("%s \r\n", prop);
            result->lpVtbl->Release(result);
        }
    }

    results->lpVtbl->Release(results);
    services->lpVtbl->Release(services);
    locator->lpVtbl->Release(locator);
    CoUninitialize();
    SysFreeString(query);
    SysFreeString(language);
    SysFreeString(resource);
}

Looks familiar, right? I borrowed some of the code from my Crypter. This is just for bios info though.

I dug deeper and looked using an amazing tool called RW-Everything on both VMWare and OpenVZ to try and find other ways to reveal if I’m in a VM besides the BIOS info. The result? Let’s take a look…

First up is Windows 7 on VMWare. The tool does a pretty good job at identifying VMWare off the bat via the Extended System Description Table. This part of ACPI (Advanced Configuration and Power Interface) and used in BIOS and hardware shit. If you really want to know more, knock yourself out.

Note the ‘Creator ID’ specifies VMW. Is this the only reference in the ACPI table for VMWare? Fuck no. We can dump the whole thing with our little tool to a file and peek for ourselves:

23 hits! Not bad.

What about for KVM? Let’s take a peek:

Seems to list Bochs and Qemu. Makes sense since KVM is a fork of Qemu and Bochs comes with KVM.

One more part to check out is the USB information window. This proves quite fruitful for determining if we’re in a VM.

Here we see multiple instances of ‘Vmware’ devices in the list of USB devices. Dumping the file and taking a peek, we again see multiple instances for VMWare:

10 hits. The mouse, the hub, vendor and product info. Not a bad haul.

How about KVM?

Only 2 hits, but better than none.

I’m trailing off here, so let’s go over one more example via WMI that we can use to determine if we’re in a VM:

By querying the win32_OnboardDevice class, we get a hit.

Are there more ways? You betcha. I’m always looking for new ways to detect VM’s on Windows and I’m certain I’ll think of more in the future.

For now though, It’s like 3 am and I’m in need of sleep.

Until next time,

Happy cracking!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.