Talos Vulnerability Report

TALOS-2016-0149

Hancom Hangul HCell OfficeArt Record pConnectionSites and pVertices Code Execution Vulnerability

August 4, 2016
CVE Number

CVE-2016-4294

Description

This vulnerability was discovered within the Hangul Hcell application which is part of the Hangul Office Suite. Hangul Office is published by Hancom, Inc. and is considered one of the more popular Office suites used within South Korea. When opening a Hangul Hcell Document (.cell) and processing a property record within the Workbook stream, the application will attempt to allocate space for an element using a length from the file. When copying user-supplied data to this buffer, however, the application will use a different size which leads to a heap-based buffer overflow. This vulnerabiltiy can lead to code-execution under the context of the application.

Tested Versions

Hancom Office 2014 VP Trial HCell.exe Product version: 9.1.0.2176 HCellApp.dll Product version: 9.1.0.2176 HCellBook.dll Product version: 9.1.0.2176

Product Urls

http://www.hancom.com http://www.hancom.com/en/product/product2014vp_01.jsp

CVSSv3 Score

8.6 – CVSS:3.0/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H

Details

Hangul Hcell uses the Structured Storage COM API to load and store the Spreadsheet generated by a user. Although there are various streams that can be specified wthin a document, the Hcell application stores the contents of a workbook within the “Workbook” stream as an array of Type-Length-Value structures. Each of these structures describe the worksheets and the cells that compose the document.

When parsing the Workbook stream, the application will perform 3 passes over each record. The third pass is assumed by the author to parse record types that depend on cell data that is parsed during the second pass. During the third pass, the application will read the record type of 0x00ec. This record type is the same as OfficeArt’s (Escher) record and utilizes the exact same format. Once this type is identified, the application will then enter a function that deals with OfficeArt records.

HCellApp!CNexPTViewDefine::SetColLast+0x20be7:
69738067 8b13            mov     edx,dword ptr [ebx]
69738069 8b92e4010000    mov     edx,dword ptr [edx+1E4h]
6973806f 8d442434        lea     eax,[esp+34h]
69738073 50              push    eax
69738074 57              push    edi        ; worksheet
69738075 8d8c2480000000  lea     ecx,[esp+80h]
6973807c 51              push    ecx
6973807d 8bcb            mov     ecx,ebx
6973807f ffd2            call    edx        ; XXX: office art records
69738081 8bf0            mov     esi,eax

Inside this function is a loop that will take the recordheader and use it to determine which case should be used to handle which record type. If the recordtype is 0xf004, which defines the record OfficeArtSpContainer, then the application will execute the following code. This code is responsible for reading information from the file that is used to define a Shape.

HCellApp!CHclUndoCommand::AddRef+0x56809:
6979d829 8b442444        mov     eax,dword ptr [esp+44h]
6979d82d 50              push    eax        ; worksheet
6979d82e 8d4c242c        lea     ecx,[esp+2Ch]
6979d832 51              push    ecx        ; recordheader
6979d833 8d54241c        lea     edx,[esp+1Ch]
6979d837 52              push    edx
6979d838 55              push    ebp
6979d839 e862fbffff      call    HCellApp!CHclUndoCommand::AddRef+0x56380 (6979d3a0)    ; XXX
6979d83e 8bf0            mov     esi,eax

Inside this function, the application will read the contents of the container into a buffer. After reading the file data into a buffer, the function call at 6979d455 is responsible for initializing an object containing a number of associative arrays that are used to reference file data related to the shape. Each of these arrays are a map-like-object that store the offsets to the various record types that compose a Microsoft Office shape container. When creating the associative array for each property, if the property has it’s fComplex bit set, then the associative-array’s value is mapped to the out-of-band data associated with the property. This allows the application to quickly find the IMsoArray data that is used by the pVertices and pSegmentInfo properties when rendering the shape. After populating this object with it’s lookup tables, the object will then get passed to the function call at 6979d477.

HCellApp!CHclUndoCommand::AddRef+0x563c1:
6979d3e1 8bbc2480000000  mov     edi,dword ptr [esp+80h]
6979d3e8 8b4f14          mov     ecx,dword ptr [edi+14h]
6979d3eb 8b11            mov     edx,dword ptr [ecx]
6979d3ed 8b5204          mov     edx,dword ptr [edx+4]
6979d3f0 8bf0            mov     esi,eax    ; heap buffer
6979d3f2 8b4504          mov     eax,dword ptr [ebp+4]
6979d3f5 83c404          add     esp,4
6979d3f8 50              push    eax        ; size
6979d3f9 56              push    esi        ; buffer to read file data into
6979d3fa 89742428        mov     dword ptr [esp+28h],esi
6979d3fe ffd2            call    edx
...
HCellApp!CHclUndoCommand::AddRef+0x5642c:
6979d44c 8b4504          mov     eax,dword ptr [ebp+4]
6979d44f 50              push    eax    ; recordLength
6979d450 56              push    esi    ; recordData
6979d451 8d4c2434        lea     ecx,[esp+34h]      ; container of sub-records
6979d455 e826d43900      call    HCellApp!NXDeleteArcObj+0xe390 (69b3a880)  ; initialize a structure for sub-records
...
HCellApp!CHclUndoCommand::AddRef+0x5643a:
6979d45a 8b942488000000  mov     edx,dword ptr [esp+88h]
6979d461 8d4c242c        lea     ecx,[esp+2Ch]
6979d465 51              push    ecx                ; mapcontainer
6979d466 52              push    edx                ; worksheet
6979d467 8bf7            mov     esi,edi
6979d469 e812ef0600      call    HCellApp!CHclUndoManager::AddRef+0x43410 (6980c380)  ; takes one argument. allocates a 0x64 and 0x2c byte object
6979d46e 50              push    eax
6979d46f 8d84248c000000  lea     eax,[esp+8Ch]  ; recordHeader
6979d476 50              push    eax
6979d477 e894453a00      call    HCellApp!NXDeleteArcObj+0x15520 (69b41a10) ; XXX: takes 3 arguments
6979d47c 83c40c          add     esp,0Ch

Inside the function at 69b41a10, the application will process the different sub-records that are within the OfficeArtSpContainer. After processing record types such as 0xf122 or 0xf00b which contains information such as the coordinate system for the shape, the application will use the flags for the 0xf00a record type. This record type is named OfficeArtFSP and contains a list of flags that describe conditions of the shape. Eventually, the application will execute the code at 69b42009. This function call is specifically responsible for acting on the list of properties that were read from the 0xf00b record. It is within the 0xf00b record that information such as the vertices and the segment-info of our shape are processed.

HCellApp!NXDeleteArcObj+0x15907:
69b41df7 8b8c2480000000  mov     ecx,dword ptr [esp+80h]        ; shape structure
69b41dfe 8b74241c        mov     esi,dword ptr [esp+1Ch]        ; shapeCoordinateSystem
69b41e02 8b9c2484000000  mov     ebx,dword ptr [esp+84h]        ; map/set container
69b41e09 51              push    ecx
69b41e0a 8d442440        lea     eax,[esp+40h]                  ; flags from 0xf00a record
69b41e0e 8bce            mov     ecx,esi
69b41e10 896c2440        mov     dword ptr [esp+40h],ebp
69b41e14 e8b7010000      call    HCellApp!NXDeleteArcObj+0x15ae0 (69b41fd0)     ; \
69b41e19 83c404          add     esp,4
\
HCellApp!NXDeleteArcObj+0x15b14:
69b42004 57              push    edi        ; recordData(f00a)
69b42005 56              push    esi        ; shapeCoordinateSystem
69b42006 55              push    ebp
69b42007 8bc3            mov     eax,ebx    ; map-container
69b42009 e862920000      call    HCellApp!NXDeleteArcObj+0x1ed80 (69b4b270)     ; \
69b4200e 8b431c          mov     eax,dword ptr [ebx+1Ch]
\
HCellApp!NXDeleteArcObj+0x1ed83:
69b4b273 8b4810          mov     ecx,dword ptr [eax+10h]    ; map (f00b)
69b4b276 8b5014          mov     edx,dword ptr [eax+14h]
69b4b279 890c24          mov     dword ptr [esp],ecx
69b4b27c 8b4818          mov     ecx,dword ptr [eax+18h]    ; map (f122)
69b4b27f 89542404        mov     dword ptr [esp+4],edx
69b4b283 33d2            xor     edx,edx
69b4b285 894c2408        mov     dword ptr [esp+8],ecx
...
69b4b2b4 8b4c241c        mov     ecx,dword ptr [esp+1Ch]    ; shapeCoordinateSystem
69b4b2b8 50              push    eax
69b4b2b9 8b44241c        mov     eax,dword ptr [esp+1Ch]    ; shape object
69b4b2bd 8d542404        lea     edx,[esp+4]                ; map (f00b)
69b4b2c1 52              push    edx
69b4b2c2 8b542428        mov     edx,dword ptr [esp+28h]
69b4b2c6 50              push    eax
69b4b2c7 e804000000      call    HCellApp!NXDeleteArcObj+0x1ede0 (69b4b2d0) ; XXX: process the list of shape properties

Inside this function, the application will process our vulnerable OfficeArtFOPTE properties specifically. The function call at 0x69b4b316 will return a pointer to the file-data given a property identifier in the %esi register. With the provided proof-of-concept, which does not include a philShape property, the application will execute until it finally hits the function call at 69b4b4ac. This function call checks to see if the shape is to be drawn in Black and White mode (bWMode).

HCellApp!NXDeleteArcObj+0x1ee0c:
69b4b2fc 8b4510          mov     eax,dword ptr [ebp+10h]
69b4b2ff 8b7d0c          mov     edi,dword ptr [ebp+0Ch]    ; map (f00b)
69b4b302 8b5d08          mov     ebx,dword ptr [ebp+8]
69b4b305 be82030000      mov     esi,382h       ; pihlShape property
69b4b30a 89442418        mov     dword ptr [esp+18h],eax
69b4b30e 894c2414        mov     dword ptr [esp+14h],ecx    ; shapeCoordinateSystem
69b4b312 89542410        mov     dword ptr [esp+10h],edx
69b4b316 e805aeffff      call    HCellApp!NXDeleteArcObj+0x19c30 (69b46120) ; return a fileRecordProperty
69b4b31b 85c0            test    eax,eax
69b4b31d 742a            je      HCellApp!NXDeleteArcObj+0x1ee59 (69b4b349) ; XXX
69b4b31f 83780200        cmp     dword ptr [eax+2],0                        ; op
69b4b323 7424            je      HCellApp!NXDeleteArcObj+0x1ee59 (69b4b349)
69b4b325 b900800000      mov     ecx,8000h                                  ; fComplex bit
69b4b32a 668508          test    word ptr [eax],cx                          ; opid
69b4b32d 741a            je      HCellApp!NXDeleteArcObj+0x1ee59 (69b4b349)
...
HCellApp!NXDeleteArcObj+0x1ee7d:
69b4b36d c744245800000000 mov     dword ptr [esp+58h],0
69b4b375 8b442430        mov     eax,dword ptr [esp+30h]
69b4b379 85c0            test    eax,eax
69b4b37b 7424            je      HCellApp!NXDeleteArcObj+0x1eeb1 (69b4b3a1)
...
HCellApp!NXDeleteArcObj+0x1efb8:
69b4b4a8 57              push    edi        ; map (f00b)
69b4b4a9 53              push    ebx
69b4b4aa 8bce            mov     ecx,esi
69b4b4ac e88f000000      call    HCellApp!NXDeleteArcObj+0x1f050 (69b4b540) ; XXX
69b4b4b1 83c408          add     esp,8

Inside the function at 69b4b540, the application will map the value of the bWMode property to an enumeration described as MSOBWMODE. After this is determined, the application will finally grab the value of the pVertices property and then make a call to the function at 69b4fb45 with the file data as it’s parameter. Once in this function, the application will continue on to the call at 69b55f60 which will actually use the property’s values in a vulnerable manner.

HCellApp!NXDeleteArcObj+0x1f0b8:
69b4b5a8 8bc3            mov     eax,ebx    ; shapeCoordinateSystem
69b4b5aa 8bcf            mov     ecx,edi    ; map (f00b)
69b4b5ac e85f450000      call    HCellApp!NXDeleteArcObj+0x23620 (69b4fb10) ; \
\
HCellApp!NXDeleteArcObj+0x23644:
69b4fb34 be45010000      mov     esi,145h       ; pVertices
69b4fb39 e83266ffff      call    HCellApp!NXDeleteArcObj+0x19c80 (69b46170) ; return the FOPTE header
69b4fb3e 85c0            test    eax,eax
69b4fb40 740b            je      HCellApp!NXDeleteArcObj+0x2365d (69b4fb4d)
69b4fb42 53              push    ebx
69b4fb43 8bcf            mov     ecx,edi
69b4fb45 e866180000      call    HCellApp!NXDeleteArcObj+0x24ec0 (69b513b0) ; \
69b4fb4a 83c404          add     esp,4
\
HCellApp!NXDeleteArcObj+0x24eed:
69b513dd 8d442454        lea     eax,[esp+54h]
69b513e1 50              push    eax
69b513e2 e8794b0000      call    HCellApp!NXDeleteArcObj+0x29a70 (69b55f60) ; XXX

Inside the function call at 69b55f60, the application will process the pVertices and pSegmentInfo properties. Earlier, when the application created an associative array for the properties within this container, an the array was made to store the out-of-band data parts of each property. This out-of-band data will be referred to as the complexData field. For these properties, the complexData field is organized in a structure known as IMsoArray. It as at this point in execution, that the application copies an IMsoArray structure out of the complexData field within the file. At address 0x69b56031, the application processes the pVertices’ IMsoArray. A little bit later, at address 69b5607f, the application will call the vulnerable function using the IMsoArray from the pSegmentInfo property. Although both properties are vulnerable, the provided proof-of-concept triggers the vulnerability using the pSegmentInfo property.

HCellApp!NXDeleteArcObj+0x29b36:
69b56026 46              inc     esi
69b56027 b950010000      mov     ecx,150h
69b5602c 663bf1          cmp     si,cx
69b5602f 76bf            jbe     HCellApp!NXDeleteArcObj+0x29b00 (69b55ff0)
69b56031 8d71f5          lea     esi,[ecx-0Bh]      ; 0x150-0xb == 0x145 == pVertices
69b56034 e83701ffff      call    HCellApp!NXDeleteArcObj+0x19c80 (69b46170) ; return property record
69b56039 85c0            test    eax,eax
69b5603b 7418            je      HCellApp!NXDeleteArcObj+0x29b65 (69b56055)
69b5603d 8b10            mov     edx,dword ptr [eax]    ; IMsoArray.nElems
69b5603f 8d7520          lea     esi,[ebp+20h]
69b56042 8916            mov     dword ptr [esi],edx
69b56044 668b4804        mov     cx,word ptr [eax+4]    ; IMsoArray.cbElem
69b56048 83c006          add     eax,6                  ; IMsoArray.data
69b5604b 50              push    eax                    ; XXX: pointer to file data
69b5604c 66894e04        mov     word ptr [esi+4],cx
69b56050 e86b010000      call    HCellApp!NXDeleteArcObj+0x29cd0 (69b561c0) ; XXX: call vulnerable function
...
HCellApp!NXDeleteArcObj+0x29b8f:
69b5607f be51010000      mov     esi,151h           ; pSegmentInfo
69b56084 e8e700ffff      call    HCellApp!NXDeleteArcObj+0x19c80 (69b46170)
69b56089 85c0            test    eax,eax
69b5608b 7418            je      HCellApp!NXDeleteArcObj+0x29bb5 (69b560a5)
69b5608d 8b10            mov     edx,dword ptr [eax]        ; IMsoArray.nElems
69b5608f 8d7538          lea     esi,[ebp+38h]
69b56092 8916            mov     dword ptr [esi],edx
69b56094 668b4804        mov     cx,word ptr [eax+4]        ; IMsoArray.cbElem
69b56098 83c006          add     eax,6                      ; IMsoArray.data
69b5609b 50              push    eax
69b5609c 66894e04        mov     word ptr [esi+4],cx
69b560a0 e81b010000      call    HCellApp!NXDeleteArcObj+0x29cd0 (69b561c0) ; XXX: calls vulnerable function

Within the function 69b561c0, the application will then perform an allocation by multiplying the constant 8 by the value of the IMsoArray.nElems field. Later, at address 69b56231, the application copies data into this buffer using the value of the IMsoArray.cbElem field for each element. Due to the application using a different size (8) for the cbElem field during allocation than what is used to copy data from the file into the allocated buffer, a heap-based buffer overflow can be made to occur. This can allow for one to corrupt the heap which can lead to code-execution under the context of the application.

HCellApp!NXDeleteArcObj+0x29cd0:
69b561c0 55              push    ebp
69b561c1 8b6c2408        mov     ebp,dword ptr [esp+8]
69b561c5 b8f0ff0000      mov     eax,0FFF0h
69b561ca 57              push    edi
69b561cb 66394604        cmp     word ptr [esi+4],ax    ; IMsoArray.cbElem
69b561cf 7509            jne     HCellApp!NXDeleteArcObj+0x29cea (69b561da)
...
69b561da 0fb706          movzx   eax,word ptr [esi]     ; IMsoArray.nElems
69b561dd 33c9            xor     ecx,ecx
69b561df ba08000000      mov     edx,8          ; XXX: cbElem == 8
69b561e4 f7e2            mul     eax,edx        ; XXX: nElems * 8
69b561e6 0f90c1          seto    cl
69b561e9 f7d9            neg     ecx
69b561eb 0bc8            or      ecx,eax
69b561ed 51              push    ecx            ; nElems * 8
69b561ee e864790200      call    HCellApp!CHclDoc::IsPrinting+0x53c7 (69b7db57) ; heap allocation
...
HCellApp!NXDeleteArcObj+0x29d24:
69b56214 0fb74604        movzx   eax,word ptr [esi+4]   ; XXX: IMsoArray.cbElem
69b56218 53              push    ebx
69b56219 8da42400000000  lea     esp,[esp]
69b56220 d1e8            shr     eax,1                  ; XXX: divide by 2
69b56222 50              push    eax
69b56223 8b4608          mov     eax,dword ptr [esi+8]
69b56226 8d1cfd00000000  lea     ebx,[edi*8]
69b5622d 03c3            add     eax,ebx                ; index into destination by constant size
69b5622f 55              push    ebp
69b56230 50              push    eax                    ; XXX: destination heap buffer
69b56231 e828ff0300      call    HCellApp!CHclDoc::IsPrinting+0x1d9ce (69b9615e)    ; XXX: memcpy

After corrupting the heap buffer, the application will eventually have to return 5 times to get to the address 0x69b4b5bf. It as at this point the application will use a 0x2c byte object to call a virtual method.

HCellApp!NXDeleteArcObj+0x1f0b8:
69b4b5a8 8bc3            mov     eax,ebx    ; shapeCoordinateSystem
69b4b5aa 8bcf            mov     ecx,edi    ; map (f00b)
69b4b5ac e85f450000      call    HCellApp!NXDeleteArcObj+0x23620 (69b4fb10) ; return
...
69b4b5bf 8bf3            mov     esi,ebx    ; 0x2c byte object
69b4b5c1 8bcf            mov     ecx,edi
69b4b5c3 e8c8930000      call    HCellApp!NXDeleteArcObj+0x284a0 (69b54990) ; \
\
HCellApp!NXDeleteArcObj+0x284c3:
69b549b3 8b16            mov     edx,dword ptr [esi]        ; dereference a virtual table
69b549b5 50              push    eax
69b549b6 8b4224          mov     eax,dword ptr [edx+24h]    ; dereference a code pointer
69b549b9 6a08            push    8
69b549bb 8bce            mov     ecx,esi
69b549bd ffd0            call    eax

0:000> lm
692d0000 69fb5000   HCellApp   (export symbols)       HCellApp.dll 00CB6449

Crash Analysis

eax=00000200 ebx=001bcba0 ecx=00000000 edx=00000008 esi=001bcbd8 edi=001bcd20
eip=69b561e4 esp=001bcaf4 ebp=1d126b2e iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
HCellApp!NXDeleteArcObj+0x29cf4:
69b561e4 f7e2            mul     eax,edx
0:000> ? @eax*@edx
Evaluate expression: 4096 = 00001000

0:000> u .
HCellApp!NXDeleteArcObj+0x29cf4:
69b561e4 f7e2            mul     eax,edx
69b561e6 0f90c1          seto    cl
69b561e9 f7d9            neg     ecx
69b561eb 0bc8            or      ecx,eax
69b561ed 51              push    ecx
69b561ee e864790200      call    HCellApp!CHclDoc::IsPrinting+0x53c7 (69b7db57)

0:000> g 69b56220
eax=00006040 ebx=001bcba0 ecx=00000000 edx=00000000 esi=001bcbd8 edi=00000000
eip=69b56220 esp=001bcaf0 ebp=1d126b2e iopl=0         nv up ei ng nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000287
HCellApp!NXDeleteArcObj+0x29d30:
69b56220 d1e8            shr     eax,1
0:000> p
eax=00003020 ebx=001bcba0 ecx=00000000 edx=00000000 esi=001bcbd8 edi=00000000
eip=69b56222 esp=001bcaf0 ebp=1d126b2e iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
HCellApp!NXDeleteArcObj+0x29d32:
69b56222 50              push    eax

0:000> ? @eax
Evaluate expression: 12320 = 00003020

0:000> u .
HCellApp!NXDeleteArcObj+0x29d32:
69b56222 50              push    eax
69b56223 8b4608          mov     eax,dword ptr [esi+8]
69b56226 8d1cfd00000000  lea     ebx,[edi*8]
69b5622d 03c3            add     eax,ebx
69b5622f 55              push    ebp
69b56230 50              push    eax
69b56231 e828ff0300      call    HCellApp!CHclDoc::IsPrinting+0x1d9ce (69b9615e)

(184.d78): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=1d129b4e ebx=00000000 ecx=00000ad4 edx=00000000 esi=1d126ffe edi=201db4d0
eip=71b3ae7a esp=001bcad4 ebp=001bcadc iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
MSVCR90!memcpy+0x5a:
71b3ae7a f3a5            rep movs dword ptr es:[edi],dword ptr [esi]

0:000> kv L2
ChildEBP RetAddr  Args to Child
001bcadc 69b56236 201db000 1d126b2e 00003020 MSVCR90!memcpy+0x5a
001bcaf8 69b560a5 1d126b2e 91c83667 001bcd20 HCellApp!NXDeleteArcObj+0x29d46

0:000> db 1d126b2e
1d126b2e  20 00 80 61 00 61 00 08-00 69 9a 0c 00 28 90 19   ..a.a...i...(..
1d126b3e  00 d7 9e 0d 00 9a 8f 1a-00 03 17 0f 00 97 a8 1b  ................
1d126b4e  00 81 fe 0f 00 db 41 1c-00 71 1b 10 00 db 41 1c  ......A..q....A.
1d126b5e  00 ce 3c 11 00 39 f5 1b-00 da ee 12 00 b1 c2 1a  ..<..9..........
1d126b6e  00 c1 a9 16 00 ba 77 17-00 e5 bf 1b 00 3a fa 12  ......w......:..
1d126b7e  00 4e 93 1e 00 40 c8 10-00 a2 52 23 00 02 fd 0d  .N...@....R#....
1d126b8e  00 2c ec 25 00 90 fd 0c-00 f2 e0 29 00 90 fd 0c  .,.%.......)....
1d126b9e  00 f1 ff 30 00 a1 62 0f-00 45 bf 35 00 f6 60 12  ...0..b..E.5..`.

0:000> !heap -p -a 201db000
    address 201db000 found in
    _DPH_HEAP_ROOT @ 33b1000
    in busy allocation (  DPH_HEAP_BLOCK:         UserAddr         UserSize -         VirtAddr         VirtSize)
                                18013514:         201db000             1000 -         201da000             3000
    744e8e89 verifier!AVrfDebugPageHeapAllocate+0x00000229
    77d6628e ntdll!RtlDebugAllocateHeap+0x00000030
    77d2a6cb ntdll!RtlpAllocateHeap+0x000000c4
    77cf5d20 ntdll!RtlAllocateHeap+0x0000023a
    71b63db8 MSVCR90!malloc+0x00000079
    71b63eb8 MSVCR90!operator new+0x0000001f

Description of the proof-of-concept

The Hangul HCell document format utilizes the Compound Document format that is available via Microsoft’s API. This file format is documented by Microsoft as part of their Document Interoperability Initiative. The format is similar to the FAT file format and contains a table describing where each file stream is stored within the file. Within each Hcell file is a stream labeled “Worbook” which is where the contents of the document is stored at.

The overall structure of an Hcell document can be described as a list of arrays of smaller type-length-value structures. Each record within the stream is prefixed by a header described as the following.

struct {
    uint16 type
    uint16 size
    byte[size] data
} record

Each array is terminated by an element of type 0x000a. Within the proof-of-concept, this leaves 5 Worksheets.

The Escher record is used by Hangul Hcell to draw Office Art records. This record can be identified by the type 0x00ec and is located at offset 0x129e6 of the provided proof-of-concept. This can also be located as record 72 of the 2nd sheet. The documentation for this format [1] has been released as part of Microsoft’s Open Specification promise and is named [MS-ODRAW].

<class RecordGeneral> '72'
[129e6] <instance uint16_t 'type'> 0x00ec (236)
[129e8] <instance uint16_t 'length'> 0x0e74 (3700)
[129ea] <instance unknown 'data'> "\x0f\x00\x04\xf0\x6c\x0e\x00   ..skipped ~3680 bytes..  \x11\xf0\x00\x00\x00\x00"

Within this record, the application abides by the format described in Microsoft Office’s Office Art file-format. This format prefixes each record with an 8-byte header. This particular vulnerability is located within an OfficeArtSpContainer identified by the record type of 0xf004. This specific record type is used for describing a shape in the OfficeArt format and actually contains multiple records.

<class VersionInstance>
[129ea.0] <instance type 'Instance'> (0x000, 12)
[129eb.4] <instance type 'Version'> (0xf, 4)

<class Header> 'Header'
[129ea] <instance VersionInstance 'Version/Instance'> (0x000f, 16)
[129ec] <instance RecordType 'Type'> FT_OfficeArtSp(0xf004)
[129ee] <instance uint32_t 'Length'> 0x00000e6c (3692)
[129f2] <instance OfficeArtSpContainer 'data'> RecordGeneral[4] "\x02\x00\x0a\xf0\x08\x00\x00   ..skipped ~3672 bytes..  \x11\xf0\x00\x00\x00\x00"

This shape record, OfficeArtSpContainer, is used to describe shapes which will be drawn onto the spreadsheet. Within this record is a list of subrecords which begins at offset 0x129f2. Another record, identified by the recType 0xf00b, is named OfficeArtFOPT and specifically holds the property table that contains the fields that are used by this vulnerability. Within the proof-of-concept, this record begins at offset 0x12a02.

<class VersionInstance>
[12a02.0] <instance type 'Instance'> (0x011, 12)
[12a03.4] <instance type 'Version'> (0x3, 4)

<class Header> 'Header'
[12a02] <instance office.VersionInstance 'Version/Instance'> (0x0113, 16)
[12a04] <instance office.RecordType 'Type'> FT_OfficeArtFOPT(0xf00b)
[12a06] <instance uint32_t 'Length'> 0x00000e2e (3630)

<class RecordGeneral> '1'
[12a02] <instance Header 'Header'> Version/Instance=0113 type=0xf00b length=0x00000e2e
[12a0a] <instance OfficeArtFOPT 'data'> "\x7f\x00\x10\x02\x10\x02\x42   ..skipped ~3610 bytes..  \x49\x00\x67\x11\x1d\x00"
[13838] <instance undefined 'extra'> ...

The 0xf00b record contains a list of properties for a particular shape. The number of properties in this record is identified by the Instance field within the record’s header. Within the provided proof-of-concept, this value is 0x11 which states that there’s 17 properties within the container. Each property is 6-bytes in length and has the following structure. If any of the properties has it’s fComplex bit set, then immediately following the list of properties is out-of-band data associated with the property. It is prudent to note that n order to determine where the out-of-band data begins, the number of propertes will need to be multiplied by 6 and for each property that has it’s fComplex bit set, the ‘op’ field of that property contains the length within the complexData.

<class OfficeArtFOPTEOPID> 'opid'
[12a22.0] <instance type 'fComplex'> (0x1, 1)
[12a22.1] <instance type 'fBid'> (0x1, 1)
[12a22.2] <instance type 'id'> (0x0145, 14)

In order to trigger this vulnerability any of the properties must have an id of 0x145 (pVertices) or 0x151 (pConnectionSites). Within the provided proof-of-concept a pVertices property is located at 12a22. This property has an op value of 0x90e which states that the size of it’s data within the complexData field is 0x90e bytes. At offset 0x12a23 the complexData field has 0x30e bytes which is the next number of bytes that contains the complexData.

; At offset 0x12a22 is an example pVertices property.
<class OfficeArtFOPTE> '4'
[12a22] <instance OfficeArtFOPTEOPID 'opid'> (0xc145, 16)
[12a24] <instance pVertices 'op'> 0x0000090e (2318)

; At offset 0x12a23 is the pConnectionSites property that this proof-of-concept utilizes.
<class OfficeArtFOPTE> '6'
[12a2e] <instance OfficeArtFOPTEOPID 'opid'> (0xc151, 16)
[12a30] <instance pConnectionSites 'op'> 0x0000030e (782)

Each piece of data is indexed by whichever properties have it’s fComplex bit set. Within the proof-of-concept the pConnectionSites property’s complexData field begins at offset 0x1338a. This is the 3rd property that has it’s fComplex bit set. The other properties that prefix the complexData are the pVertices propetty at offset 0x12a22 and the pSegmentInfo property at offset 0x12a28.

; pConnectionSites complexData field
<class block(782)> '2'
1338a  00 02 00 00 40 60 20 00  80 61 00 61 00 08 00 69  ....@` ..a.a...i
1339a  9a 0c 00 28 90 19 00 d7  9e 0d 00 9a 8f 1a 00 03  ...(............
133aa  17 0f 00 97 a8 1b 00 81  fe 0f 00 db 41 1c 00 71  ............A..q
133ba  1b 10 00 db 41 1c 00 ce  3c 11 00 39 f5 1b 00 da  ....A...<..9....

Both the pVertices and pSegmentInfo properties’ complexData field have the following structure. This structure contains the fields that are utilized by the vulnerability. The expected size of the pVertices and pSegmentInfo fields is supposed to be 8. The application uses the value of 8 multiplied by the nElems field to calculate the size of the buffer. However, when copying file-data into this buffer, it explicitly trusts the value in the cbElem field. If any of the pVertices or pSegmentInfo properties’ complexData contains a cbElem value other than 8, then this vulnerability is being triggered. Within the provided proof-of-concept, the IMsoArray structure is at offset 0x1338a and uses the cbElem value of 0x6040.

<class IMsoArray>
[1338a] <instance uint2 'nElems'> 0x0200 (512)
[1338c] <instance uint2 'nElemsAlloc'> 0x0000 (0)
[1338e] <instance uint2 'cbElem'> 0x6040 (24640)

Timeline

2016-03-28 - Discovery
2016-04-19 - Vendor Notification
2016-08-04 - Public Disclosure

References

[1] http://download.microsoft.com/download/2/4/8/24862317-78F0-4C4B-B355-C7B2C1D997DB/[MS-ODRAW].pdf

Credit

Discovered by Cisco Talos.