Wednesday, April 2, 2008

Virtualization Detection

As you know, virtualization is changing traditional IT infrastructure.
VMware ESX server, the market leading hypervisor, has been accepted by customers of all sizes, including all of the Fortune 100; Microsoft Windows 2008 also integrate Hyper-V as a core server role; several open source projects also focus on it, such as Xen (Intel), KVM (Linux) and Virtual Box (Sun) etc.

There are a lot of research papers and online discussion about Virtualization Detection

The 1st option is using vender specific public interface or backdoor, which could provide rich information about host OS and virtualization.

Microsoft public a Hypervisor Functional Specification for its Hyper-V implementation, which includes definition about not only feature and interface discovery but also Hyper-Call based management interfaces.
We could directly use one simple CPUID instruction to detect the existent of Hyper-V.

bool CHyperV::Exists(void)
int cpuid[4];

__cpuid(cpuid, 1);

return cpuid[2] & (1 <<>Further more, vender ID, neutral interface name, version and supported features could be fetched through similar method.

VMware also has similar private interface through a magic I/O port, which includes not only implementation information but also runtime information, such as processor speed, mouse cursor position and clipboard etc.
We could use its magic I/O port to detect the existent of VMware.

bool CVMware::Exists(void)
bool exists = true;


push edx
push ecx
push ebx

mov eax, 'VMXh'
mov ebx, 0 // any value but not the MAGIC VALUE
mov ecx, 10 // get VMWare version

mov edx, 'VX' // port number

in eax, dx // read port

// on return EAX returns the VERSION
cmp ebx, 'VMXh' // is it a reply from VMWare?

setz [exists] // set return value

pop ebx
pop ecx
pop edx

exists = false;
return exists;
For more completely commands list, you could check the following URL

VMware Backdoor I/O Port
VMware also provide an open source project, Open Virtual Machine Tools, which includes more detail usage of its backdoor.

Besides, Microsoft Virtual PC/Server, bochs, qemu has similar interface, you could check the following URLs for more detail.

How to detect Virtual PC or VMware from your program

Attacks on Virtual Machine Emulators

The 2nd option is checking VM implementation mechanism, which could detect some unknown VM vender in theory.

The mostly famous method is checking IDT register from Joanna’s Red Pill.

Red Pill... or how to detect VMM using (almost) one CPU instruction
The heart of this code is actually the SIDT instruction (encoded
as 0F010D[addr]), which stores the contents of the interrupt descriptor table register (IDTR) in the destination operand, which is actually a memory location. What is special and interesting about SIDT instruction is that, it can be executed in non privileged mode (ring3) but it returns the contents of the sensitive register, used internally by operating system.

Because there is only one IDTR register, but there are at least two OS running concurrently (i.e. the host and the guest OS), VMM needs to relocate the guest's IDTR in a safe place, so that it will not conflict with a host's one. Unfortunately, VMM cannot know if (and when) the process running in guest OS executes SIDT instruction, since it is not privileged (and it doesn't generate exception). Thus the process gets the relocated address of IDT table. It was observed that on VMWare, the relocated address of IDT is at address 0xffXXXXXX, whereas on Virtual PC it is 0xe8XXXXXX. This was tested on VMWare Workstation 4 and Virtual PC 2004, both running on Windows XP host OS.

This method only use one SIDT instruction to detect the existent of VM, because a lot of x86 software VM implementation choose to change IDT for guest OS.

bool CUnknown::CheckIDT(void)
unsigned char idt[6];

sidt idt

return idt[5] > 0xd0;
Unfortunately, this method could be spoofed by VM implementation

SubVirt: Implementing malware with virtual machines
The redpill [39] virtual-machine detection technique detects the
presence of a VMM by using the sidt instruction. The sidt instruction reads the address of the processor’s interrupt descriptor table. This address is different for an operating system running directly above hardware than for an operating system running above a VMM. VMMs emulate the sidt instruction when it is called from kernel-mode, but for performance reasons this instruction is not virtualized when called from user-mode. Thus, user-mode code can execute the
sidt instruction to detect the presence of a VMM. To defeat this detection technique, we use virtual-machine introspection to emulate the sidt instruction when it is called by the redpill application.

And it also doesn’t work on some hardware accelerated VM implementation and multi-core CPU system.

Introducing Blue Pill
SubVirt was implemented on x86 hardware, which doesn't allow to achieve 100% virtualization, because there are number of sensitive instructions, which are not privileged, like the famous SIDT/SGDT/SLDT. This allows for trivial detection of the virtual mode - see e.g. my little Red Pill program. This however, doesn't apply to Blue Pill, as it relies on AMD SVM

Detecting the Presence of Virtual Machines
Using the Local Data Table
The SIDT mechanism as implemented by Tobias Klein [1] and
separately by Joanna Rutkowska [2] is a method for detecting the presence of a virtual machine environment. While the test is by no means thorough, it is an effective test for the presence of an emulated CPU environment on a single-processor machine. There are various problems with the implementation, however. If a multi-core CPU is used, the interrupt descriptor table can change significantly when the process is run on different cores. Furthermore if two or more physical processors are present the same implementation issues apply.
To improve the issues of SIDT mechanism, a lot of attempts focus on similar register, such as GDT, LDT or TS register.

Detecting the Presence of Virtual Machines Using the Local Data Table

Methods for Virtual Machine Detection

bool CUnknown::CheckGDT(void)
unsigned char gdt[6];
sgdt gdt
return gdt[5] > 0xd0;

bool CUnknown::CheckLDT(void)
unsigned char ldt[2];
sldt ldt
return ldt[0] != 0 && ldt[1] != 0;

bool CUnknown::CheckTR(void)
unsigned char tr[2];

str tr

return tr[0] == 0 && tr[1] == 0x40;
The major problem of these kinds of detection methods is the researcher hard to test compatibility on every VM vender.

After I made a simple test, it seems we hard to trust any of them, but we could made a hyper detection method base on more test results.

The 3rd option is using VM specific defect, which mostly tight coupling with VM version.

For example, eEye researcher published a detection method base on wrong far execution transfers behaviors.

Another VMware Detection
So, the real world is not perfect, we hard to use one hammer to solve all the problems. We should carefully define our purpose and scope of virtualization detection, and choose a hyper detection solution for major focus market.

No comments: