It is no secret that the Information Security industry takes advantage of virtualization software in order to research security threats. VMWare, Sandboxie, Virtual PC, Anubis, CWSandbox, JoeBox, VirtualBox, Parallels, QEMU are just just of few of these virtual machines. The cornucopia of virtual environments gives the security professional the opportunity to observe and analyze malicious software in a convenient and easily reproducible manner. This presents an issue for malware writers and because of this, they often include code in their binaries to make it more difficult for computer security professionals to analyze their executables in those virtual environments. Here are some of the most frequent anti-virtualization techniques:

Check for the presence of virtualized hardware:

Virtual environments have virtual network interfaces. Just like any network interface, they are assigned a unique MAC address that usually includes the manufacturer's identification number. For example, a network interface for VMware Workstation will have a MAC address that starts with 00:50:56 or 00:0C:29 (VMware has more than one organizationally unique identifier or OUI). Malware can check for the presence of certain OUIs and choose to behave differently or not to display any malignant behavior whatsoever in a virtual machine.

It is also possible to check for the presence of GUIDs that give away the fact that it's being run in a virtual environment. Eg: MD5: 0151c5afde070a7b194f492d26e9b3ef (Trojan.Agent-124243 by ClamAV):

.text:004012EA                 jz      short loc_40130E
.text:004012EC                 push    104h            ; size_t
.text:004012F1                 push    offset a76487644317703 ; "76487-644-3177037-23510"
.text:004012F6                 lea     ecx, [ebp+var_104]
.text:004012FC                 push    ecx             ; char *
.text:004012FD                 call    _strncmp
.text:00401302                 add     esp, 0Ch
.text:00401305                 test    eax, eax
.text:00401307                 jnz     short loc_40130E


The presence of HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\ProductId    76487-644-3177037-23510 shows that the host environment is CWSandbox.

Each virtual machine is associated with specific device drivers, registry values that give away their nature. For instance:

Hard drive driver (VMware):
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\IDE\DiskVMware_Virtual_IDE_Hard_

Drive___________00000001\3030303030303030303030303030303030303130\FriendlyName        VMware Virtual IDE Hard Drive

Video driver (VMware):
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Class\{4D36E968-E325-11CE-BFC1-08002BE10318}\0000\DriverDesc    VMware SVGA II

Mouse driver (VMware):
%WINDIR%\system32\drivers\vmmouse.sys

Any of these can be used by a malware writer to detect the presence of a virtual machine.

Descriptor Table Registers check:

There is only one Interrupt Descriptor Table Register (IDTR), one Global Descriptor Table Register (GDTR) and one Local Descriptor Table Register (LDTR) per processor. Since there are two operating systems running at the same time (the host and the guest), the virtual machine needs to relocate the IDTR, GDTR and LDTR for the guest OS to different locations in order to avoid conflicts. This will cause inconsistencies between the values of these registers in a virtual machine and in the native machine. The instructions SIDT, SGDT and SLDT are assembly instructions that can respectively be used to retreive the values of IDTR, GDTR and LDTR.

Eg: MD5: b27d73bfcbaec49a95f23b45e9cf9310 (W32.Virut-54 by ClamAV)

UPX2:3142A03A loc_3142A03A:              ; CODE XREF: sub_3142A02E+2 j
UPX2:3142A03A                 push    eax
UPX2:3142A03B                 sidt    fword ptr [esp+var_6+4]
UPX2:3142A040                 pop     eax
UPX2:3142A041                 mov     eax, [eax+6]
UPX2:3142A044                 shl     eax, 10h
UPX2:3142A047                 jns     short sub_3142A021


The IDT is at:

0x80ffffff in Windows
0xe8XXXXXX in Virtual PC
0xffXXXXXX in VMware

Backdoor I/O port:

VMware uses the I/O port 0x5658 ("VX" in ASCII) to communicate with the virtual machine. A piece of malware could detect the presence of that port by doing the following:

mov EAX, 564D5868h ; VMXh
xor EBX, EBX  ; set EBX to anything but 0x564D5868 (in this case 0)
mov CX, 0Ah   ; Backdoor command. 10: Get VMware version
mov DX, 5658h  ; VX
in EAX, DX  ; Read from port VX into EAX
cmp EBX, 564D5868h ; EBX should have the magic number VX is VMware is present. If not, EBX=0


Basically, the magic number 0×564D5868 ("VMXh") is copied to EAX and EBX is set to anything but 0x564D5868. A backdoor command is loaded into CX and finally the I/O port number 0x5658 ("VX") is loaded into DX. Then the "in" instruction is used to read from port 0x5658 into EAX. Outside of VMware (on a native host), a privilege error occurs. Under VMware, the magic number 0x564D5868 is returned to EBX (yes, in this case EBX is affected by in EAX, DX) hence the CMP instruction.

Exit if being debugged:

While this is not, per se, a anti-virtualization technique, it remains a a popular check performed by malware to see if a user-land debugger is present on the operating system. That's because more often than not a debugger will be installed in a virtual image used for malware analysis.

Eg: MD5: 74ab05d1ebdba509fd68711b360c1235 (Trojan.IRCBot-3475 by ClamAv)

.text:004050F8                 push    offset aZwquerysystemi ; "ZwQuerySystemInformation"
.text:004050FD                 push    [ebp+hModule]   ; hModule
.text:00405100                 call    ds:GetProcAddress
.text:00405106                 mov     [ebp+var_4], eax
.text:00405109                 push    offset aZwqueryinforma ; "ZwQueryInformationProcess"
.text:0040510E                 push    [ebp+hModule]   ; hModule
.text:00405111                 call    ds:GetProcAddress
.text:00405117                 mov     [ebp+var_14], eax
.text:0040511A                 cmp     [ebp+var_4], 0
.text:0040511E                 jz      short loc_405147

.text:00405120                 push    0
.text:00405122                 push    2   ; SystemInformationLength
.text:00405124                 lea     eax, [ebp+var_8]
.text:00405127                 push    eax ; SystemKernelDebuggerInformation
.text:00405128                 push    23h
.text:0040512A                 call    [ebp+var_4] ; ZwQueryInformationProcess
.text:0040512D                 test    eax, eax
.text:0040512F                 jnz     short loc_405147 ; process is being debugged


For the Windows API function ZwQuerySystemInformation, setting the value of SystemInfoClass to 2 (SystemKernelDebuggerInformation) retrieves system information on the presence of a user-land debugger.

NTSTATUS WINAPI ZwQuerySystemInformation(
__in       SYSTEM_INFORMATION_CLASS SystemInformationClass,
__inout    PVOID SystemInformation,
__in       ULONG SystemInformationLength,
__out_opt  PULONG ReturnLength
);


For the Windows API function ZwQueryInformationProcess, setting the value of ProcessInformationClass to 7 (ProcessDebugPort) retrieves the port number for the debugger of the process. A value other than 0 indicates that the process is being run through a user-land debugger.

NTSTATUS WINAPI ZwQueryInformationProcess(
__in       HANDLE ProcessHandle,
__in       PROCESSINFOCLASS ProcessInformationClass,
__out      PVOID ProcessInformation,
__in       ULONG ProcessInformationLength,
__out_opt  PULONG ReturnLength
);

How to thwart virtual machine detection:

For starters, do not install tools provided by the virtual machine in your guest OS. For example, VMware provides a set of tools called VMware Tools that enhances the overall user experience with the guest OS. The drawback is that installing VMware Tools in a Windows guest OS will leave many clues easily detectable by a piece malware that it is being run in a virtual machine.

The next step is to edit your VMware .vmx file. When you create a new virtual image with VMware, settings about it are stored in a configuration file with the .vmx extension. The file contains information about networking, disk size, devices attached to the virtual machine, etc...and is usually located in the directory where you created your virtual image. With your guest OS stopped, edit the .vmx file and append the following:

isolation.tools.setPtrLocation.disable = "TRUE"
isolation.tools.setVersion.disable = "TRUE"
isolation.tools.getVersion.disable = "TRUE"
monitor_control.disable_directexec = "TRUE"
monitor_control.disable_chksimd = "TRUE"
monitor_control.disable_ntreloc = "TRUE"
monitor_control.disable_selfmod = "TRUE"
monitor_control.disable_reloc = "TRUE"
monitor_control.disable_btinout = "TRUE"
monitor_control.disable_btmemspace = "TRUE"
monitor_control.disable_btpriv = "TRUE"
monitor_control.disable_btseg = "TRUE"


Now start your virtual machine. This will allow you to run (with very little effort) more vmware-aware malware than before.

I'll point out that:


  1. monitor_control.disable_directexec = "TRUE" will usually thwart descriptor table registers checks. This setting will make VMware interpret each assembly instruction instead of executing them directly on the processor. Therefore a the result of a sidt instruction will not be an address in the 0xffXXXXXX range as one would get without this setting.
  2. isolation.tools.getVersion.disable = "TRUE" will thwart the backdoor I/O check.
    Now, what if after all this, your piece of malware still detects that it is being run in a virtual machine? I would go through the code, find where virtual machine checks are being performed and patch the code with NOPs (0x90).

Finally, if that's too hard or not possible for whatever reason, run your sample on a native system! :-) (you can always use system backup and restore software to quickly revert the machine to its original state without reinstalling the OS)