Protecting VMWare from CPUID hypervisor detection

One of the less-known anti-sandbox detection tricks relies on the instruction CPUID that is executed with EAX=1 as an input parameter. When executed the values returned by general purpose registers describe the various Processor Info and Feature Bits. Some malware samples analyse the bit 31th of the value returned in the register ECX; the bit is equal to zero on the real CPU/hypervisor and 1 on the guest VM.

You can test this trick by running the following program.

When executed on a real CPU it should give you the following output:

cpuid_novm

 

On the guest OS it should (not surprisingly) show the following output:

cpuid_vm

Depending on your hardware set up and the way your Virtual Platform is executing code you may get different results (modification of virtualization and dynamic translation settings may affect the results).

Bypassing this trick on the code level (e.g. during debugging session or via patching) is not easy as you need to find a sequence of code that is responsible for the detection first. And if the code is metamorphic that won’t be easy (CPUID is just 2 bytes long i.e. 0F A2 and the input values may be initiated using random sequence of code).

It turns out VMWare (tested on 10.0.3) supports a mechanism that allows to modify the CPUID instruction results. All you have to do is add the following line to your .vmx file:

cpuid.1.ecx="0---:----:----:----:----:----:----:----"

It instructs the VMWare to mask the 31st bit of ECX when the CPUID instruction is executed. As such, running the same program on the re-configured VM will give you the output as seen on the first screenshot i.e. CPUID returns value observed on the real CPU; malware running on such re-configured VM will get fooled and the sandbox detection can be bypassed.

Note: I am not an expert in VMWare configuration – any modification you do to your VM is on your own risk. If you break anything it’s your own fault 🙂

I encourage you to explore VMWare forums before doing any modification to your setup. Also, remember that you need to fully restart the VM (and the guest system) for the change to take place (it won’t work for a restart from a snapshot).

Beyond good ol’ Run key, Part 15

Today I am going to show you yet another debugging mechanism that allows to load a couple of phantom DLLs.

This time the culprit is DirectX.

The DirectX is pretty much a standard for programming anything that is multimedia-related on Windows. Since this includes games, animations, demos, as well as video players, picture viewers, etc. the phantom DLLs (they are debug DLLs in this case) can be easily made persistent because they will be loaded anytime one of such DirectX-aware applications starts.

Dropping one (or both) of these DLLs:

  • d3d8d.dll
  • d3d9d.dll

in one of the directories covered by the PATH variable and adding the following Registry Entry

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Direct3D]
@=""
"LoadDebugRuntime"=dword:00000001

will ensure that these DLLs will be loaded anytime a Direct X (its component called Direct 3D) is being used by some application. They are loaded by respective Direct X versions (8 or 9).

To test on XP (DirectX version 8 still is being used by dxdiag):

  • Add the registry entry
  • Drop test d3d8d.dll and d3d9d.dll into e.g. c:\windows\system32 directory
  • Run dxdiag
  • Go to Display tab
  • Click Test Direct 3D
  • You should see that d3d9d.dll is loaded when dxdiag starts and d3d8d.dll loads when you test Direct 3D feature on the Display tab

To test on Win 7 (DirectX version 8 doesn’t seem to be used by dxdiag, but DLLs are present and applications loading Direct X 8 libraries will _still_ load the DLLs):

  • Add the registry entry
  • Drop test d3d9d.dll into e.g. c:\windows\system32 directory
  • Run dxdiag
  • You should see that d3d9d.dll is loaded when dxdiag starts

In other words, it should work on all OSes that have the Direct X 8 or 9 installed.

You may be wondering if the same trick works for newer versions of DirectX.

It does.

The naming convention stays the same (e.g. d3d10d.dll, d3d11d.dll), but the major change is that:

  • The loading is not system-wide (or, more specifically DirectX-ecosystem wide), but application specific, hence a different registry entry is being used to load these DLLs
    • e.g. for dxdiag it would be
      • HKEY_CURRENT_USER\Software\
         Microsoft\Direct3D\dxdiag\
         D3D10LoadDebugRuntime=1
  • The DLLs (e.g. d3d10d.dll) are loaded only under very specific circumstances (only a couple of Direct X functions related to shaders load the debug DLLs) so chance for it to be a successful persistent mechanism are much lower
    • I guess the DLLs are used to test performance of the graphic primitives, but I have no programming experience with Direct X so can only speculate here