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
how detect the software the presence of a VM
4.6k views Asked by user7396065 AtThere are 2 answers
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
matchModel
andManufacturer
against(?i)(Hyper-V|Virtual Machine|VMware|VirtualBox)
. - In
Win32_VideoController
matchName
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).
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.