Detecting Virtual Machines¶
For many reasons (workarounds for improper emulation, host integration, ect...) we may want to know if we're running inside a virtual machine (VM.)
VM's include Bochs, Qemu, VirtualBox, Parallels and VirtualPC.
Detecting Bochs¶
There are several methods to detect bochs, the easiest being:
write 0xFF to port 0x80 read from 0xE9 and store in tmp if tmp is equal to 0xE9 then --> We are running in bochs and have debug output available else --> We are not running in bochs, or bochs was not built with BX_PORT_E9_HACK
Sadly, CPUID isn't an option here. For CPUID=0000h, Bochs returns either GenuineIntel(x86) or AuthenticAMD(x86-64).CPUID=80000002h, 80000003h, and 80000004h returns either Intel(R) Pentium(R) 4 CPU(x86) or AMD Athalon(tm) processor(x86-64).
- INVD flushes TLBs
- REP CMPS/SCAS flags
- CPUID AMD K7 Easter Egg
- 32-bit ARPL register corruption
- 16-bit segment wraparound
Detecting VirtualBox¶
With VirtualBox, the easiest method is to scan the PCI bus for VENDOR=0x80EE,DEVICE=0xCAFE, which is the device used for host integration with the guest OS.
VirtualBox also supports SMBIOS, and checking the strings in header type 0 & 1 is also an option.
- CPUID K7 Easter Egg
- CMPXCHG8B memory write
Detecting Parallels¶
Probably the most annoying to detect, the best method of detecting it is using the (undocumented) INT 0x1B vector.
mov esi, 'magi' mov edi, 'c!nu' mov ebx, 'mber' mov edx, <stack address> mov eax, <function> int 0x1B
Presumably, checking the value of the register on return would give you an idea if your currently running in Parallels.
Detecting VMWare¶
A portable method, by 'Joanna Rutkowska' called RedPill uses the SIDT instruction to find the address of the IDTR. On VMWare, this is a 0xffXXXXXX
#include <stdio.h>
int main () {
unsigned char m[2+4], rpill[] = "\x0f\x01\x0d\x00\x00\x00\x00\xc3";
*((unsigned*)&rpill[3]) = (unsigned)m;
((void(*)())&rpill)();
printf ("idt base: %#x\n", *((unsigned*)&m[2]));
if (m[5]>0xd0) printf ("Inside Matrix!\n", m[5]);
else printf ("Not in Matrix.\n");
return 0;
}
Another method is to use the host integration feature's VERSION command.
mov eax, 0x564D5868 ;'VMXh' mov ecx, 0x0A ;get VMware version mov dx, 0x5658 ;'VX' in eax, dx cmp ebx, 0x564d5868 ;'VMXh' je detected
However, it is possible to disable the version command. An alternative (which cannot be disabled at the moment) is to use mov ecx, 0x14 which retrieves the guests memory size.
Detecting VirtualPC¶
The easiest method of detecting VirtualPC is the CPUID instruction. Unlike a real machine, CPUID=0x00 will return ConnectixCPU in reference to its original developers.
The RedPill method described above for detecting VMWare will also work for VirtualPC, returning an address around 0xe8XXXXXX.