Source: DxgkDdiSubmitCommandVirtual is the function implemented by the kernel mode driver responsible for submitting a command buffer to the GPU. One of the arguments passed contains vendor specific data from the user mode driver. The kernel allocates a single buffer for this purpose for all submit calls for the same context. NVIDIA implements this data as: struct NvPrivateHeader { DWORD magic; WORD unknown_4; WORD unknown_6; DWORD unknown_8; DWORD size; }; struct NvPrivateData { NvPrivateHeader header; DWORD unknown_0; DWORD unknown_1; DWORD some_size; DWORD unknown_2; PVOID a_gpu_address_maybe; BYTE unknown[1220]; }; In one of the functions that process this data, there appears to be code to shift around the contents of this user private data. // |len| is controlled by the user. can come from the |some_size| field if the |a_gpu_address_maybe| field is 0. if ( len ) { if ( 8 * len >= pCommand_->DmaBufferPrivateDataSize - 0x4E8 ) do_debug_thingo(); // doesn't stop the memcpy priv_data = (NvSubmitPrivateData *)pCommand_->pDmaBufferPrivateData; src = (char *)priv_data + priv_data->header.size; // unchecked length priv_data = (NvSubmitPrivateData *)((char *)priv_data + 1256); *(_QWORD *)&v4->unknown_0[256] = priv_data; // potential bad memcpy memcpy(priv_data, src, 8 * len); } There are two main problems here: the |len| value is checked, but that appears to only call a debug logging function and not actually stop the memcpy that occurs afterwards. Also, the |size| field from the header is not properly checked to be smaller than the actual size of the data (this is also checked in the calling function but once again only calls do_debug_thingo()). This lets an attacker specify an arbitrary length for the copy, as well as specify an arbitrary 32-bit offset to copy from, leading to pool memory corruption. Crashing context with PoC (Win 10 x64, driver version 375.95): PAGE_FAULT_IN_NONPAGED_AREA (50) ... rax=0000000000000008 rbx=0000000000000000 rcx=ffffb2087fe8f4f0 rdx=0000000041413c59 rsi=0000000000000000 rdi=0000000000000000 rip=fffff8035fc15b00 rsp=ffffd88179edd1a8 rbp=0000000000000080 r8=00000000020a0a08 r9=0000000000105050 r10=0000000000000000 r11=ffffb2087fe8f4f0 r12=0000000000000000 r13=0000000000000000 r14=0000000000000000 r15=0000000000000000 iopl=0 nv up ei ng nz na po nc nvlddmkm+0x5e5b00: fffff803`5fc15b00 f30f6f040a movdqu xmm0,xmmword ptr [rdx+rcx] ds:ffffb208`c12a3149=???????????????????????????????? Resetting default scope Proof of Concept: # Iranian Exploit DataBase = http://IeDb.Ir [2017-02-17]