Exploit-DB #38713
Description: Microsoft Windows Kernel - 'win32k.sys' Malformed TrueType Program TTF Font Processing Pool-Based Buffer Overflow (MS15-115)
Type: dos
Platform: windows
Date: 2015-11-16
Author: Google Security Research

Exploit:
Source: https://code.google.com/p/google-security-research/issues/detail?id=507

We have observed a number of Windows kernel crashes in the win32k.sys driver while processing corrupted TTF font files. An example of a crash log excerpt generated after triggering the bug is shown below:

---
DRIVER_PAGE_FAULT_BEYOND_END_OF_ALLOCATION (d6)
N bytes of memory was allocated and more than N bytes are being referenced.
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: fffff900c49ab000, memory referenced
Arg2: [PII_REDACTED], value 0 = read operation, 1 = write operation
Arg3: fffff96000324c14, if non-zero, the address which referenced memory.
Arg4: [PII_REDACTED], (reserved)

[...]

FAULTING_IP: 
win32k!or_all_N_wide_rotated_need_last+70
fffff960`00324c14 410802          or      byte ptr [r10],al

MM_INTERNAL_CODE:  0

DEFAULT_BUCKET_ID:  VISTA_DRIVER_FAULT

BUGCHECK_STR:  0xD6

CURRENT_IRQL:  0

TRAP_FRAME:  fffff[PII_REDACTED]0 -- (.trap 0xfffff[PII_REDACTED]0)
.trap 0xfffff[PII_REDACTED]0
NOTE: The trap frame does not contain all registers.
Some register values may be zeroed or incorrect.
rax=fffff880075318ff rbx=[PII_REDACTED] rcx=[PII_REDACTED]
rdx=[PII_REDACTED]0000ff rsi=[PII_REDACTED] rdi=[PII_REDACTED]
rip=fffff96000324c14 rsp=fffff[PII_REDACTED]0 rbp=fffffffffffffff5
 r8=00000000ffffffff  r9=fffff900c1b48995 r10=fffff900c49ab000
r11=[PII_REDACTED] r12=[PII_REDACTED] r13=[PII_REDACTED]
r14=[PII_REDACTED] r15=[PII_REDACTED]
iopl=0         nv up ei ng nz na po nc
win32k!or_all_N_wide_rotated_need_last+0x70:
fffff960`00324c14 410802          or      byte ptr [r10],al ds:0b08:fffff900`c49ab000=??
.trap
Resetting default scope

LAST_CONTROL_TRANSFER:  from fffff8000294a017 to fffff800028cd5c0

STACK_TEXT:  
fffff880`07531528 fffff800`0294a017 : 00000000`00000050 fffff900`c49ab[PII_REDACTED]0`00000001 fffff880`07531690 : nt!KeBugCheckEx
fffff880`07531530 fffff800`028cb6ee : 00000000`00000001 fffff900`c49ab000 fffff900`c4211000 fffff900`c49ab002 : nt! ?? ::FNODOBFM::`string'+0x4174f
fffff880`07531690 fffff960`00324c14 : 00000000`0000001f fffff960`000b8f1f fffff900`c4ed2f08 00000000`0000001f : nt!KiPageFault+0x16e
fffff880`07531820 fffff960`000b8f1f : fffff900`c4ed2f08 00000000`0000001f 00000000`[PII_REDACTED]`00000007 : win32k!or_all_N_wide_rotated_need_last+0x70
fffff880`07531830 fffff960`000eba0d : 00000000`00000000 fffff880`[PII_REDACTED]`[PII_REDACTED]`0000000a : win32k!draw_nf_ntb_o_to_temp_start+0x10f
fffff880`07531890 fffff960`000c5ab8 : 00000000`00000000 fffff900`c49aad60 fffff900`c4ed2ed0 00000000`00ffffff : win32k!vExpandAndCopyText+0x1c5
fffff880`07531c30 fffff960`00874b4b : fffff900`0000000a fffff880`00000002 fffff900`c4484ca0 fffff880`07532368 : win32k!EngTextOut+0xe54
fffff880`07531fc0 fffff900`0000000a : fffff880`00000002 fffff900`c4484ca0 fffff880`[PII_REDACTED]`00000000 : VBoxDisp+0x4b4b
fffff880`07531fc8 fffff880`00000002 : fffff900`c4484ca0 fffff880`[PII_REDACTED]`00000000 fffff880`07532110 : 0xfffff900`0000000a
fffff880`07531fd0 fffff900`c4484ca0 : fffff880`[PII_REDACTED]`00000000 fffff880`07532110 fffff900`c49b6d58 : 0xfffff880`00000002
fffff880`07531fd8 fffff880`07532368 : 00000000`00000000 fffff880`07532110 fffff900`c49b6d58 fffff900`c49b6de8 : 0xfffff900`c4484ca0
fffff880`07531fe0 00000000`00000000 : fffff880`07532110 fffff900`c49b6d58 fffff900`c49b6de8 fffff900`c49b6c30 : 0xfffff880`07532368
---

While the above is only one example, we have seen the issue manifest itself in a variety of ways: either by crashing while trying to write beyond a pool allocation in the win32k!or_all_4_wide_rotated_need_last, win32k!or_all_N_wide_rotated_need_last, win32k!or_all_N_wide_rotated_no_last or win32k!or_all_N_wide_unrotated functions, or in other locations in the kernel due to system instability caused by pool corruption. In all cases, the crash occurs somewhere below a win32k!EngTextOut function call, i.e. it is triggered while trying to display the glyphs of a malformed TTF on the screen, rather than while loading the font in the system.

We believe the condition to be a pool-based buffer overflow triggered by one of the above win32k.sys functions, with a binary -or- operation being performed on bytes outside a pool allocation. This is also confirmed by the fact that various system bugchecks we have observed are a consequence of the kernel trying to dereference addresses with too many bits set, e.g.:

---
rax=fffff91fc29b4c60 rbx=[PII_REDACTED] rcx=fffff900c4ede320
rdx=[PII_REDACTED] rsi=[PII_REDACTED] rdi=[PII_REDACTED]
rip=fffff96000271f6a rsp=fffff880035b8bd0 rbp=fffff880035b9780
 r8=[PII_REDACTED]00021d  r9=fffff900c4edf000 r10=fffff880056253f4
r11=fffff900c4902eb0 r12=[PII_REDACTED] r13=[PII_REDACTED]
r14=[PII_REDACTED] r15=[PII_REDACTED]
iopl=0         nv up ei ng nz na po nc
win32k!PopThreadGuardedObject+0x16:
fffff960`00271f6a 4c8918          mov     qword ptr [rax],r11 ds:0030:fffff91f`c29b4c60=????????????????
---

While we have not determined the specific root cause of the vulnerability, the proof-of-concept TTF files triggering the bug were created by taking legitimate fonts and replacing the glyph TrueType programs with ones generated by a dedicated generator. Therefore, the problem is almost certainly caused by some part of the arbitrary TrueType programs.

The issue reproduces on Windows 7 and 8.1. It is easiest to reproduce with Special Pools enabled for win32k.sys (typically leading to an immediate crash in one of the aforementioned functions when the overflow takes place), but it is also possible to observe a system crash on a default Windows installation as a consequence of pool corruption and resulting system instability. In order to reproduce the problem with the provided samples, it is necessary to use a custom program whi