Advertisement






Microsoft Windows Kernel REG_RESOURCE_LIST Memory Disclosure

CVE Category Price Severity
CVE-2018-0899 CWE-200 $10,000 - $25,000 High
Author Risk Exploitation Type Date
Theori High Local 2018-03-21
CVSS EPSS EPSSP
CVSS:4.0/AV:L/AC:L/AT:P/PR:N/UI:N/S:U/C:H/I:H/A:N 0.02192 0.50148

CVSS vector description

Our sensors found this exploit at: https://cxsecurity.com/ascii/WLB-2018030170

Below is a copy:

Microsoft Windows Kernel REG_RESOURCE_LIST Memory Disclosure
Windows Kernel 64-bit pool memory disclosure via REG_RESOURCE_LIST registry values (videoprt.sys descriptors) 

CVE-2018-0899


We have discovered a Windows kernel memory disclosure vulnerability through the body of "AllocConfig" registry values (of type REG_RESOURCE_LIST) corresponding to devices handled by videoprt.sys, which can be found under HKLM\SYSTEM\CurrentControlSet\Enum\*\*\*\Control\AllocConfig. The vulnerability affects 64-bit versions of Windows 7 to 10, and is very similar to <a href="/p/project-zero/issues/detail?id=1473" title="Windows Kernel 64-bit pool memory disclosure via REG_RESOURCE_LIST registry values (CmResourceTypeDevicePrivate entries)" class="closed_ref" rel="nofollow"> Issue #1473 </a>.

The leak was originally detected under the following stack trace (Windows 7):

--- cut ---
  kd> k
   # Child-SP          RetAddr           Call Site
  00 fffff880`020a68a8 fffff800`0295bdaa nt!memcpy+0x3
  01 fffff880`020a68b0 fffff800`0295c30f nt!CmpQueryKeyValueData+0xea
  02 fffff880`020a6940 fffff800`0296107f nt!CmQueryValueKey+0x1af
  03 fffff880`020a6a20 fffff800`0268d093 nt!NtQueryValueKey+0x37d
  04 fffff880`020a6bb0 00000000`772abeaa nt!KiSystemServiceCopyEnd+0x13
  05 00000000`007aeb18 00000000`77153dec ntdll!ZwQueryValueKey+0xa
  06 00000000`007aeb20 00000000`77153ff2 kernel32!LocalBaseRegQueryValue+0x17c
  07 00000000`007aeca0 000007fe`fc281dd1 kernel32!RegQueryValueExW+0xf2
  08 00000000`007aed40 000007fe`fc2735e4 umpnpmgr!OpenLogConfKey+0xb3
  09 00000000`007aedc0 000007fe`ff25e9d5 umpnpmgr!PNP_GetFirstLogConf+0x8d
  [...]
--- cut ---

and more specifically in the copying of the CM_RESOURCE_LIST structure:

--- cut ---
  kd> db rdx rdx+r8-1
  fffff8a0`049de874  01 00 00 00 01 00 00 00-00 00 00 00 00 00 00 00  ................
  fffff8a0`049de884  05 00 00 00 01 03 01 00-b0 03 00 00 00 00 00 00  ................
  fffff8a0`049de894  0c 00 00 00 aa aa aa aa-01 03 01 00 c0 03 00 00  ................
  fffff8a0`049de8a4  00 00 00 00 20 00 00 00-aa aa aa aa 03 03 00 00  .... ...........
  fffff8a0`049de8b4  00 00 0a 00 00 00 00 00-00 00 02 00 aa aa aa aa  ................
  fffff8a0`049de8c4  01 03 01 00 ce 01 00 00-00 00 00 00 02 00 00 00  ................
  fffff8a0`049de8d4  aa aa aa aa 01 03 01 00-e8 02 00 00 00 00 00 00  ................
  fffff8a0`049de8e4  08 00 00 00 aa aa aa aa                          ........
--- cut ---

In the above example, the 0xaa values are unitialized bytes originating from a pool allocation made in videoprt!pVideoPortReportResourceList.

If we dive deeper into the layout of the memory area, we can see that in all cases, the leaked bytes reside at the end of a nested CM_PARTIAL_RESOURCE_DESCRIPTOR structure:

--- cut ---
  kd> dt _CM_RESOURCE_LIST @rdx
  ntdll!_CM_RESOURCE_LIST
     +0x000 Count            : 1
     +0x004 List             : [1] _CM_FULL_RESOURCE_DESCRIPTOR

  kd> dx -r1 ((ntdll!_CM_FULL_RESOURCE_DESCRIPTOR (*)[1])0xfffff8a0049de878)
  ((ntdll!_CM_FULL_RESOURCE_DESCRIPTOR (*)[1])0xfffff8a0049de878)                 : 0xfffff8a0049de878 [Type: _CM_FULL_RESOURCE_DESCRIPTOR (*)[1]]
      [0]              [Type: _CM_FULL_RESOURCE_DESCRIPTOR]

  kd> dx -r1 ((ntdll!_CM_FULL_RESOURCE_DESCRIPTOR *)0xfffff8a0049de878)
  ((ntdll!_CM_FULL_RESOURCE_DESCRIPTOR *)0xfffff8a0049de878)                 : 0xfffff8a0049de878 [Type: _CM_FULL_RESOURCE_DESCRIPTOR *]
      [<Raw View>]     [Type: _CM_FULL_RESOURCE_DESCRIPTOR]
      [0]              : Port Resource: 0x3b0 of length 0xc [Type: _CM_PARTIAL_RESOURCE_DESCRIPTOR]
      [1]              : Port Resource: 0x3c0 of length 0x20 [Type: _CM_PARTIAL_RESOURCE_DESCRIPTOR]
      [2]              : Memory Resource: 0xa0000 of length 0x20000 [Type: _CM_PARTIAL_RESOURCE_DESCRIPTOR]
      [3]              : Port Resource: 0x1ce of length 0x2 [Type: _CM_PARTIAL_RESOURCE_DESCRIPTOR]
      [4]              : Port Resource: 0x2e8 of length 0x8 [Type: _CM_PARTIAL_RESOURCE_DESCRIPTOR]

  kd> dx -r1 ((ntdll!unsigned long (*)[4])(0xfffff8a0049de88c+sizeof(_CM_PARTIAL_RESOURCE_DESCRIPTOR)*0))
  ((ntdll!unsigned long (*)[4])(0xfffff8a0049de88c+sizeof(_CM_PARTIAL_RESOURCE_DESCRIPTOR)*0))                 : 0xfffff8a0049de88c [Type: unsigned long (*)[4]]
      [0]              : 0x3b0 [Type: unsigned long]
      [1]              : 0x0 [Type: unsigned long]
      [2]              : 0xc [Type: unsigned long]
      [3]              : 0xaaaaaaaa [Type: unsigned long]

  kd> dx -r1 ((ntdll!unsigned long (*)[4])(0xfffff8a0049de88c+sizeof(_CM_PARTIAL_RESOURCE_DESCRIPTOR)*1))
  ((ntdll!unsigned long (*)[4])(0xfffff8a0049de88c+sizeof(_CM_PARTIAL_RESOURCE_DESCRIPTOR)*1))                 : 0xfffff8a0049de8a0 [Type: unsigned long (*)[4]]
      [0]              : 0x3c0 [Type: unsigned long]
      [1]              : 0x0 [Type: unsigned long]
      [2]              : 0x20 [Type: unsigned long]
      [3]              : 0xaaaaaaaa [Type: unsigned long]

  kd> dx -r1 ((ntdll!unsigned long (*)[4])(0xfffff8a0049de88c+sizeof(_CM_PARTIAL_RESOURCE_DESCRIPTOR)*2))
  ((ntdll!unsigned long (*)[4])(0xfffff8a0049de88c+sizeof(_CM_PARTIAL_RESOURCE_DESCRIPTOR)*2))                 : 0xfffff8a0049de8b4 [Type: unsigned long (*)[4]]
      [0]              : 0xa0000 [Type: unsigned long]
      [1]              : 0x0 [Type: unsigned long]
      [2]              : 0x20000 [Type: unsigned long]
      [3]              : 0xaaaaaaaa [Type: unsigned long]

  kd> dx -r1 ((ntdll!unsigned long (*)[4])(0xfffff8a0049de88c+sizeof(_CM_PARTIAL_RESOURCE_DESCRIPTOR)*3))
  ((ntdll!unsigned long (*)[4])(0xfffff8a0049de88c+sizeof(_CM_PARTIAL_RESOURCE_DESCRIPTOR)*3))                 : 0xfffff8a0049de8c8 [Type: unsigned long (*)[4]]
      [0]              : 0x1ce [Type: unsigned long]
      [1]              : 0x0 [Type: unsigned long]
      [2]              : 0x2 [Type: unsigned long]
      [3]              : 0xaaaaaaaa [Type: unsigned long]

  kd> dx -r1 ((ntdll!unsigned long (*)[4])(0xfffff8a0049de88c+sizeof(_CM_PARTIAL_RESOURCE_DESCRIPTOR)*4))
  ((ntdll!unsigned long (*)[4])(0xfffff8a0049de88c+sizeof(_CM_PARTIAL_RESOURCE_DESCRIPTOR)*4))                 : 0xfffff8a0049de8dc [Type: unsigned long (*)[4]]
      [0]              : 0x2e8 [Type: unsigned long]
      [1]              : 0x0 [Type: unsigned long]
      [2]              : 0x8 [Type: unsigned long]
      [3]              : 0xaaaaaaaa [Type: unsigned long]
--- cut ---

There are two types of descriptors here: port and memory resources. Their corresponding structures within the CM_PARTIAL_RESOURCE_DESCRIPTOR.u union are:

--- cut ---
    struct {
      PHYSICAL_ADDRESS Start;
      ULONG            Length;
    } Port;
--- cut ---
    struct {
      PHYSICAL_ADDRESS Start;
      ULONG            Length;
    } Memory;
--- cut ---

The size of both these structures is 12 (0xc), but on x64 builds, the size of the overall union is 16 (0x10). This leaves the 4 bytes directly after the Port/Memory structures unused.

A proof-of-concept program is not provided for this issue, but it has been observed at normal system runtime, and is quite evident in the code.

Repeatedly triggering the vulnerability could allow local authenticated attackers to defeat certain exploit mitigations (kernel ASLR) or read other secrets stored in the kernel address space.

This bug is subject to a 90 day disclosure deadline. After 90 days elapse or a patch has been made broadly available, the bug report will become visible to the public.



Found by: mjurczyk

Copyright ©2024 Exploitalert.

All trademarks used are properties of their respective owners. By visiting this website you agree to Terms of Use.