Skip to content
This repository has been archived by the owner on Jun 16, 2021. It is now read-only.

Virtual Machines

Adriano Repetti edited this page May 13, 2016 · 4 revisions

Generic WMI Solution

Simplest check to detect you are running inside a virtual machine is to search for known names. Places where you can find them:

  • 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.

Host Specific Detection

Alternative host specific detection is much more complex (unless you want to go with hacky tricks checking, for example, USB legacy support) because each host has its own technique to be detected but it's little bit more reliable.

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;
}
Clone this wiki locally