CVE Number
Summary
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.
The DLL exposes two API functions: CreateFontPackage and MergeFontPackage. We have developed a test exploit to invoke a sequence of library APIs. This report describes an issue triggered by a malformed font file in fontsub.dll code through our exploit.
Our initial tested version
Windows 10 x64 version 1909 with fontsub.dll version 10.0.18362.535 (WinBuild.160101.0800).
Affected version (confirmed by Microsoft)
All version of Windows from Windows 7 to Windows 10 latest version (prior to Patch Tuesday this month) and Windows Server 2008 to Windows Server latest version (prior to Patch Tuesday this month). See CVE-2020-0687 link above for more details.
CVSSv3
Score 8.8CVSS:3.0/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H/E:P/RL:O/RC:C
Details
During fuzzing 2 APIs of fontsub.dll, an invalid font file will cause an error in the MergeFontPackage function.
Function MergeFontPackage is shown below:
unsigned long MergeFontPackage(
const unsigned char *puchMergeFontBuffer,
const unsigned long ulMergeFontBufferSize,
const unsigned char *puchFontPackageBuffer,
const unsigned long ulFontPackageBufferSize,
unsigned char **ppuchDestBuffer,
unsigned long *pulDestBufferSize,
unsigned long *pulBytesWritten,
const unsigned short usMode,
CFP_ALLOCPROC lpfnAllocate,
CFP_REALLOCPROC lpfnReAllocate,
CFP_FREEPROC lpfnFree,
void *lpvReserved
);
The process flow of the function is shown below:
![]() |
Figure 1: Processing flow of the MergeFontPackage function |
![]() |
Figure 2: bitmaptable initialization handler function in MergeEblcEbdtTables |
Then run into the while loop to execute the ReadTableIntoStructure function, the condition to exit the loop is when the variable runs j > unk_v3 (value of Table_array).
Inside the ReadTableIntoStructure function, the processing part is shown below:
![]() |
Figure 3: The processing code that causes an error in the ReadTableIntoStructure function |
It also runs a loop to fill in the struct bitmaptable. In this function, we also check to see if the capacity of arr is exceeded, but there is a problem in line 156 where it checks size_1 with the capacity of arr is size_arr, but the placement is not reasonable.
Take the following example:
- If size_1 = 1 and bitmaptable-> size_arr = 2 => the condition in line 156 will not be satisfied, so the while loop will continue.
- Go to test i with glyphArray. Assuming i will be less than glyphArray => the condition in line 166 is not satisfied and the program returns to the while loop at this time size_1 is equal to 2 and an error occurs in line 150.
![]() |
Figure 4: Crash context |
This leads to out of bound write memory. It could be potentially used to execute arbitrary code in the context of the FontSub client process. It is easiest to reproduce with PageHeap enabled, but it is also possible to observe a crash in a default system configuration.
Crash information
(6b80.7284): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
FONTSUB!ReadTableIntoStructure+0x22f:
00007ffa`1f0e485b 6689440a10 mov word ptr [rdx+rcx+10h],ax ds:000001b4`6ad3f010=????
0:000> !analyze -v
*******************************************************************************
* *
* Exception Analysis *
* *
*******************************************************************************
KEY_VALUES_STRING: 1
TIMELINE_ANALYSIS: 1
Timeline: !analyze.Start
Name: <blank>
Time: 2020-04-02T12:27:38.906Z
Diff: 1093 mSec
Timeline: Dump.Current
Name: <blank>
Time: 2020-04-02T12:27:40.0Z
Diff: 0 mSec
Timeline: Process.Start
Name: <blank>
Time: 2020-04-02T12:12:45.0Z
Diff: 895000 mSec
Timeline: OS.Boot
Name: <blank>
Time: 2020-03-23T12:28:16.0Z
Diff: 863964000 mSec
DUMP_CLASS: 2
DUMP_QUALIFIER: 0
FAULTING_IP:
FONTSUB!ReadTableIntoStructure+22f
00007ffa`1eba485b 6689440a10 mov word ptr [rdx+rcx+10h],ax
EXCEPTION_RECORD: (.exr -1)
ExceptionAddress: 00007ffa1eba485b (FONTSUB!ReadTableIntoStructure+0x000000000000022f)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 0000000000000001
Parameter[1]: 000001e16eabf010
Attempt to write to address 000001e16eabf010
FAULTING_THREAD: 0000cde8
PROCESS_NAME: fuzz_ttf.exe
FOLLOWUP_IP:
FONTSUB!ReadTableIntoStructure+22f
00007ffa`1eba485b 6689440a10 mov word ptr [rdx+rcx+10h],ax
WRITE_ADDRESS: 000001e16eabf010
ERROR_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%p referenced memory at 0x%p. The memory could not be %s.
EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%p referenced memory at 0x%p. The memory could not be %s.
EXCEPTION_CODE_STR: c0000005
EXCEPTION_PARAMETER1: 0000000000000001
EXCEPTION_PARAMETER2: 000001e16eabf010
WATSON_BKT_PROCSTAMP: 5e05a3f2
WATSON_BKT_MODULE: FONTSUB.dll
WATSON_BKT_MODSTAMP: 22c86eba
WATSON_BKT_MODOFFSET: 1485b
WATSON_BKT_MODVER: 10.0.18362.535
MODULE_VER_PRODUCT: Microsoft® Windows® Operating System
BUILD_VERSION_STRING: 18362.1.amd64fre.19h1_release.190318-1202
MODLIST_WITH_TSCHKSUM_HASH: e0701885b4164630ff6784e9b6d075fc447148d6
MODLIST_SHA1_HASH: e9d8cb4ef4ad38bb2bd153b069d6b052a809b0c9
NTGLOBALFLAG: 2000000
PROCESS_BAM_CURRENT_THROTTLED: 0
PROCESS_BAM_PREVIOUS_THROTTLED: 0
APPLICATION_VERIFIER_FLAGS: 0
PRODUCT_TYPE: 1
SUITE_MASK: 272
DUMP_TYPE: fe
APPLICATION_VERIFIER_LOADED: 1
ANALYSIS_SESSION_HOST: DESKTOP-CBBVQA8
ANALYSIS_SESSION_TIME: 04-02-2020 19:27:38.0906
ANALYSIS_VERSION: 10.0.17134.1 amd64fre
THREAD_ATTRIBUTES:
OS_LOCALE: ENU
PROBLEM_CLASSES:
ID: [0n309]
Type: [@ACCESS_VIOLATION]
Class: Addendum
Scope: BUCKET_ID
Name: Omit
Data: Omit
PID: [Unspecified]
TID: [0xcde8]
Frame: [0] : FONTSUB!ReadTableIntoStructure
ID: [0n282]
Type: [INVALID_POINTER_WRITE]
Class: Primary
Scope: DEFAULT_BUCKET_ID (Failure Bucket ID prefix)
BUCKET_ID
Name: Add
Data: Omit
PID: [Unspecified]
TID: [0xcde8]
Frame: [0] : FONTSUB!ReadTableIntoStructure
ID: [0n96]
Type: [AVRF]
Class: Addendum
Scope: DEFAULT_BUCKET_ID (Failure Bucket ID prefix)
BUCKET_ID
Name: Add
Data: Omit
PID: [0x3228]
TID: [0xcde8]
Frame: [0] : FONTSUB!ReadTableIntoStructure
BUGCHECK_STR: APPLICATION_FAULT_INVALID_POINTER_WRITE_AVRF
DEFAULT_BUCKET_ID: INVALID_POINTER_WRITE_AVRF
PRIMARY_PROBLEM_CLASS: APPLICATION_FAULT
LAST_CONTROL_TRANSFER: from 00007ffa1eba5e8d to 00007ffa1eba485b
STACK_TEXT:
0000002a`b50fd620 00007ffa`1eba5e8d : 00000000`00000003 0000001c`00280027 00000038`004e004e 00000000`00000000 : FONTSUB!ReadTableIntoStructure+0x22f
0000002a`b50fd6d0 00007ffa`1eb9b6ed : 000001e1`6ea70f10 0000002a`b50fd9f0 00000000`00000000 00000000`0000000f : FONTSUB!MergeEblcEbdtTables+0xb79
0000002a`b50fd8f0 00007ffa`1eb9c13c : 00000000`00000000 0000002a`b50fdb81 00000000`ffffffff 00000000`0000ffff : FONTSUB!MergeFonts+0x699
0000002a`b50fdaa0 00007ffa`1eb91583 : 00000000`00000c7c 0000002a`b50fdcc8 0000002a`b50fdc18 0000002a`b50fdc20 : FONTSUB!MergeDeltaTTF+0x3dc
0000002a`b50fdbd0 00007ff6`feef1e4e : 000001e1`6cbc89a0 00000000`00003640 00000000`00000000 00000000`00000000 : FONTSUB!MergeFontPackage+0x133
0000002a`b50fdc60 00007ff6`feef21ba : 00000000`00000000 00000000`00000000 00000000`00000000 000001e1`6ca71fcb : fuzz_ttf+0x1e4e
0000002a`b50ffae0 00007ff6`feef332d : 00007ffa`31a0b590 00000000`00000000 00000000`00000000 00000000`00000000 : fuzz_ttf+0x21ba
0000002a`b50ffb40 00007ffa`31be7bd4 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : fuzz_ttf+0x332d
0000002a`b50ffb80 00007ffa`33b2ced1 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : KERNEL32!BaseThreadInitThunk+0x14
0000002a`b50ffbb0 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x21
STACK_COMMAND: ~0s ; .cxr ; kb
THREAD_SHA1_HASH_MOD_FUNC: 9ce9cd8861479d96159761a9691ba4c8c894d465
THREAD_SHA1_HASH_MOD_FUNC_OFFSET: 9d3f8671fbf17c2d1c0c9a4058647f93ece75fc6
THREAD_SHA1_HASH_MOD: c36dc10ccf4919ee237948f385c765a7701b1bdd
FAULT_INSTR_CODE: a448966
SYMBOL_STACK_INDEX: 0
SYMBOL_NAME: FONTSUB!ReadTableIntoStructure+22f
FOLLOWUP_NAME: MachineOwner
MODULE_NAME: FONTSUB
IMAGE_NAME: FONTSUB.dll
DEBUG_FLR_IMAGE_TIMESTAMP: 22c86eba
FAILURE_BUCKET_ID: INVALID_POINTER_WRITE_AVRF_c0000005_FONTSUB.dll!ReadTableIntoStructure
BUCKET_ID: APPLICATION_FAULT_INVALID_POINTER_WRITE_AVRF_FONTSUB!ReadTableIntoStructure+22f
FAILURE_EXCEPTION_CODE: c0000005
FAILURE_IMAGE_NAME: FONTSUB.dll
BUCKET_ID_IMAGE_STR: FONTSUB.dll
FAILURE_MODULE_NAME: FONTSUB
BUCKET_ID_MODULE_STR: FONTSUB
FAILURE_FUNCTION_NAME: ReadTableIntoStructure
BUCKET_ID_FUNCTION_STR: ReadTableIntoStructure
BUCKET_ID_OFFSET: 22f
BUCKET_ID_MODTIMEDATESTAMP: 22c86eba
BUCKET_ID_MODCHECKSUM: 24c8a
BUCKET_ID_MODVER_STR: 10.0.18362.535
BUCKET_ID_PREFIX_STR: APPLICATION_FAULT_INVALID_POINTER_WRITE_AVRF_
FAILURE_PROBLEM_CLASS: APPLICATION_FAULT
FAILURE_SYMBOL_NAME: FONTSUB.dll!ReadTableIntoStructure
TARGET_TIME: 2020-04-02T12:27:53.000Z
OSBUILD: 18363
OSSERVICEPACK: 329
SERVICEPACK_NUMBER: 0
OS_REVISION: 0
OSPLATFORM_TYPE: x64
OSNAME: Windows 10
OSEDITION: Windows 10 WinNt SingleUserTS
USER_LCID: 0
OSBUILD_TIMESTAMP: unknown_date
BUILDDATESTAMP_STR: 190318-1202
BUILDLAB_STR: 19h1_release
BUILDOSVER_STR: 10.0.18362.1.amd64fre.19h1_release.190318-1202
ANALYSIS_SESSION_ELAPSED_TIME: 3a49
ANALYSIS_SOURCE: UM
FAILURE_ID_HASH_STRING: um:invalid_pointer_write_avrf_c0000005_fontsub.dll!readtableintostructure
FAILURE_ID_HASH: {edfa825c-ba3b-c2d6-424f-ccecd5a7ca4c}
Followup: MachineOwner
0:000> lmv a rip
Browse full module list
start end module name
00007ffa`1f0d0000 00007ffa`1f0f2000 FONTSUB (pdb symbols) C:\ProgramData\dbg\sym\fontsub.pdb\2A2820FCD9D9D44522A8601FBA7839B71\fontsub.pdb
Loaded symbol image file: C:\WINDOWS\SYSTEM32\FONTSUB.dll
Image path: C:\WINDOWS\SYSTEM32\FONTSUB.dll
Image name: FONTSUB.dll
Browse all global symbols functions data
Image was built with /Brepro flag.
Timestamp: 22C86EBA (This is a reproducible build file hash, not a timestamp)
CheckSum: 00024C8A
ImageSize: 00022000
File version: 10.0.18362.535
Product version: 10.0.18362.535
File flags: 0 (Mask 3F)
File OS: 40004 NT Win32
File type: 2.0 Dll
File date: 00000000.00000000
Translations: 0409.04b0
Information from resource tables:
CompanyName: Microsoft Corporation
ProductName: Microsoft® Windows® Operating System
InternalName: fontsub
OriginalFilename: fontsub
ProductVersion: 10.0.18362.535
FileVersion: 10.0.18362.535 (WinBuild.160101.0800)
FileDescription: Font Subsetting DLL
LegalCopyright: © Microsoft Corporation. All rights reserved.An attacker who successfully exploited this vulnerability could take control of the affected system. An attacker could then install programs; view, change, or delete data; or create new accounts with full user rights. Users whose accounts are configured to have fewer user rights on the system could be less impacted than users who operate with administrative user rights.
There are multiple ways an attacker could exploit this vulnerability:
- In a web-based attack scenario, an attacker could host a specially crafted website that is designed to exploit this vulnerability and then convince or lure users to browse the website. Normally, an attacker would have no way to force users to browse the attacker-controlled content. Instead, an attacker would have to convince users to take action, typically by getting them to click a link in an email or instant message that takes users to the attacker's website, or by opening an attachment sent through email.
- In a file-sharing attack scenario, an attacker could provide a specially crafted document file designed to exploit the vulnerability and then convince users to open the document file.
![]() |
Figure 5: Attack vectors can happen in real life |
Timeline
2020-Jan-03 – Reported vendor
2020-Jan-09 – The vendor confirmed it was a bug
2020-Jan-13 – Updated detailed analysis for vendor
2020-Apr-14 - Public Release
Does it Possible RCE? Have you did it?
ReplyDeletevery good , thanks
ReplyDelete