how detect the software the presence of a VM

4.6k views Asked by At

I am beginners in the world of virtual machines and have a small question. if a software is running on a VM (eg. VMware Player) how does it know that it is installed on a VM? Does the software get the information from the operating system or is there a direct communication between the software and the hardware (VMware Player)? thank you in advance

2

There are 2 answers

8
Mohammed Noureldin On

I don't think that it does matter for the software where it is running as long as it works properly.

If you really want to check if you are running (or if your self-written code) is running on VM. In Windows case it is possible to check the hardware in device manager (Windows case), because VM apps create some virtual hardware. For example VMWare will create some hardware named VMware... devices.

6
Adriano Repetti On

Unfortunately there is not an unique answer. Each virtual machine has a sort of bridge you can use but you have to write specific checks for each VM you want to detect (examples are VC++ specific but you can easily adapt them to your compiler). Note that in theory you should not be able to determine if you're running under a VM or not.

VMWare

VMWare uses IN instruction to handle guest to host communication. Normally this instruction is not available in user-mode and it throws an exception but VM handles it. If we catch the exception then we know we are not running under VMWare (or we are privileges to execute IN instruction). Second test to determine if we have privileges or we are running under WMWare is almost useless but that's standard detect code and I write it here for completeness (we just check for an expected string VMXh in EBX register, note we had to initialize some registers with required values.)

bool IsRunningInsideVmWare()
{
    bool flag = true;

    __try
    {
        __asm
        {
            push    edx
            push    ecx
            push    ebx

            mov     eax, 'VMXh'
            mov     ebx, 0
            mov     ecx, 10
            mov     edx, 'VX'

            in      eax, dx
            cmp     ebx, 'VMXh'
            setz    [flag]

            pop     ebx
            pop     ecx
            pop     edx
        }
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        flag = false;
    }

    return flag;
}

Virtual PC

Guests can use a non-existing instruction 0f3f070b to communicate with host, what you can do is then emit such instruction, VM will correctly interpret it but physical CPUs will throw an exception (which you can catch and jump over offending instruction). In this example we set EBX to a known value in the exception handler and then we can detect this scenario.

DWORD __forceinline VpcExceptionFilter(LPEXCEPTION_POINTERS ep)
{
    ep->ContextRecord->ctx->Ebx = -1;
    ep->ContextRecord->ctx->Eip += 4;

    return EXCEPTION_CONTINUE_EXECUTION;
}

bool IsRunningInsideVpc()
{
    bool flag = false;

    __try
    {
        _asm
        {
            push    ebx

            mov     eax, 1
            mov     ebx, 0 

            __emit  0Fh
            __emit  3Fh
            __emit  07h
            __emit  0Bh

            test    ebx, ebx
            setz    [flag]

            pop     ebx
        }
    }
    __except(VpcExceptionFilter(GetExceptionInformation()))
    {
    }

    return flag;
}

VirtualBox

To detect VirtualBox is extremely simple, you just need to check if a pseudo-device \\.\VBoxMiniRdrDN exists:

bool IsRunningInsideVirtualBox()
{
    HANDLE handle = CreateFile("\\\\.\\VBoxMiniRdrDN", GENERIC_READ, FILE_SHARE_READ, 
        NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    if (handle != INVALID_HANDLE_VALUE)
    {
        CloseHandle(handle);
        return true;
    }

    return false;
}

Something little bit more generic can be done (assumption: you're running on Windows) using WMI and the following queries:

  • In Win32_BaseBoard matchName against (?i)(Hyper-V|Virtual Machine|Microsoft|VMware|VirtualBox|Parallels Virtual).
  • In Win32_ComputerSystem match Model and Manufacturer against (?i)(Hyper-V|Virtual Machine|VMware|VirtualBox).
  • In Win32_VideoController match Name against (?i)Hyper-V.

CPUID instructions can also help you (when those values are supported).

With EAX set to 0 (Get vendor ID) you get in EBX, EDX and ECX an ASCII string with CPU vendor name (see Wikipedia for list). Of course a VM can return a false name or it may be an unknown VM.

With EAX set to 1 (Processor Info and Feature Bits) bit 31 of ECX (hypervisor) is set to 1 if you're running under a VM. Again a VM may return a false result (and some VMs don't honor this bit).


When I had to play with this issue I tried also to check for hardware tricks/features which are not supported in a VM (for example to USB Legacy support) but I found it's not reliable enough to be used in production.


In comment you said you're running on Android. That's a completely different story but common techniques are similar to what I said about WMI (or a combination of the above). A common way is to check the device name string for well-known emulators, from Android 7 there is a specific flag ro.kernel.qemu.

Can you fake those values? Yes, see for example Is there a way to set ro.kernel.qemu to 0 in a emulator?. Note that any decent application which cares to stop you to use it under emulation will also use multiple detection techniques (see also Android: Get Hardware Information Programmatically).