header-logo
Suggest Exploit
vendor:
N/A
by:
Project Zero
7,8
CVSS
HIGH
Buffer Overflow
119
CWE
Product Name: N/A
Affected Version From: N/A
Affected Version To: N/A
Patch Exists: YES
Related CWE: N/A
CPE: N/A
Metasploit: N/A
Other Scripts: N/A
Tags: N/A
CVSS Metrics: N/A
Nuclei References: N/A
Nuclei Metadata: N/A
Platforms Tested: N/A
2018

ExAllocatePoolWithTag Uninitialized Memory Leak

ExAllocatePoolWithTag is called with a user provided size to allocate a buffer, but the subsequent copying of said buffer to the user provided pointer doesn't make sense since the buffer is never initialised with any values. This means that a user mode program can leak uninitialised memory from arbitrarily-sized pool allocations.

Mitigation:

Ensure that all allocated memory is initialized with valid values before passing it off to the user.
Source

Exploit-DB raw data:

Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=892

The handler for the DxgkDdiEscape escape code 0x70000D4 has the following pseudocode:

void __fastcall escape_70000D4(NvMiniportDeviceContext *a1, NvEscapeData *a2)
{
  Escape70000D4 *escape_data_; // rbx@1
  PVOID alloc_buf; // rsi@1
  unsigned int v4; // edi@1
  __int64 user_ptr; // r14@4
  DWORD *v6; // rbx@5
  __int128 v7; // [rsp+40h] [rbp-38h]@1
  __int128 v8; // [rsp+50h] [rbp-28h]@4
  PVOID alloc_buf_; // [rsp+60h] [rbp-18h]@4

  escape_data_ = (Escape70000D4 *)a2;
  a2->unknown_rest[6] = 1;
  LODWORD(v7) = 0;
  memset((char *)&v7 + 4, 0, 0x24ui64);
  alloc_buf = ExAllocatePoolWithTag_(PagedPool, escape_data_->user_ptr_size, 'paVN');
  v4 = 0;
  if ( !alloc_buf )
    v4 = 0xFFFF;
  if ( v4 )
    goto LABEL_12;
  HIDWORD(v8) = escape_data_->user_ptr_size;
  alloc_buf_ = alloc_buf;
  v4 = sub_625BC(0i64, dword_B1BB94, escape_data_->unknown_0, 0x83F30101, (__int64)&v7, 40);
  user_ptr = escape_data_->user_ptr;
  ProbeForWrite((PVOID)escape_data_->user_ptr, escape_data_->user_ptr_size, UserMode);
  memcpy((void *)escape_data_->user_ptr, alloc_buf, escape_data_->user_ptr_size);
  *(_OWORD *)&escape_data_->unknown_2 = v7;
  *(_OWORD *)&escape_data_->unknown_4 = v8;
  escape_data_->user_ptr = user_ptr;
  if ( v4 )
  {
LABEL_12:
    v6 = &escape_data_->header.unknown_rest[6];
    if ( v6 )
    {
      if ( v4 <= 0xFFFFF000 )
        *v6 = -4096 - v4;
    }
  }
  if ( alloc_buf )
    ExFreePoolWithTag_(alloc_buf, 0x7061564Eu);
}

ExAllocatePoolWithTag is called with a user provided size to allocate a buffer, but the subsequent copying of said buffer to the user provided pointer doesn't make sense since the buffer is never initialised with any values. This means that a user mode program can leak uninitialised memory from arbitrarily-sized pool allocations.

########

Looks like I made an oversimplified analysis of the pseudocode in the report. The allocated buffer pointer is indeed passed off to the sub_625BC function (as part of a struct member on the stack) which eventually passes it to a bunch of other functions.

However, this doesn't change the fact that with the provided PoC, the pool allocated buffer still isn't being initialised and is copied into the user buffer unchanged.


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/40656.zip