Wednesday, 26 September 2018

Detecting VMware by reading an invalid MSR

This isn't exactly related to hypervisor development, I just thought it was a neat find.
Basic background:
An MSR, or Model-Specific Register is a natural-width (i.e the size of a pointer) buffer that contains data which either affects processor behaviour or is used to store processor-specific data which is deemed to not go into a CPUID leaf. Trying to interact with an invalid MSR index will result in a General-Protection Fault, or a #GP(0) (the (0) meaning an error code of 0).

MSRs are virtualized or emulated by the Virtual Machine Monitor. Generally speaking, an MSR read or write will trap into the VMM/hypervisor so it can give the correct response (newer processors contain features such as MSR bitmaps for Intel's Virtual Machine eXtensions which specify the MSRs that do this). Therefore, if a hypervisor decides to not implement the proper response for an MSR interaction, it can be used as a way to detect it.

So, back to invalid MSR indices. Intel defines a range of MSRs which, unless subverted by a hypervisor, will always be invalid, no matter what CPU you're using (provided it's Intel). These are MSRs 40000000h - 400000FFh.
As said before, reading or writing to these MSRs will always cause a #GP(0). Unless, of course, you're running under VMware.

One day, while messing around with my hypervisor inside of VMware and reading random MSRs, well, let the image speak for itself:
I was able to read a normally invalid MSR! This means that one could detect VMware by simply doing:

For context, with my program, the normal output is:

1 comment:

  1. As far as I know, such MSRs (0x4000XXXX) are defined by Microsoft as Synthetic MSRs. VMware's Hypervisor, when hypervising Windows, is Microsoft-compliant. MSR[0x40000000] is defined as HV_X64_MSR_GUEST_OS_ID, which indicates the identifier of Operating System. Since the value you got is 0x0001040a0000271b, this means your build number is 0x271b(10011), minor version is 0x00, major version is 0x0a(10), OS ID is 0x04(Windows NT), Vendor ID is 0x01(Microsoft). In summary, your Windows installed in VMware is Microsoft Windows NT 10.0.10011 (seems to be a preview version).
    Have a look at Microsoft's manual and you will see how do Synthetic MSRs work: https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs
    This detection is easy to be countered. If your VM is not encrypted, simply edit your .vmx file. Add the following line to file:
    hypervisor.cpuid.v0 = "FALSE"
    In this regard, VMware will hypervise Windows without being Microsoft-compliant.

    ReplyDelete

Unexplained crashes, microcode updates, and CPU errata

Computers are complicated machines. It's all too common to be browsing the internet, playing the newest Call of Duty , or just watching ...