NVIDIA Driver - No Bounds Checking in Escape 0x7000194

EDB-ID:

40658




Platform:

Windows

Date:

2016-10-31


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

The DxgkDdiEscape handler for 0x7000194 doesn't do bounds checking with the
user provided lengths it receives. When these lengths are passed to memcpy,
overreads and memory corruption can occur.

void __fastcall escape_7000194(NvMiniportDeviceContext *ctx, Escape7000194 *escape_data)
  ...

  alloc_0_ = ExAllocatePoolWithTag_(PagedPool, escape->size_0, 0x7061564Eu);

  ...

  alloc_1 = ExAllocatePoolWithTag_(PagedPool, escape->size_1, 0x7061564Eu);

  ..

  if ( (_BYTE)v11 ) {
    memcpy(alloc_0, escape->buf_0, escape->size_0);
    memcpy(alloc_1, escape->buf_2, escape->size_1);
  }
  v8 = Escape7Handler(0i64, dword_7DCB84, *(_DWORD *)(v3 + 24), 0x402C0105, &escape->data, 96);
  v9 = v8;
  if ( !(_BYTE)v11 && !v8 )
    memcpy(escape->buf_0, alloc_0, escape->size_0);

  ...

The PoC I've provided causes an OOB read, but it should be possible to pass an
input that results in the third memcpy being executed instead of the first two,
which leads to kernel memory corruption (OOB write).

(Win 10 x64 372.54) crashing context with PoC:

PAGE_FAULT_IN_NONPAGED_AREA (5)
...
Some register values may be zeroed or incorrect.
rax=0000000000000007 rbx=0000000000000000 rcx=ffffc000f5220f80
rdx=fffffffff3d5509c rsi=0000000000000000 rdi=0000000000000000
rip=fffff8007d4dad66 rsp=ffffd00166b9d2a8 rbp=ffffc000e8f55038
 r8=0000000000020fc0  r9=000000000006603e r10=0000000000020000
r11=ffffc000f5200000 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0         nv up ei pl nz na pe nc
nvlddmkm+0x5dad66:
fffff800`7d4dad66 f30f6f4c0ae0    movdqu  xmm1,xmmword ptr [rdx+rcx-20h] ds:ffffc000`e8f75ffc=????????????????????????????????
Resetting default scope

To reproduce, compile the PoC as a x64 binary (requires linking with
setupapi.lib, and WDK for D3DKMTEscape), and run. It may require some changes
as for it to work as the escape data must contain the right values (e.g. a
field that appears to be gpu bus device function). My PoC should hopefully set
all the right values for the machine it's running on.


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