New issue
Advanced search Search tips
Starred by 3 users

Issue metadata

Status: Fixed
Closed: Apr 2015

Sign in to add a comment

Issue 177: Windows Kernel ATMFD.DLL read/write-what-where in LOAD and STORE operators

Reported by, Nov 19 2014 Project Member

Issue description

The "Type 2 Charstring Format" specification from 5 May 1998 specified two storage operators which were later removed from the document: `store` and `load`. These operators were responsible for copying data between the transient array (also known as the BuildCharArray) and the so-called "Registry object" (also deprecated by now, but still supported by Adobe implementations).

As the specs state:

    The Registry provides more permanent storage for a number of items that have predefined meanings. The items stored in the Registry do not persist beyond the scope of rendering a font. Registry items are selected with an index, thus:

    0 Weight Vector
    1 Normalized Design Vector
    2 User Design Vector

    The result of selecting a Registry item with an index outside this list is undefined.

However, the parameter sanity checking implemented for both operators - although present - is flawed. There is an off-by-one error in the verification of the Registry index, allowing for index 3 to be used:

.text:0003CA35                 cmp     eax, 3
.text:0003CA38                 ja      loc_3BEC4       ; jumptable 0003BF69 case 2

Internally, the Registry is implemented as a three-item array of structures similar to the following:

  int32 size;
  void *data;
} Registry[3];

Accessing the 4th element of the array results in a reference to uninitialized memory from the Session Paged Pool. If the value of the "size" field happens to be positive, the "data" pointer is used as the "source" parameter of a "memcpy" call in case of the `load` instruction, and as "dest" in case of `store`.

With the ability to perform kernel pool massaging, it is possible to transform the bug into a read/write-what-where primitive by controlling the contents of the uninitialized memory used as source/destination addresses, which then easily leads to elevation of privileges and full system security compromise.

The issue is reproducible with Type1 and OTF fonts -- attached are reproducers for both formats, which can be opened in the standard Windows Font Viewer utility to trigger a bugcheck. Please note that in order for the system to crash, the "size" field must be positive and the "data" pointer must point into kernel-mode memory (ATMFD.DLL silently catches exceptions caused by invalid user-mode references), so it might require a few attempts. On the other hand, a local exploit is believed to be able to take advantage of the vulnerability with near 100% reliability.

If the kernel pool is sprayed such that size=0x55555555 and data=0xaaaaaaaa, the following bugcheck is triggered on a fully patched Windows 8.1 32-bit:

Invalid system memory was referenced.  This cannot be protected by try-except,
it must be protected by a Probe.  Typically the address is just plain bad or it
is pointing at freed memory.
Arg1: aaaaaaaa, memory referenced.
Arg2: 00000001, value 0 = read operation, 1 = write operation.
Arg3: 994f8c00, If non-zero, the instruction address which referenced the bad memory
Arg4: 00000002, (reserved)

A full crash log can be found in "crash.txt".

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.
19.6 KB Download
668 bytes Download
5.8 KB View Download
86.4 KB Download

Comment 1 by, Dec 4 2014

Project Member
Labels: -Product-Windows Product-Kernel

Comment 2 by, Dec 11 2014

Project Member
Labels: Reported-2014-Dec-10 MSRC-21199

Comment 3 by, Mar 24 2015

Project Member
Labels: CVE-2015-0090

Comment 4 by, Apr 1 2015

Status: Fixed

Comment 5 by, Apr 20 2015

Project Member
Labels: Fixed-2015-Mar-10

Comment 6 by, Jun 12 2015

Project Member
Labels: -Restrict-View-Commit

Sign in to add a comment