Microsoft Windows - 'gdi32.dll' Multiple DIB-Related EMF Record Handlers Heap Out-of-Bounds Reads/Memory Disclosure (MS16-074)








As clearly visible in the EMF (Enhanced Metafile) image format specification ([MS-EMF]), there are multiple records which deal with DIBs (Device Independent Bitmaps). Examples of such records are EMR_ALPHABLEND, EMR_BITBLT, EMR_MASKBLT, EMR_PLGBLT, EMR_SETDIBITSTODEVICE, EMR_STRETCHBLT, EMR_STRETCHDIBITS, EMR_TRANSPARENTBLT, EMR_CREATEDIBPATTERNBRUSHPT, EMR_CREATEMONOBRUSH and EMR_EXTCREATEPEN.

The DIB format is relatively complex, since the headers and data itself may be interpreted in a number of ways depending on a combination of settings found in the headers. For example, various (de)compression algorithms can be applied to the data depending on the BITMAPINFOHEADER.biCompression field, and the image data can either be treated as RGB, or indexes into a color palette, depending on BITMAPINFOHEADER.biBitCount. The Windows API functions taking DIBs on input work under the assumption that the passed bitmap is valid, and particularly that there is enough memory in the image buffer to cover all picture pixels.

The EMF format essentially works as a proxy for GDI calls, and therefore the burden of a thorough DIB sanitization is on the underlying implementation. We have found the sanitization performed by a number of EMF record handlers in the gdi32.dll user-mode library to be insufficient, leading to heap-based out-of-bounds reads while parsing/loading the bitmap, and in some cases to a subsequent memory disclosure. Since the bugs are present in a core Windows library, all of its clients which allow the loading of arbitrary EMF images are affected. The severity is highest for software which makes it possible to recover the disclosed heap bytes, as an attacker could then steal secret information from the program's memory, or defeat the ASLR exploit mitigation mechanism to reliably take advantage of another vulnerability.

The DIB-embedding records follow a common scheme: they include four fields, denoting the offsets and lengths of the DIB header and DIB data, respectively (named offBmiSrc, cbBmiSrc, offBitsSrc, cbBitsSrc). A correct implementation should:

1) Verify that cbBmiSrc is within expected bounds, accounting for the DIB header, color palette etc.
2) Verify that the (offBmiSrc, offBmiSrc + cbBmiSrc) region resides within the record buffer's area.
3) Verify that cbBitsSrc is within expected bounds, and especially that it is larger or equal the expected number of bitmap bytes.
4) Verify that the (offBitsSrc, offBitsSrc + cbBitsSrc) region resides within the record buffer's area.

If any of the above steps is not executed correctly, it is possible for an attacker to craft an EMF file which causes gdi32.dll to attempt to create DIB objects based on out-of-bounds memory. As it turns out, many EMF record handlers fail to perform exhaustive sanitization. Our analysis was based on a 32-bit gdi32.dll file found in the C:\Windows\SysWOW64 directory on a fully patched Windows 7 operating system. The problems we have discovered are as follows:


Conditions (1) and (2) are not checked.


Condition (3) is not checked.


Conditions (1) and (3) are not checked.


Conditions (1), (2), (3) and (4) are not checked.

Please note that seeing the general class of bugs and how widespread it is across various DIB-related EMF handlers, we only performed a cursory analysis to see which checks are missing from which functions. It is possible that there are more missing sanity checks in some of them that we haven't noted in the list above. We recommend performing a careful security audit of the handlers dealing with DIBs, to ensure they perform correct and complete sanitization of the input data.

In order to demonstrate that the bug is real and affects Internet Explorer (among other targets - Microsoft Office 2013 was also tested), we have hacked up a proof-of-concept EMF file, which includes a specially crafted EMR_STRETCHBLT record, which in turn contains a 8 bpp DIB, whose palette entries go beyond the record area. Each time the image is opened in Internet Explorer, it is displayed differently, as the garbage heap bytes beyond the allocated buffer change. Attached is also a screenshot of the proof of concept picture, as displayed by Internet Explorer 11 on Windows 7 when opened three times in a row.

Proof of Concept: