Microsoft Windows - 'win32k.sys' TTF Processing win32k!sbit_Embolden / win32k!ttfdCloseFontContext Use-After-Free (MS16-120)

EDB-ID:

40599




Platform:

Windows

Date:

2016-10-20


Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=868

We have encountered Windows kernel crashes in the win32k!sbit_Embolden and win32k!ttfdCloseFontContext functions while processing corrupted TTF font files. Excerpts of them are shown below:

---
KERNEL_MODE_EXCEPTION_NOT_HANDLED (8e)
This is a very common bugcheck.  Usually the exception address pinpoints
the driver/function that caused the problem.  Always note this address
as well as the link date of the driver/image that contains this address.
Some common problems are exception code 0x80000003.  This means a hard
coded breakpoint or assertion was hit, but this system was booted
/NODEBUG.  This is not supposed to happen as developers should never have
hardcoded breakpoints in retail code, but ...
If this happens, make sure a debugger gets connected, and the
system is booted /DEBUG.  This will let us see why this breakpoint is
happening.
Arguments:
Arg1: c0000005, The exception code that was not handled
Arg2: 8e70bba3, The address that the exception occurred at
Arg3: 9b7e3a84, Trap Frame
Arg4: 00000000

Debugging Details:
------------------


EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s.

FAULTING_IP: 
win32k!MultiUserGreTrackRemoveEngResource+1c
8e70bba3 8901            mov     dword ptr [ecx],eax

TRAP_FRAME:  9b7e3a84 -- (.trap 0xffffffff9b7e3a84)
ErrCode = 00000002
eax=fa42ce68 ebx=fa42ce78 ecx=00000000 edx=00000000 esi=ff73a000 edi=fc4a4fc8
eip=8e70bba3 esp=9b7e3af8 ebp=9b7e3af8 iopl=0         nv up ei pl zr na pe nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010246
win32k!MultiUserGreTrackRemoveEngResource+0x1c:
8e70bba3 8901            mov     dword ptr [ecx],eax  ds:0023:00000000=????????
Resetting default scope

DEFAULT_BUCKET_ID:  WIN7_DRIVER_FAULT

BUGCHECK_STR:  0x8E

PROCESS_NAME:  csrss.exe

CURRENT_IRQL:  2

ANALYSIS_VERSION: 6.3.9600.17237 (debuggers(dbg).140716-0327) x86fre

LAST_CONTROL_TRANSFER:  from 82933d87 to 828cf978

STACK_TEXT:  
9b7e303c 82933d87 00000003 1d46c818 00000065 nt!RtlpBreakWithStatusInstruction
9b7e308c 82934885 00000003 9b7e3490 00000000 nt!KiBugCheckDebugBreak+0x1c
9b7e3450 82933c24 0000008e c0000005 8e70bba3 nt!KeBugCheck2+0x68b
9b7e3474 829092a7 0000008e c0000005 8e70bba3 nt!KeBugCheckEx+0x1e
9b7e3a14 828929a6 9b7e3a30 00000000 9b7e3a84 nt!KiDispatchException+0x1ac
9b7e3a7c 8289295a 9b7e3af8 8e70bba3 badb0d00 nt!CommonDispatchException+0x4a
9b7e3af8 8e70bbe6 ff73a000 fb77cd28 9b7e3b20 nt!Kei386EoiHelper+0x192
9b7e3b08 8e7ef63d ff73a010 8e7ef5c0 fb784cf0 win32k!EngFreeMem+0x16
9b7e3b20 8e7ef67c fa42ce78 9b7e3b98 9b7e3b3c win32k!ttfdCloseFontContext+0x51
9b7e3b30 8e7ef5d8 fb784cf0 9b7e3b74 8e7ef1f8 win32k!ttfdDestroyFont+0x16
9b7e3b3c 8e7ef1f8 fb784cf0 fe38ccf0 9b7e3bd8 win32k!ttfdSemDestroyFont+0x18
9b7e3b74 8e7ef41b fb784cf0 fe38ccf0 00000000 win32k!PDEVOBJ::DestroyFont+0x67
9b7e3ba4 8e7749c3 00000000 00000000 00000001 win32k!RFONTOBJ::vDeleteRFONT+0x33
9b7e3bcc 8e77660f 9b7e3bf0 fb784cf0 00000000 win32k!vRestartKillRFONTList+0x8d
9b7e3c00 8e84100e 00000006 fb284fc0 8eaf8fc8 win32k!PFTOBJ::bUnloadWorkhorse+0x15f
9b7e3c28 82891dc6 0500019c 002cf9cc 76e26bf4 win32k!GreRemoveFontMemResourceEx+0x60
9b7e3c28 76e26bf4 0500019c 002cf9cc 76e26bf4 nt!KiSystemServicePostCall
002cf9cc 00000000 00000000 00000000 00000000 ntdll!KiFastSystemCallRet
---

And:

---
PAGE_FAULT_IN_FREED_SPECIAL_POOL (cc)
Memory was referenced after it was freed.
This cannot be protected by try-except.
When possible, the guilty driver's name (Unicode string) is printed on
the bugcheck screen and saved in KiBugCheckDriver.
Arguments:
Arg1: fc1ffa54, memory referenced
Arg2: 00000001, value 0 = read operation, 1 = write operation
Arg3: 82848a05, if non-zero, the address which referenced memory.
Arg4: 00000000, Mm internal code.

Debugging Details:
------------------


WRITE_ADDRESS:  fc1ffa54 Special pool

FAULTING_IP: 
nt!memset+45
82848a05 f3ab            rep stos dword ptr es:[edi]

MM_INTERNAL_CODE:  0

DEFAULT_BUCKET_ID:  WIN7_DRIVER_FAULT

BUGCHECK_STR:  0xCC

PROCESS_NAME:  csrss.exe

CURRENT_IRQL:  2

ANALYSIS_VERSION: 6.3.9600.17237 (debuggers(dbg).140716-0327) x86fre

TRAP_FRAME:  8fb73d58 -- (.trap 0xffffffff8fb73d58)
ErrCode = 00000002
eax=00000000 ebx=00000001 ecx=00000001 edx=00000000 esi=00000004 edi=fc1ffa54
eip=82848a05 esp=8fb73dcc ebp=8fb73e28 iopl=0         nv up ei pl nz na po nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010202
nt!memset+0x45:
82848a05 f3ab            rep stos dword ptr es:[edi]
Resetting default scope

LAST_CONTROL_TRANSFER:  from 828eed87 to 8288a978

STACK_TEXT:  
8fb738ac 828eed87 00000003 766f335a 00000065 nt!RtlpBreakWithStatusInstruction
8fb738fc 828ef885 00000003 00000000 0000000a nt!KiBugCheckDebugBreak+0x1c
8fb73cc0 8289d94d 00000050 fc1ffa54 00000001 nt!KeBugCheck2+0x68b
8fb73d40 8284ffa8 00000001 fc1ffa54 00000000 nt!MmAccessFault+0x104
8fb73d40 82848a05 00000001 fc1ffa54 00000000 nt!KiTrap0E+0xdc
8fb73dcc 8f15cca0 fc1ffa54 00000000 00000004 nt!memset+0x45
8fb73e28 8f050c00 0000000b 00000004 c0000002 win32k!sbit_Embolden+0x34d
8fb73e68 8efc3e10 fb972fd0 fc200ea0 faec6040 win32k!sbit_GetBitmap+0x18c
8fb73eb4 8efc9ff1 fc200010 fc20007c faec6040 win32k!fs_ContourScan+0x192
8fb73ff8 8efbef89 00000028 00000020 faec6000 win32k!lGetGlyphBitmap+0x1aa
8fb74020 8efbedd6 00000000 00000001 00000020 win32k!ttfdQueryFontData+0x15e
8fb74070 8efbdff2 fbf98010 fa794cf0 00000001 win32k!ttfdSemQueryFontData+0x45
8fb740b8 8f14eef5 fbf98010 fa794cf0 00000001 win32k!PDEVOBJ::QueryFontData+0x3e
8fb740e8 8f14ef48 fc586f20 ffa84130 8fb74114 win32k!RFONTOBJ::bInsertGlyphbitsLookaside+0xa7
8fb740f8 8f050663 0000000a fc586f20 8fb74798 win32k!RFONTOBJ::cGetGlyphDataLookaside+0x1c
8fb74114 8f03b2fc 8fb74798 8fb74148 8fb74144 win32k!STROBJ_bEnum+0x6c
8fb7414c 8f03b4d9 00000001 8fb74358 00000d0d win32k!GetTempTextBufferMetrics+0x61
8fb743d4 8ee34042 fc1cadb8 8fb74798 fa794cf0 win32k!EngTextOut+0x26
WARNING: Stack unwind information not available. Following frames may be wrong.
8fb74410 8f13cce0 fb16edb8 8fb74798 fa794cf0 VBoxDisp+0x4042
8fb7446c 8f03dbcb fef7cc90 8fb74798 fa794cf0 win32k!WatchdogDrvTextOut+0x51
8fb744b8 8f03de38 8f13cc8f 8fb74724 fb16edb8 win32k!OffTextOut+0x71
8fb7473c 8f03d9a8 fb16edb8 8fb74798 fa794cf0 win32k!SpTextOut+0x1a2
8fb74a38 8efcc2d4 8fb74bfc fc0b8e20 fc0b8e7c win32k!GreExtTextOutWLocked+0x1040
8fb74ab4 8f01f251 00000000 ff7bf064 00001000 win32k!GreBatchTextOut+0x1e6
8fb74c24 8284cd5c 000000bc 001afd88 001afdb4 win32k!NtGdiFlushUserBatch+0x123
8fb74c34 76f16bf3 badb0d00 001afd88 00000000 nt!KiSystemServiceAccessTeb+0x10
8fb74c38 badb0d00 001afd88 00000000 00000000 ntdll!KiFastSystemCall+0x3
8fb74c3c 001afd88 00000000 00000000 00000000 0xbadb0d00
8fb74c40 00000000 00000000 00000000 00000000 0x1afd88
---

While the two above crashes look differently, we believe they manifest a single security issue, as they occur interchangeably with our proof of concept files. The first one is a NULL pointer dereference while performing a list unlinking operation, while the second is an attempt to write to memory which has already been freed, and they both indicate a use-after-free condition. While we have not determined the specific root cause of the vulnerability, we have pinpointed the offending mutations to reside in the "OS/2" and "VDMX" tables.

The issue reproduces on Windows 7 and 8.1. It is easiest to reproduce with Special Pools enabled for win32k.sys (leading to an immediate crash when the bug is triggered), but it is also possible to observe a crash on a default Windows installation. In order to reproduce the problem with the provided samples, it might be necessary to use a custom program which displays all of the font's glyphs at various point sizes. It is also required for the "Adjust for best performance" option to be set in "System > Advanced system settings > Advanced > Performance > Settings", most likely due to the "Smooth edges of screen fonts" getting unchecked.

Attached is an archive with three proof of concept font files.


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/40599.zip