Exploit-DB #39832
Description: Microsoft Windows - 'gdi32.dll' Multiple 'EMF CREATECOLORSPACEW' Record Handling (MS16-055)
Type: dos
Platform: windows
Date: 2016-05-17
Author: Google Security Research

Exploit:
Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=722

There are multiple programming errors in the implementation of the CREATECOLORSPACEW record in EMF files, as found in the user-mode gdi32.dll system library. The worst of them may lead to reading beyond allocated heap-based buffers, leading to a crash or potential disclosure of the library client's memory (e.g. Internet Explorer's). Another bug may also lead to disclosure of information regarding the existence of arbitrary files in the file system.

Each of the discovered bugs is briefly described below. The 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.

--------------------------------------------------------------------------------
- Out-of-bounds read of EMR_CREATECOLORSPACEW.cbData in MRCREATECOLORSPACEW::bCheckRecord
--------------------------------------------------------------------------------

The MRCREATECOLORSPACEW::bCheckRecord() function starts off by checking if the length of the record is greater or equal than 0x50 (80):

--- cut ---
.text:7DB01AEF                 mov     eax, [esi+4]
.text:7DB01AF2                 cmp     eax, 50h
.text:7DB01AF5                 jb      short loc_7DB01B1E
--- cut ---

and then immediately proceeds to reading the .cbData field at offset 0x25c (604):

--- cut ---
.text:7DB01AF7                 mov     ecx, [esi+25Ch]
--- cut ---

Since the record is not guaranteed to be large enough to hold the value at +0x25c, the instruction shown above can read beyond the allocated buffer. The attached oob.emf file illustrates this issue.

--------------------------------------------------------------------------------
- Integer overflow when checking EMR_CREATECOLORSPACEW.cbData in MRCREATECOLORSPACEW::bCheckRecord
--------------------------------------------------------------------------------

Furthermore, the value obtained from offset +0x25c is also used to verify the record length, as part of the (record.length <= ((record->cbData + 0x263) & 0xfffffffc)) expression:

--- cut ---
.text:7DB01AF7                 mov     ecx, [esi+25Ch]
.text:7DB01AFD                 add     ecx, 263h
.text:7DB01B03                 and     ecx, 0FFFFFFFCh
.text:7DB01B06                 cmp     eax, ecx
.text:7DB01B08                 ja      short loc_7DB01B1E
--- cut ---

Since there is no overflow check in the arithmetic operation, if the cbData field is sufficiently large, it may overflow the 32-bit type. It is not clear, however, why the record length is required to be *smaller* than the structure's field in the first place (intuitively, it should be larger). Whether this is a mistake or not doesn't really seem to matter, as the optional color space data is not used further in the MRCREATECOLORSPACEW::bPlay() function anyway.

--------------------------------------------------------------------------------
- Out-of-bounds read in CreateColorSpaceW
--------------------------------------------------------------------------------

The LOGCOLORSPACEW structure passed to CreateColorSpaceW() by MRCREATECOLORSPACEW::bPlay() is assumed to be at least 0x24c (588) bytes long. However, as we've seen before, the record is only guaranteed to be at least 80 bytes long. As a result, in case of a specially crafted small record, the CreateColorSpaceW() function could operate on data well beyond the record's buffer. The memory from outside the buffer could then be potentially recovered by reading back pixels using the HTML5 canvas API, and deriving the uninitialized values of the LOGCOLORSPACEW structure.

The attached oob.emf file also illustrates this issue (in terms of passing OOB heap data to CreateColorSpaceW), provided that the out-of-bounds .cbData check passes successfully in MRCREATECOLORSPACEW::bCheckRecord(), but this is very likely as there are only a few specific values of .cbData which could cause it to fail.

--------------------------------------------------------------------------------
- File existence information disclosure in CreateColorSpaceW
--------------------------------------------------------------------------------

This is perhaps the most interesting bug found in the handling of the CREATECOLORSPACEW / CREATECOLORSPACE EMF records. After being passed a specially crafted LOGCOLORSPACEW structure, the CreateColorSpaceW() function builds a file path based on the LOGCOLORSPACEW.lcsFilename field, using the BuildIcmProfilePath() routine:

--- cut ---
.text:7DAEF12E                 push    104h            ; cchDest
.text:7DAEF133                 lea     eax, [ebp+FileName]
.text:7DAEF139                 push    eax             ; pszDest
.text:7DAEF13A                 push    ebx             ; pszSrc
.text:7DAEF13B                 call    _BuildIcmProfilePath@12 ; BuildIcmProfilePath(x,x,x)
--- cut ---

While paths starting with "\\" are forbidden (limiting access to remote or internal system resources), all other paths, including absolute ones, are allowed. The function then attempts to open the file in order to make sure that it exists, and if this succeeds, the resulting handle is immediately closed:

--- cut ---
      hFile = CreateFileW(&FileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
      if ( hFile == INVALID_HANDLE_VALUE )
      {
        GdiSetLastError(2016);
        return 0;
      }
      CloseHandle(hFile);
--- cut ---

Only if the file exists, the code proceeds to invoking the NtGdiCreateColorSpace system call, which creates a Color Space GDI object based on the input structure. This behavior can be used to disclose information regarding the existence of specific (attacker-chosen) files in the file system through applications (GDI client) which enable the propagation of rendered image's pixels back to the attacker, such as the Internet Explorer web browser.

The most intuitiv