Exploit the possiblities

Microsoft Windows Kernel ATMFD.DLL NamedEscape 0x250D Pool Corruption

Microsoft Windows Kernel ATMFD.DLL NamedEscape 0x250D Pool Corruption
Posted Jan 10, 2018
Authored by Google Security Research, mjurczyk

The Microsoft Windows OpenType ATMFD.DLL kernel-mode font driver has an undocumented "escape" interface, handled by the standard DrvEscape and DrvFontManagement functions implemented by the module. The interface is very similar to Buffered IOCTL in nature, and handles 13 different operation codes in the numerical range of 0x2502 to 0x2514. It is accessible to user-mode applications through an exported (but not documented) gdi32!NamedEscape function, which internally invokes the NtGdiExtEscape syscall.

tags | advisory, kernel
systems | windows
advisories | CVE-2018-0788
MD5 | 96b46447ba7a6c968d0db2900d57b8a3

Microsoft Windows Kernel ATMFD.DLL NamedEscape 0x250D Pool Corruption

Change Mirror Download
Windows Kernel ATMFD.DLL NamedEscape 0x250D pool corruption due to malformed .MMM metrics 

CVE-2018-0788


The OpenType ATMFD.DLL kernel-mode font driver on Windows has an undocumented "escape" interface, handled by the standard DrvEscape and DrvFontManagement functions implemented by the module. The interface is very similar to Buffered IOCTL in nature, and handles 13 different operation codes in the numerical range of 0x2502 to 0x2514. It is accessible to user-mode applications through an exported (but not documented) gdi32!NamedEscape function, which internally invokes the NtGdiExtEscape syscall.

It is difficult to understand the functionality and design of the various escape codes based on the ATMFD.DLL image alone, as no debug symbols are provided for it on the Microsoft Symbol Server. However, such symbols are available for the ATMLIB.DLL user-mode client library which uses the interface, and more importantly for fontdrvhost.exe, the sandboxed user-mode font driver on Windows 10, which shares most of its code with ATMFD. These two sources of information are invaluable in reverse-engineering the NamedEscape code area. All symbols referenced in this report were originally found in fontdrvhost.pdb, but can also be applied to the corresponding code in ATMFD.

The problem discussed in this report is caused by the fact that ATMFD lacks any sort of sanitization of the font metrics found in .MMM files (Multiple Master Metrics); and specifically the "first char" and "last char" fields. The equivalent .PFM files (Type-1 font metrics) have the 8-bit dfFirstChar and dfLastChar fields at offsets 95 and 96, and the internal ValidatePFMPointers() function verifies that dfLastChar >= dfFirstChar:

--- cut ---
.text:000217C8 mov esi, _pfmBase
.text:000217CE lea ebx, [esi+75h]
.text:000217D1 movzx edi, byte ptr [esi+dfLastChar]
.text:000217D5 movzx eax, byte ptr [esi+dfFirstChar]
.text:000217D9 sub edi, eax
.text:000217DB inc edi
.text:000217DC cmp edi, ecx
.text:000217DE jle loc_218CB
--- cut ---

If dfLastChar is not greater or equal to dfFirstChar, the font loading is aborted. However, there is no adequate ValidateMMMPointers() function, and so an attacker can set these fields (at offsets 170 and 172) to arbitrary values in .MMM files, including scenarios where dfFirstChar > dfLastChar.

One function that makes use of the saved first/last char indexes is MakePFM(), called by BDMakePFM(), which is the handler function for escape code 0x250D. The routine wrongly assumes that dfFirstChar may never be greater than dfLastChar, and so it uses the "dfLastChar - dfFirstChar" expression in a number of places to determine the number of characters in the font. The result is then used for calculating buffer sizes and offsets in memory.

When dfFirstChar is greater than dfLastChar, the result of "dfLastChar - dfFirstChar" is negative, causing MakePFM() to miscalculate the required size of the output buffer and offsets within it. This could in turn lead to various types of pool corruption, such as continuous buffer overflow, buffer underflow, or even a non-continuous overflow with a controlled offset relative to the output buffer. The last mentioned primitive can be achieved by overwriting an offset stored within the generated PFM structures, that in theory should not be overwritten during the subsequent loops that use it, but it becomes possible with the negative offsets in play.

Two examples of system bugchecks generated on Windows 7 32-bit are shown below. The first one is caused by an invalid memory write with a partially controlled index (the "cccc" part in 0x00cccc84), while the second one is due to an attempt to write to a memory region before the allocated output buffer (note the negative 0xfffffeea offset). It is advised to enable the Special Pools mechanism for win32k.sys to reliably reproduce the crashes.

--- cut ---
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:
Arg1: ffd90cda, memory referenced.
Arg2: 00000001, value 0 = read operation, 1 = write operation.
Arg3: 94c52169, If non-zero, the instruction address which referenced the bad memory
address.
Arg4: 00000000, (reserved)

[...]

TRAP_FRAME: 9ba7c61c -- (.trap 0xffffffff9ba7c61c)
ErrCode = 00000002
eax=00000120 ebx=00330000 ecx=ff0c4054 edx=00cccc84 esi=ff0c4054 edi=00000000
eip=94c52169 esp=9ba7c690 ebp=9ba7c754 iopl=0 nv up ei ng nz na po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010282
ATMFD+0x12169:
94c52169 88441102 mov byte ptr [ecx+edx+2],al ds:0023:ffd90cda=??
Resetting default scope

LAST_CONTROL_TRANSFER: from 8292129b to 828a7aa8

STACK_TEXT:
9ba7c17c 8292129b 00000003 9cbc9f46 00000065 nt!RtlpBreakWithStatusInstruction
9ba7c1cc 82921d99 00000003 829919d0 0000001f nt!KiBugCheckDebugBreak+0x1c
9ba7c590 828ad8dd 00000050 ffd90cda 00000001 nt!KeBugCheck2+0x68b
9ba7c604 82886b18 00000001 ffd90cda 00000000 nt!MmAccessFault+0xbd
9ba7c604 94c52169 00000001 ffd90cda 00000000 nt!KiTrap0E+0xdc
WARNING: Stack unwind information not available. Following frames may be wrong.
9ba7c754 94c42178 ff0c4042 00000006 ff0c4054 ATMFD+0x12169
9ba7c7a0 94c44738 0f6e8917 00000000 0000250d ATMFD+0x2178
9ba7c7d4 94c44878 0000250d 0f6e86cf 00000000 ATMFD+0x4738
9ba7c80c 94f34653 00000000 00000000 0000250d ATMFD+0x4878
9ba7c838 94f346b3 00000000 00000000 0000250d win32k!atmfdFontManagement+0x49
9ba7c85c 94e758ab 00000000 0000250d 001000d4 win32k!atmfdEscape+0x1e
9ba7c8a0 94f2fa4b 00000000 0000250d 001000d4 win32k!PDEVOBJ::Escape+0x39
9ba7caec 94e6ebb4 9ba7cb70 0000250d 001000d4 win32k!GreNamedEscape+0x14c
9ba7cc0c 82883936 00000000 0037fd20 00000009 win32k!NtGdiExtEscape+0x32c
9ba7cc0c 77196c74 00000000 0037fd20 00000009 nt!KiSystemServicePostCall
001ffacc 00000000 00000000 00000000 00000000 ntdll!KiFastSystemCallRet
--- cut ---

--- cut ---
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:
Arg1: ff056f3e, memory referenced.
Arg2: 00000001, value 0 = read operation, 1 = write operation.
Arg3: 94d32115, If non-zero, the instruction address which referenced the bad memory
address.
Arg4: 00000000, (reserved)

[...]

TRAP_FRAME: 891a461c -- (.trap 0xffffffff891a461c)
ErrCode = 00000002
eax=fffffeea ebx=000000ff ecx=fea4cccc edx=ff057054 esi=ff057054 edi=00000000
eip=94d32115 esp=891a4690 ebp=891a4754 iopl=0 nv up ei pl nz ac po cy
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010213
ATMFD+0x12115:
94d32115 66890c02 mov word ptr [edx+eax],cx ds:0023:ff056f3e=????
Resetting default scope

LAST_CONTROL_TRANSFER: from 8292029b to 828a6aa8

STACK_TEXT:
891a417c 8292029b 00000003 1bf25859 00000065 nt!RtlpBreakWithStatusInstruction
891a41cc 82920d99 00000003 829909d0 0000001f nt!KiBugCheckDebugBreak+0x1c
891a4590 828ac8dd 00000050 ff056f3e 00000001 nt!KeBugCheck2+0x68b
891a4604 82885b18 00000001 ff056f3e 00000000 nt!MmAccessFault+0xbd
891a4604 94d32115 00000001 ff056f3e 00000000 nt!KiTrap0E+0xdc
WARNING: Stack unwind information not available. Following frames may be wrong.
891a4754 94d22178 ff057042 00000006 ff057054 ATMFD+0x12115
891a47a0 94d24738 1dce23b6 00000000 0000250d ATMFD+0x2178
891a47d4 94d24878 0000250d 1dce2c6e 00000000 ATMFD+0x4738
891a480c 94f84653 00000000 00000000 0000250d ATMFD+0x4878
891a4838 94f846b3 00000000 00000000 0000250d win32k!atmfdFontManagement+0x49
891a485c 94ec58ab 00000000 0000250d 001000d4 win32k!atmfdEscape+0x1e
891a48a0 94f7fa4b 00000000 0000250d 001000d4 win32k!PDEVOBJ::Escape+0x39
891a4aec 94ebebb4 891a4b70 0000250d 001000d4 win32k!GreNamedEscape+0x14c
891a4c0c 82882936 00000000 003bfd20 00000009 win32k!NtGdiExtEscape+0x32c
891a4c0c 77456c74 00000000 003bfd20 00000009 nt!KiSystemServicePostCall
002ff890 00000000 00000000 00000000 00000000 ntdll!KiFastSystemCallRet
--- cut ---

Exploitation of the vulnerability could allow local attackers to execute arbitrary code in the context of ring-0 and thus elevate their privileges in the operating system.

This bug is subject to a 90 day disclosure deadline. After 90 days elapse or a patch has been made broadly available, the bug report will become visible to the public.



Found by: mjurczyk

Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

Want To Donate?


Bitcoin: 18PFeCVLwpmaBuQqd5xAYZ8bZdvbyEWMmU

File Archive:

January 2018

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Jan 1st
    2 Files
  • 2
    Jan 2nd
    13 Files
  • 3
    Jan 3rd
    16 Files
  • 4
    Jan 4th
    39 Files
  • 5
    Jan 5th
    26 Files
  • 6
    Jan 6th
    40 Files
  • 7
    Jan 7th
    2 Files
  • 8
    Jan 8th
    16 Files
  • 9
    Jan 9th
    25 Files
  • 10
    Jan 10th
    28 Files
  • 11
    Jan 11th
    44 Files
  • 12
    Jan 12th
    32 Files
  • 13
    Jan 13th
    2 Files
  • 14
    Jan 14th
    4 Files
  • 15
    Jan 15th
    31 Files
  • 16
    Jan 16th
    0 Files
  • 17
    Jan 17th
    0 Files
  • 18
    Jan 18th
    0 Files
  • 19
    Jan 19th
    0 Files
  • 20
    Jan 20th
    0 Files
  • 21
    Jan 21st
    0 Files
  • 22
    Jan 22nd
    0 Files
  • 23
    Jan 23rd
    0 Files
  • 24
    Jan 24th
    0 Files
  • 25
    Jan 25th
    0 Files
  • 26
    Jan 26th
    0 Files
  • 27
    Jan 27th
    0 Files
  • 28
    Jan 28th
    0 Files
  • 29
    Jan 29th
    0 Files
  • 30
    Jan 30th
    0 Files
  • 31
    Jan 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2018 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close