xinali/articles

Microsoft Font Subsetting DLL heap-based out-of-bounds read in CreateFontPackage (CVE-2019-1468)

xinali opened this issue · 0 comments

Microsoft Font Subsetting DLL heap-based out-of-bounds read in CreateFontPackage

Please excuse my poor English. I'm not a native speaker. I will do my best to describe this bug.

I tested on sytem

windows 10 professional
v1903 x64 bit

fontsub background

The Microsoft Font Subsetting DLL (fontsub.dll) is a default Windows helper library for subsetting TTF fonts; i.e. converting fonts to their more compact versions based on the specific glyphs used in the document where the fonts are embedded. It is used by Windows GDI and Direct2D, and parts of the same code are also found in the t2embed.dll library designed to load and process embedded fonts.

The DLL exposes two API functions: CreateFontPackage and MergeFontPackage. I have tested CreateFontPackage with a fuzzer.

crash

when I use a specific ttf file with CreateFontPackage , it crashed

0:000> g
(3b28.2074): Access violation - code c0000005 (first/second chance not available)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
Time Travel Position: 3A2:0
msvcrt!memcpy+0x220:
00007ffb`b4544920 f30f7f40f0      movdqu  xmmword ptr [rax-10h],xmm0 ds:00000285`c7d0730a=????????????????????????????????

stack call

0:000> kb
 # RetAddr           : Args to Child                                                           : Call Site
00 00007ffb`a52a962a : 000000db`0376f3e8 0000017a`00000a7c 00005d61`c54c9886 000000db`0376f400 : msvcrt!memcpy+0x220
01 00007ffb`a52a927f : 00000000`fffffff0 000000db`0376f331 000000db`0376f3e8 00000000`0000017a : fontsub!ReadBytes+0x3e
02 00007ffb`a52a09b1 : 00000000`000001dc 000000db`0376f3e8 000000db`0376f3e8 00007ffb`a52a94f9 : fontsub!CopyTableOver+0xc7
03 00007ffb`a52973d3 : 00000000`00000000 000000db`0376f3e8 00000000`00000000 000000db`03760009 : fontsub!ModCmap+0x7d
04 00007ffb`a5296f89 : 00000284`c7cd1460 000000db`0376f591 00000000`00000001 00000000`00000001 : fontsub!CreateDeltaTTFEx+0x40f
05 00007ffb`a52913fa : 00000000`00000000 00000000`00000000 0000a4b2`e51c6297 00000000`00000000 : fontsub!CreateDeltaTTF+0x2c9
06 00007ff7`143d11c8 : 00000000`00000000 00000000`00000000 00000000`00000000 00000284`c7d05170 : fontsub!CreateFontPackage+0x15a

crash analysis

debug with time travel, return to function fontsub!ReadBytes

0:000> uf fontsub!ReadBytes:
00007ffb`a52a95ec 48895c2408      mov     qword ptr [rsp+8],rbx
00007ffb`a52a95f1 48896c2410      mov     qword ptr [rsp+10h],rbp
00007ffb`a52a95f6 4889742418      mov     qword ptr [rsp+18h],rsi
00007ffb`a52a95fb 57              push    rdi
00007ffb`a52a95fc 4883ec20        sub     rsp,20h
00007ffb`a52a9600 418bd8          mov     ebx,r8d
00007ffb`a52a9603 488bf2          mov     rsi,rdx
00007ffb`a52a9606 8bd3            mov     edx,ebx
00007ffb`a52a9608 4d8bc1          mov     r8,r9
00007ffb`a52a960b 4d8bd9          mov     r11,r9
00007ffb`a52a960e 488bf9          mov     rdi,rcx
00007ffb`a52a9611 e8f6fdffff      call    fontsub!CheckInOffset (00007ffb`a52a940c)
00007ffb`a52a9616 33ed            xor     ebp,ebp
00007ffb`a52a9618 6685c0          test    ax,ax
00007ffb`a52a961b 7510            jne     fontsub!ReadBytes+0x41 (00007ffb`a52a962d)  Branch

fontsub!ReadBytes+0x31:
00007ffb`a52a961d 8bd3            mov     edx,ebx
00007ffb`a52a961f 488bce          mov     rcx,rsi
00007ffb`a52a9622 480317          add     rdx,qword ptr [rdi]
00007ffb`a52a9625 e8e8130000      call    fontsub!memcpy (00007ffb`a52aaa12)
00007ffb`a52a962a 0fb7c5          movzx   eax,bp

fontsub!ReadBytes+0x41:
00007ffb`a52a962d 488b5c2430      mov     rbx,qword ptr [rsp+30h]
00007ffb`a52a9632 488b6c2438      mov     rbp,qword ptr [rsp+38h]
00007ffb`a52a9637 488b742440      mov     rsi,qword ptr [rsp+40h]
00007ffb`a52a963c 4883c420        add     rsp,20h
00007ffb`a52a9640 5f              pop     rdi
00007ffb`a52a9641 c3              ret

set breakpint in

00007ffb`a52a9625 e8e8130000      call    fontsub!memcpy (00007ffb`a52aaa12)

check

0:000> ub .
fontsub!ReadBytes+0x22:
00007ffb`a52a960e 488bf9          mov     rdi,rcx
00007ffb`a52a9611 e8f6fdffff      call    fontsub!CheckInOffset (00007ffb`a52a940c)
00007ffb`a52a9616 33ed            xor     ebp,ebp
00007ffb`a52a9618 6685c0          test    ax,ax
00007ffb`a52a961b 7510            jne     fontsub!ReadBytes+0x41 (00007ffb`a52a962d)
00007ffb`a52a961d 8bd3            mov     edx,ebx
00007ffb`a52a961f 488bce          mov     rcx,rsi
00007ffb`a52a9622 480317          add     rdx,qword ptr [rdi]
0:000> ? rcx
Evaluate expression: 2773606232480 = 00000285`c7d071a0
0:000> ? rdx
Evaluate expression: 2769311261228 = 00000284`c7d0622c
0:000> dd rdx
00000284`c7d0622c  03000000 00000000 24010000 00000100
00000284`c7d0623c  1c000000 01000300 24010000 06010000
00000284`c7d0624c  00010000 00000000 03000000 02000000
00000284`c7d0625c  00000000 00000000 00000000 00000000
00000284`c7d0626c  00030000 00000000 00000000 00000000
00000284`c7d0627c  00000000 00000000 00000000 00000000
00000284`c7d0628c  00000000 04000000 00050000 00000000
00000284`c7d0629c  00000000 00000000 00000600 00000000
0:000> dps rdx
00000284`c7d0622c  00000000`03000000
00000284`c7d06234  00000100`24010000
00000284`c7d0623c  01000300`1c000000
00000284`c7d06244  06010000`24010000
00000284`c7d0624c  00000000`00010000
00000284`c7d06254  02000000`03000000
00000284`c7d0625c  00000000`00000000
00000284`c7d06264  00000000`00000000
00000284`c7d0626c  00000000`00030000
00000284`c7d06274  00000000`00000000
00000284`c7d0627c  00000000`00000000
00000284`c7d06284  00000000`00000000
00000284`c7d0628c  04000000`00000000
00000284`c7d06294  00000000`00050000
00000284`c7d0629c  00000000`00000000
00000284`c7d062a4  00000000`00000600
0:000> dd 00000000`03000000
00000000`03000000  ???????? ???????? ???????? ????????
00000000`03000010  ???????? ???????? ???????? ????????
00000000`03000020  ???????? ???????? ???????? ????????
00000000`03000030  ???????? ???????? ???????? ????????
00000000`03000040  ???????? ???????? ???????? ????????
00000000`03000050  ???????? ???????? ???????? ????????
00000000`03000060  ???????? ???????? ???????? ????????
00000000`03000070  ???????? ???????? ???????? ????????

memcpy use rdx as src, but it can not be accessed.

So it crashed. Because rdx in heap memory, so case heap-base out of bounds.

0:000> !heap -p -a rdx
    address 00000284c7d0622c found in
    _HEAP @ 284c7cf0000
              HEAP_ENTRY Size Prev Flags            UserPtr UserSize - state
        00000284c7d057a0 00da 0000  [00]   00000284c7d057b0    00d8d - (busy)

Conclusion

rdx in heap memory, and its data read from ttf file, so it can be controled. It may cause some import security issues.