Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=940
The DxgkDdiEscape handler for 0x70001b2 doesn't do proper bounds checks for its
variable size input.
void sub_8C4304(...) {
...
// escape_->size is controlled by the user.
if ( escape_->size < size )
size = escape_->size;
memcpy(escape_->data, v31, 28i64 * size);
...
}
Note that this appears to be a common pattern. Normally, before
escape handlers are executed, |PrivateDriverDataSize| (from DXGKARG_ESCAPE)
is checked to be equal to some value against a hardcoded table. However, some escapes
allow a more relaxed check that |PrivateDriverDataSize| >= minimum. This means that
the handler themselves must implement an ad hoc bounds check, which either seems to be
missing or implemented incorrectly (relying on a user specified value) in many cases.
bug 936 is a similar issue and there are likely more. I've noticed (but not confirmed)
a few more OOB reads that I haven't reported that follow this same pattern.
Crashing context with PoC (Win 10 x64 with 372.54):
PAGE_FAULT_IN_NONPAGED_AREA (50)
Invalid system memory was referenced. This cannot be protected by try-except.
Typically the address is just plain bad or it is pointing at freed memory.
Arguments:
...
rax=ffffd000239d51dc rbx=0000000000000000 rcx=fffffffffffffff4
rdx=fffff000e9e6c754 rsi=0000000000000000 rdi=0000000000000000
rip=fffff80166d6aca0 rsp=ffffd000239d3df8 rbp=ffffd000239d3f00
r8=0000000000000924 r9=000000000000003b r10=000000000000e9ef
r11=ffffd000239d48ac r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0 nv up ei ng nz ac pe cy
nvlddmkm+0x5daca0:
fffff801`66d6aca0 f30f7f40f0 movdqu xmmword ptr [rax-10h],xmm0 ds:ffffd000`239d51cc=????????????????????????????????
Resetting default scope
To reproduce, compile as an x64 executable an run (requires WDK for D3DKMTEscape).
Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/40664.zip