-
Notifications
You must be signed in to change notification settings - Fork 23
Virtual Machines
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
matchModel
andManufacturer
against(?i)(Hyper-V|Virtual Machine|VMware|VirtualBox)
. - In
Win32_VideoController
matchName
against(?i)Hyper-V
.
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 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;
}
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;
}
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;
}