Tuesday, October 30, 2012

Virtual PC vs. CPUID

In this post i will show another weird behavior of Virtual PC 2007. This time it is about the CPUID instruction. As most of you already know well what the CPUID is for and how it works, i will directly jump into the main topic.

In Virtual PC, executing CPUID disables interrupts for one instruction. Oh, wait, how is that?

Imagine we want to trace a sequence of x86 instruction. What the debugger does in that situation is as follows:
1) Calls the "GetThreadContext" function to extract the current context of the thread executing this sequence of instructions.
2) Modifies the "EFLAGS" register of the "CONTEXT" structure such that the Trap flag (TF) is set. EFLAGS is situated at offset 0xC0 from the start of the structure for the x86 version. TF is bit number 8 (0x100).
3) Calls the "SetThreadContext" and "ContinueDebugEvent" functions to continue execution.

When the trap flag is set, after executing an x86 instruction, an exception EXCEPTION_SINGLE_STEP is raised and trap flag is cleared.

The debugger receives the exception and resets the trap flag as shown above and so on.

Disable interrupts, what does that mean?
Executing certain instructions when the trap flag is set, no EXCEPTION_SINGLE_STEP exception is raised. The exception is raised after executing the instruction following them. One example instruction that disables interrupts is POP SS. POP SS has been used for a long time as an anti-tracing trick. Since it disables interrupts for one instruction, dumping the EFLAGS register to stack via . PUSHFD reveals the Trap Flag.

Executing CPUID in Virtual PC 2007, i found out that it has the same effect as POP SS. CPUID disables interrupts for one instruction.

I created a simple demo that exploits this bug to detect whether it is running inside Virtual PC 2007. It has been tested on Windows XP SP2 running inside Virtual PC 2007.

Reason for that is still under research but it seems to be due to the Virtualized CPUID (Intel FlexMigration) hardware support since the trick only works if Hardware Virtualization is enabled.

You can download the demo from here and its source code from here.

N.B. VirtualBox v4.1.22 r80657 is also affected by this bug.

N.B. Parallels Desktop is reportedly affected by this bug.

You can follow me on Twitter @waleedassar.