In the Windows kernel ATMFD.DLL (Adobe Type Manager Font Driver) implementation of the `STOREWV` instruction (othersubr 19) used by Multiple Master Fonts [1], values are copied from a so-called "WeightVector" (an internal, MM-specific array) into the transient array (also known as "BuildCharArray"). The starting index is obtained from the operand stack, as shown below in Hex-Rays decompiled pseudo-code:
---
--op_sp;
idx = *(op_sp + 1);
[...]
master_designs = font->master_designs;
if ( master_designs + idx > font->lenBuildCharArray )
{
DbgPrint(
&dword_57B00,
"%s:%d: %s (%s)\n",
"windows\\core\\ntgdi\\fondrv\\otfd\\bc\\t1interp.c",
5890,
"STOREWV beyond buildCharArray",
"false");
goto label_error;
}
---
or, in assembly:
---
.text:0003C33B movsx esi, word ptr [edi+2]
[...]
.text:0003C383 mov ecx, [edx+284h]
.text:0003C389 lea eax, [ecx+esi]
.text:0003C38C cmp eax, [edx+328h]
.text:0003C392 ja loc_3FA35
---
The "master_designs" variable is the size of the "WeightVector" array and can be anything from 2 to 16, while "idx" is a fully controlled 16-bit signed integer. If "idx" is a negative number, the check can be effectively bypassed, thus leading to a buffer underflow of the "BuildCharArray" pool-based allocation, by a maximum of 64 bytes (16 dwords):
---
if ( master_designs )
{
buildchar_offset = idx;
weight_vector = font->weight_vector;
do
{
++it;
value = *weight_vector;
weight_vector += 4;
font->BuildCharArray[buildchar_offset] = value;
++buildchar_offset;
}
while ( it < font->master_designs );
op_sp = tmp_op_sp;
it = 0;
}
---
The vulnerability can be reproduced with Multiple Master Type1 fonts (i.e. fonts consisting of three files: .PFM, .PFM and .MMM), but also with regular Type1 fonts, provided that a PostScript "/WeightVector" array is present in the .PFB file header (preferably of length 16), and the following instruction sequence is used for one of the rendered glyphs:
---
-16 1 19 callother
---
This will overwrite 64 bytes in front of the transient array, corrupting Windows pool headers and leading to a bugcheck (full log can be found in "crash.txt"):
---
KERNEL_SECURITY_CHECK_FAILURE (139)
A kernel component has corrupted a critical data structure. The corruption
could potentially allow a malicious user to gain control of this machine.
Arguments:
Arg1: 00000003, A LIST_ENTRY has been corrupted (i.e. double remove).
Arg2: 81be4b54, Address of the trap frame for the exception that caused the bugcheck
Arg3: 81be4a80, Address of the exception record for the exception that caused the bugcheck
Arg4: 00000000, Reserved
---
All versions of Windows up to 8.1 (regardless of bitness) are affected. Attached is a Proof of Concept Type1 font ("poc.pfm" + "poc.pfb") and its source code ("poc.pfa"). In order to trigger a system crash, it is sufficient to open the POC font in the Windows Font Viewer program.
This bug is subject to a 90 day disclosure deadline. If 90 days elapse without a broadly available patch, then the bug report will automatically become visible to the public.
References:
[1] http://en.wikipedia.org/wiki/Multiple_master_fonts