Talos Vulnerability Report


Hancom Hangul Office HShow!NXDeleteLineObj+0x47269 Code Execution Vulnerability

August 4, 2016

Report ID



This vulnerability was discovered within the Hangul HShow 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 HShow Document (.hpt) and processing a structure within the document, the application will use a static size to allocate a heap buffer yet explicitly trust a size from the file when modifying data inside of it. Due to this, an aggressor can corrupt memory outside the bounds of this buffer which can lead to code execution under the context of the application.

Tested Versions

Hancom Office 2014 VP Trial HShow.exe Product version: HncBM90.dll Product version:

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


Hangul HShow is prefixed with a header which can describe whether it’s contents are encoded with the zlib library. After processing the header, the application will take the version and use it to determine which structures need to be decoded within the zlib-encoded data. When reading a particular structure from the file, the application will allocate 0xa0 bytes for it and initialize it with data from the file. Later, the application will trust another length when modifying data in this buffer which can allow one to corrupt memory outside the bounds of the 0xa0 byte buffer.

First the application will read a structure from the file. This structure has 5 different cases and will read a 16-bit value from the file. This 16-bit value is used to control the number of iterations within a loop that is later used during the oob write.

0190d2e1 8d442430        lea     eax,[esp+30h]
0190d2e5 8bcd            mov     ecx,ebp
0190d2e7 e814d8fbff      call    HShow!NXDeleteLineObj+0x47070 (018cab00)   ; \
0190d2ec 03d8            add     ebx,eax
018cace8 03f0            add     esi,eax
018cacea 8b07            mov     eax,dword ptr [edi]
018cacec 8b5014          mov     edx,dword ptr [eax+14h]
018cacef 6a00            push    0
018cacf1 6a02            push    2
018cacf3 8d4b2a          lea     ecx,[ebx+2Ah]
018cacf6 51              push    ecx
018cacf7 8bcf            mov     ecx,edi
018cacf9 ffd2            call    edx            ; XXX: read a uint16_t
018cacfb 83e802          sub     eax,2
018cacfe f7d8            neg     eax
018cad00 1bc0            sbb     eax,eax
018cad02 83e0fe          and     eax,0FFFFFFFEh
018cad05 83c002          add     eax,2

After reading this structure, the application will then encounter the following code. This code will allocate 0xa0 bytes for a buffer. This is done at address 0x18fc9d1. Immediately afterwards, the application will initialize it with memset followed by initializing it with data from the file at address 0x18fc9f5. This statically sized buffer will be the one that can be corrupted later.

018fc9d1 68a0000000      push    0A0h
018fc9d6 e8c83b6e00      call    HShow!NGLSetSurfaceMetal+0xe87d3 (01fe05a3)    ; allocation
018fc9db 68a0000000      push    0A0h
018fc9e0 6a00            push    0
018fc9e2 50              push    eax
018fc9e3 e8c21b6f00      call    HShow!NGLSetSurfaceMetal+0xf67da (01fee5aa)    ; memset
018fc9e8 89432c          mov     dword ptr [ebx+2Ch],eax
018fc9eb 8b752c          mov     esi,dword ptr [ebp+2Ch]
018fc9ee 8bf8            mov     edi,eax
018fc9f0 b928000000      mov     ecx,28h
018fc9f5 f3a5            rep movs dword ptr es:[edi],dword ptr [esi]

Afterwards, the application will enter the following loop at 0x18fca10. This loop will iterate the number of times as specified in the structure that was read previously. Due to this value being 15-bits in length, and the 0xa0 being less than 15-bits…this loop will act on data outside the bounds of the heap allocation.

018fc9fe 663b4b2a        cmp     cx,word ptr [ebx+2Ah]  ; XXX
018fca02 0f8d05010000    jge     HShow!NXDeleteLineObj+0x7907d (018fcb0d)
018fca08 eb06            jmp     HShow!NXDeleteLineObj+0x78f80 (018fca10)
018fca10 8b532c          mov     edx,dword ptr [ebx+2Ch]
018fca48 0fbf532a        movsx   edx,word ptr [ebx+2Ah] ; XXX
018fca4c 40              inc     eax
018fca4d 3bc2            cmp     eax,edx
018fca4f 7cbf            jl      HShow!NXDeleteLineObj+0x78f80 (018fca10)

Inside the loop, the application will test to see if a 16-bit value has it’s signed bit set, and if it doesn’t it will write the current index into that pointer. Due to the sentinel for this loop possibly being larger than 0xa0, this write will corrupt data after the 0xa0 byte buffer.

018fca10 8b532c          mov     edx,dword ptr [ebx+2Ch]
018fca13 8d0c42          lea     ecx,[edx+eax*2]        ; XXX: use iteration count to calculate index into buffer
018fca16 0fb75326        movzx   edx,word ptr [ebx+26h]
018fca1a 663911          cmp     word ptr [ecx],dx
018fca1d 7d04            jge     HShow!NXDeleteLineObj+0x78f93 (018fca23)
018fca1f 42              inc     edx
018fca20 668911          mov     word ptr [ecx],dx      ; XXX: write current iteration count to %ecx

0:010> lm
start    end        module name
012f0000 027c9000   HShow      (export symbols)       HShow.exe

Crash Analysis

(330.67c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000050 ebx=5b00aedc ecx=59ad5000 edx=00002e00 esi=ffffc763 edi=ffffc764
eip=018fca1a esp=5c9fd638 ebp=5c9fd67c iopl=0         nv up ei ng nz na pe cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010287
018fca1a 663911          cmp     word ptr [ecx],dx        ds:0023:59ad5000=????

0:010> u .
018fca1a 663911          cmp     word ptr [ecx],dx
018fca1d 7d04            jge     HShow!NXDeleteLineObj+0x78f93 (018fca23)
018fca1f 42              inc     edx
018fca20 668911          mov     word ptr [ecx],dx

0:010> ? wo(@ebx+2a)
Evaluate expression: 11776 = 00002e00

0:010> ? poi(@ebx+2c)
Evaluate expression: 1504530272 = 59ad4f60


Discovered by Cisco Talos


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