<div dir="ltr"><div><div><div><div><div><div><div><div>Hi,<br><br></div>I've made a fix for this bug <a href="https://www.virtualbox.org/ticket/10947" target="_blank">https://www.virtualbox.org/ticket/10947</a>.
 Mentioned ticket isn't very descriptive so I will try to explain this 
issue a little bit more in detail. First of all this problem occurs only
 when VT-x is enabled. Basically some instructions don't generate 
expected single step exception after they are executed with the trap 
flag being set. The behaviour is observed that such instructions are 
executed under the control of the guest system but single step exception
 is generated after the next instruction. This is a well known bug 
amongst malware researchers and malware authors who can easily take 
advantage of this fact in order to detect virtualized environment.<br>
<br></div>It turns out that the problem lies in the way VirtualBox 
handles some VM exits initiated by the execution of certain 
instructions. Several instructions can never be executed in VMX non-root
 operation and those need to be emulated and skipped within VM exit 
handlers by adjusting RIP. Unfortunately the code lacks necessary check 
for the trap flag being set, so it doesn't inject expected exception 
into the guest.<br>
<br></div><div>Here's the fix:<br></div><span style="font-family:courier new,monospace">*** src\VBox\VMM\VMMR0\HMVMXR0_original.cpp    2013-11-01 18:58:26.000000000 +0100<br>--- </span><span style="font-family:courier new,monospace"><span style="font-family:courier new,monospace">src\VBox\VMM\VMMR0\</span>HMVMXR0_fixed.cpp        2013-11-08 20:24:30.578125000 +0100<br>

***************<br>*** 8166,8181 ****<br>--- 8166,8190 ----<br>  DECLINLINE(int) hmR0VmxAdvanceGuestRip(PVMCPU pVCpu, PCPUMCTX pMixedCtx, PVMXTRANSIENT pVmxTransient)<br>  {<br>      int rc = hmR0VmxReadExitInstrLenVmcs(pVCpu, pVmxTransient);<br>

      rc    |= hmR0VmxSaveGuestRip(pVCpu, pMixedCtx);<br>      AssertRCReturn(rc, rc);<br>  <br>      pMixedCtx->rip += pVmxTransient->cbInstr;<br>      VMCPU_HMCF_SET(pVCpu, HM_CHANGED_GUEST_RIP);<br>+     <br>+     X86EFLAGS Eflags;<br>

+     rc = VMXReadVmcs32(VMX_VMCS_GUEST_RFLAGS, &Eflags.u32);<br>+     AssertRCReturn(rc, rc);<br>+     if (Eflags.Bits.u1TF)<br>+     {<br>+         hmR0VmxSetPendingXcptDB(pVCpu, pMixedCtx);<br>+     }<br>+     <br>

      return rc;<br>  }</span><br> <br></div>This fix ensures correct 
handling of mentioned condition in all 13 affected VM exit handlers: 
VMX_EXIT_CPUID, VMX_EXIT_RDTSC, VMX_EXIT_RDTSCP, VMX_EXIT_RDPMC, 
VMX_EXIT_MOV_CRX, VMX_EXIT_MOV_DRX, VMX_EXIT_MWAIT, VMX_EXIT_MONITOR, 
VMX_EXIT_RDMSR, VMX_EXIT_WRMSR, VMX_EXIT_INVD, VMX_EXIT_INVLPG, 
VMX_EXIT_WBINVD.<br>
<br></div>In the attachment I provided a simple program which can be 
used to test this condition on 2 representative instructions: CPUID and 
RDTSC. I picked those because they don't require CPL = 0.<br><br></div>I release this patch and test program under MIT license.<br>
<br></div>Best regards,<br></div>Konrad</div>