Threat Research

Analysis of CVE-2016-0059 - Microsoft IE Information Disclosure Vulnerability Discovered by Fortinet

By Kai Lu | February 19, 2016


This month Microsoft patched two vulnerabilities which were discovered and reported by me, one is an information disclosure vulnerability in Internet Explorer (IE) (CVE-2016-0059 in MS16-009), the other is a memory corruption vulnerability in Microsoft Office (CVE-2016-0055 in MS16-015). In this blog, we will provide in-depth analysis of CVE-2016-0059. The vulnerability exists because Microsoft Hyperlink Object Library improperly discloses the contents of its memory. An attacker who successfully exploited this vulnerability could obtain information to further compromise the user’s system. To exploit the vulnerability, an attacker must convince a user to either click a link in an email message or open an Office file, and then click a link in the file. 

In my original vulnerability report to Microsoft, I marked the vulnerability as Microsoft Office Excel heap overflow vulnerability. Because the vulnerability actually lies in the library hlink.dll (Microsoft Hyperlink Object Library) which is a component in Internet Explorer, Microsoft classifies it as Internet Explorer information disclosure vulnerability. In this blog, I still use Microsoft Office to demonstrate and analyze this vulnerability.   

What Products Are Affected?

All major IE versions are affected by this vulnerability.

IE 9

IE 10

IE11 (including the version for Windows 10)

Proof of Concept

To reproduce the vulnerability, we can open the PoC FG-VD-15-073_PoC.xls with Microsoft Office Excel 2007. Then we can see Excel.exe crashes and the crash information shows below:

(3344.1804): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=1a06d0d0 ebx=00000002 ecx=18b22fea edx=00000001 esi=18b23000 edi=18b22fe8
eip=6cd40b40 esp=00b739b4 ebp=00b739c4 iopl=0         nv up ei ng nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010282
6cd40b40 668b06          mov     ax,word ptr [esi]        ds:002b:18b23000=????

0:000> u
6cd40b40 668b06          mov     ax,word ptr [esi]
6cd40b43 03f3            add     esi,ebx
6cd40b45 6685c0          test    ax,ax
6cd40b48 75f6            jne     hlink!WzDupWzToWz+0x16 (6cd40b40)
6cd40b4a 2bf1            sub     esi,ecx
6cd40b4c d1fe            sar     esi,1
6cd40b4e 8d5e01          lea     ebx,[esi+1]
6cd40b51 85d2            test    edx,edx

0:000> !heap -p -a esi
    address 18b23000 found in
    _DPH_HEAP_ROOT @ 5601000
    in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize -         VirtAddr         VirtSize)
                                1a173a5c:         18b22fe8               16 -         18b22000             2000
    5e6d9abc verifier!AVrfDebugPageHeapAllocate+0x0000023c
    77c97ab1 ntdll!RtlDebugAllocateHeap+0x0000003c
    77c4ba4e ntdll!RtlpAllocateHeap+0x0004cfde
    77bfdc26 ntdll!RtlpAllocateHeapInternal+0x00000146
    77bfdab8 ntdll!RtlAllocateHeap+0x00000028
    770f32e6 combase!CRetailMalloc_Alloc+0x00000016 [d:\th\com\combase\class\memapi.cxx @ 641]
    6cd337fd hlink!CMalloc::Alloc+0x0000002d
    6cd40c32 hlink!operator new+0x00000023
    6cd3d50e hlink!HrReadLengthWzStm+0x00000034
    6cd39b2c hlink!HLNK_PersistStm::Load+0x0000010c
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files (x86)\Common Files\Microsoft Shared\office12\mso.dll - 
    3280dc07 mso!Ordinal2575+0x00000320
    3280dac1 mso!Ordinal2575+0x000001da
    3280da7a mso!Ordinal2575+0x00000193
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files (x86)\Microsoft Office\Office12\oart.dll - 
    3a99fb87 oart!Ordinal5476+0x00000709

0:000> dp 18b22fe8               
18b22fe8  00720041 00610072 00440079 006d0075
18b22ff8  00320070 d0d0d000 ???????? ????????
18b23008  ???????? ???????? ???????? ????????
18b23018  ???????? ???????? ???????? ????????
18b23028  ???????? ???????? ???????? ????????
18b23038  ???????? ???????? ???????? ????????
18b23048  ???????? ???????? ???????? ????????
18b23058  ???????? ???????? ???????? ????????

0:000> kb
 # ChildEBP RetAddr  Args to Child              
00 00b739c4 6cd3590d 00000000 00b73a88 00b73a1c hlink!WzDupWzToWz+0x16
01 00b739e0 6cd331cf 1a068f28 00000000 00b73a1c hlink!CExtensionService::Release+0x105d
02 00b73a28 3280da8e 1a068f28 00000000 00b73a88 hlink!HLNK::GetStringReference+0x5f
WARNING: Stack unwind information not available. Following frames may be wrong.
03 00b73a58 3a99fb87 08f74fd0 00000000 00b73a88 mso!Ordinal2575+0x1a7
04 00b73d70 77bf6d70 77cc74a8 19cd6ff0 00000000 oart!Ordinal5476+0x709
05 00b73d98 77c91c3a 000df3e0 00000060 14b90fa0 ntdll!RtlpPopEntrySListLockedAlt+0x20
06 00b73de8 32c8de4f 32195748 2fc48b8c 00000000 ntdll!RtlpStdLockRelease+0x14
07 00b73dec 32195748 2fc48b8c 00000000 00000000 mso!Ordinal1743+0x2f43
08 00b73df0 2fc48b8c 00000000 00000000 00000000 mso!MsoPvAllocCore+0x36
09 00b73df4 00000000 00000000 00000000 00b73c90 Excel!Ordinal40+0x108b8c


The vulnerability arises from an attempt to read a string from an invalid memory location due to missing NULL terminator at the end of the input string. This happens during string duplication attempt in hlink!WzDupWzToWz() function. Successful exploitation of this vulnerability could lead to information disclosure.

Let’s look into the specially-crafted XLS file first. The minimized PoC file has two differences at offset 0x66C and 0x140DC respectively. The comparison between the normal XLS file and the minimized PoC file shows below.  

Figure 1. The Normal XLS File vs The Minimized PoC File (Offset 0x66C)

Figure 2. The Normal XLS File vs The Minimized PoC File (Offset 0x140DC)

Then let’s use the tool Offvis to parse the minimized PoC file as follows.

Figure 3.   Parsing of The Minimized PoC File (Offset 0x66c)

Figure 4.   Parsing of the Minimized PoC File (Offset 0x140DC)

From figure 3, we can see the 8 bytes starting at offset 0x66c is the ModifyTime field. It actually doesn’t result in the vulnerability, so ignore it. From figure 4, we can see the byte |D0| at offset 0x140DC is in the complexData field. And the complexData field is a part of the fopt (OfficeArtRGFOPTE) structure. The OfficeArtRGFOPTE structure is defined by Microsoft as follows.

Figure 5.    OfficeArtRGFOPTE Structure

From the above definition, we cannot find the complexData field contains specific structures.

Then let’s set a breakpoint as follows in WinDbg.

bu hlink!HLNK::GetMonikerReference " .printf \"GetMonikerReference:\\n\"; db poi(poi(esp+4)+0x4c);"

After this breakpoint is hit several times, you can get the following debug information.

From the above debug information, we can see the heap buffer starting at 0x16c52fe8 contains part of the complexData field. It's a wide string without NULL terminator.

The following is a snippet of function hlink!HLNK::GetMonikerReference which calls the function hlink!WzDupWzToWz() to handle the wide string.

The following is the analysis of the function hlink!WzDupWzToWz().

Figure 6.  The Analysis of Function hlink!WzDupWzToWz() in IDA Pro

In conclusion, the issue arises from an attempt to read a string from an invalid memory location due to missing NULL terminator at the end of the input string. This happens during string duplication attempt in hlink!WzDupWzToWz() function.

The library hlink.dll is used to handle Hyperlink objects. We might manually construct the PoC file via creating a hyperlink as follows.

Figure 7. Create a Hyperlink in XLS File.

Save it as test.xls and use the tool Offvis to parse it as follows.

Figure 8.  Parsing of The New Excel File

From the above, we can clearly see that the created hyperlink is stored in a HLink structure. The HLink structure is defined by Microsoft as follows.

The Hyperlink structure is defined by Microsoft as follows.

Let’s compare the data of HLink structure with the complexData field. The following is the HLink structure in test.xls.

Figure 9.  HLink Structure in test.xls

Then we can speculate the inner structure of the complexData field as follows.

Figure 10.  Inner Structure of The complexData Field

Let's modify the value of hyperlinkBitFields to |08 00 00 00| and modify the NULL terminator to |00 D0| in string of HyperlinkString as follows.

Figure 11. Modified HLink Structure in test.xls

Save it and test the modified test.xls in Windows 7 and Windows 10. It can trigger this vulnerability. The following is the test screenshots in Windows 10.

Figure 12. Open The Manually-Crafted PoC File in Windows 10

When open the modified test.xls, hlink.dll isn't loaded. Then click the hyperlink of the "test" string, hlink.dll is loaded and it triggers this vulnerability.

Figure 13. Crash Triggered by The Manually-Crafted PoC File in Windows 10


All users of Microsoft IE are encouraged to upgrade to the latest version of this software. Additionally, organizations that have deployed Fortinet IPS solutions are already protected from this vulnerability with the signature MS.IE.hlink.WzDupWzToWz.Memory.Corruption.