CVE-2016-4298
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 attempt to allocate space for a list of elements using a length from the file. When calculating this length, an integer overflow can be made to occur which will cause the buffer to be undersized when the application tries to copy file data into the object containing this structure. This allows one to overwrite contiguous data in the heap which can lead to code-execution under the context of the application.
Hancom Office 2014 VP Trial HShow.exe Product version: 9.1.0.2176 HncBM90.dll Product version: 9.1.0.2291
http://www.hancom.com http://www.hancom.com/en/product/product2014vp_01.jsp
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 uint32_t from the file, the application will take this value and multiply it by 0x228. Later, the application will use this result to perform an allocation for a buffer that is used by a loop that reads content from the file. Due to the application not checking for an upper bounds on this value, the integer can be made to overflow causing the heap allocation to be undersized at which point the loop can be made to write outside this buffer.
After reading the header and decompressing the zlibbed data section in the file, the application will eventually encounter the following function. This function is responsible for reading a 0x10 byte structure from the file. When the function returns, the function only checks if the dword has it’s signed-bit set.
HShow!NXDeleteLineObj+0x560c5:
00fd9b55 8b4534 mov eax,dword ptr [ebp+34h]
00fd9b58 50 push eax
00fd9b59 8bc3 mov eax,ebx
00fd9b5b e8e05dffff call HShow!NXDeleteLineObj+0x4beb0 (00fcf940) ; XXX
00fd9b60 8b4534 mov eax,dword ptr [ebp+34h]
00fd9b63 83c404 add esp,4
00fd9b66 833800 cmp dword ptr [eax],0
00fd9b69 7e7a jle HShow!NXDeleteLineObj+0x56155 (00fd9be5)
Inside this function, the application will read a dword into the structure that’s passed as an argument in the %eax register.
HShow!NXDeleteLineObj+0x4beb0:
00fcf940 53 push ebx
00fcf941 55 push ebp
00fcf942 8b6c240c mov ebp,dword ptr [esp+0Ch]
00fcf946 56 push esi
00fcf947 57 push edi
00fcf948 8bd8 mov ebx,eax ; target structure
00fcf94a 8b03 mov eax,dword ptr [ebx]
00fcf94c 8b5014 mov edx,dword ptr [eax+14h]
00fcf94f 6a00 push 0
00fcf951 6a04 push 4
00fcf953 55 push ebp
00fcf954 8bcb mov ecx,ebx
00fcf956 ffd2 call edx ; read 4-bytes form file
00fcf958 8bf0 mov esi,eax
After reading the dword, the application will use the dword in the following code. This code multiplies the dword by 0x228 and then passes it to a function to allocate memory followed by initializing the memory using the memset function. Due to the application failing to check the bounds of this multiply, an integer overflow can be made to occur. This will later be used in an allocation.
HShow!NXDeleteLineObj+0x560db:
00fd9b6b 8b08 mov ecx,dword ptr [eax]
00fd9b6d 8b7804 mov edi,dword ptr [eax+4]
00fd9b70 69c928020000 imul ecx,ecx,228h ; XXX: integer overflow
00fd9b76 51 push ecx
00fd9b77 e8276a7000 call HShow!NGLSetSurfaceMetal+0xe87d3 (016e05a3) ; memory allocation
00fd9b7c 8b5534 mov edx,dword ptr [ebp+34h]
00fd9b7f 8b0a mov ecx,dword ptr [edx]
00fd9b81 69c928020000 imul ecx,ecx,228h
00fd9b87 83c404 add esp,4
00fd9b8a 51 push ecx
00fd9b8b 6a00 push 0
00fd9b8d 50 push eax ; XXX
00fd9b8e e8174a7100 call HShow!NGLSetSurfaceMetal+0xf67da (016ee5aa) ; memset
Later, the application will use the dword from the file as a counter to a loop that’s responsible for reading each structure from the file. This loop will iterate the number of times that’s specified by the dword and will eventually call a function with the same parameters as fread(…) to decompressed the zlibbed data into the allocated buffer. Due to this loop using a different value than the one used to allocate the space to write to, a heap-based buffer overflow can be made to occur.
HShow!NXDeleteLineObj+0x56124:
00fd9bb4 8b4004 mov eax,dword ptr [eax+4]
00fd9bb7 0344241c add eax,dword ptr [esp+1Ch]
00fd9bbb ff742414 push dword ptr [esp+14h]
00fd9bbf 8d0c37 lea ecx,[edi+esi]
00fd9bc2 8bd3 mov edx,ebx
00fd9bc4 e887e1ffff call HShow!NXDeleteLineObj+0x542c0 (00fd7d50) ; XXX: reads data from file
00fd9bc9 8b4c2424 mov ecx,dword ptr [esp+24h]
00fd9bcd 8144241c28020000 add dword ptr [esp+1Ch],228h
00fd9bd5 03f8 add edi,eax
00fd9bd7 8b4534 mov eax,dword ptr [ebp+34h]
00fd9bda 41 inc ecx
00fd9bdb 3b08 cmp ecx,dword ptr [eax] ; XXX: dword from file
00fd9bdd 894c2424 mov dword ptr [esp+24h],ecx
00fd9be1 7cd1 jl HShow!NXDeleteLineObj+0x56124 (00fd9bb4)
With the provided proof-of-concept, the particular fread that overflows this buffer is located here.
HShow!NXDeleteLineObj+0x4be0b:
00fcf89b bd00010000 mov ebp,100h
00fcf8a0 8b06 mov eax,dword ptr [esi]
00fcf8a2 8b5014 mov edx,dword ptr [eax+14h]
00fcf8a5 6a00 push 0
00fcf8a7 6a02 push 2
00fcf8a9 57 push edi
00fcf8aa 8bce mov ecx,esi
00fcf8ac ffd2 call edx ; fread(...)
00fcf8ae 83c702 add edi,2
00fcf8b1 83ed01 sub ebp,1
00fcf8b4 75ea jne HShow!NXDeleteLineObj+0x4be10 (00fcf8a0)
0:005> lm
start end module name
009f0000 01ec9000 HShow (export symbols) HShow.exe
6ba90000 6bad5000 HncBM90 (export symbols) HncBM90.dll
eax=543efff0 ebx=5c51ddd8 ecx=00000000 edx=00000008 esi=00005957 edi=41a00000
eip=00fd9b77 esp=5c51d1e0 ebp=67217ee8 iopl=0 ov up ei pl nz na pe cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000a07
HShow!NXDeleteLineObj+0x560e7:
00fd9b77 e8276a7000 call HShow!NGLSetSurfaceMetal+0xe87d3 (016e05a3)
0:010> ub .
HShow!NXDeleteLineObj+0x560d2:
00fd9b62 3483 xor al,83h
00fd9b64 c40483 les eax,fword ptr [ebx+eax*4]
00fd9b67 3800 cmp byte ptr [eax],al
00fd9b69 7e7a jle HShow!NXDeleteLineObj+0x56155 (00fd9be5)
00fd9b6b 8b08 mov ecx,dword ptr [eax]
00fd9b6d 8b7804 mov edi,dword ptr [eax+4]
00fd9b70 69c928020000 imul ecx,ecx,228h
00fd9b76 51 push ecx
0:010> ? poi(@eax)
Evaluate expression: 1073741824 = 40000000
0:010> ? poi(@eax)*228
Evaluate expression: 0 = 00000000
(a40.8a0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=67226000 ebx=00000002 ecx=671b892b edx=671acaff esi=5baa6f98 edi=67226000
eip=6bab3376 esp=5c51ce88 ebp=5c51cee0 iopl=0 nv up ei pl nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010216
HncBM90!HncGZUpdateCRC+0xa686:
6bab3376 8810 mov byte ptr [eax],dl ds:0023:67226000=??0:010> kv
0:010> kv
ChildEBP RetAddr Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
5c51cee0 6baa88d9 5baa6f98 00000002 67226000 HncBM90!HncGZUpdateCRC+0xa686
5c51d16c 00ff8918 67226000 00000002 000086c5 HncBM90!HncGZRead+0x79
5c51d18c 00fcf8ae 67226000 00000002 00000000 HShow!NXDeleteLineObj+0x74e88
5c51ddd8 5c51de40 00001000 00000000 00000000 HShow!NXDeleteLineObj+0x4be1e
5c51dddc 00000000 00000000 00000000 00000000 0x5c51de40
0:010> dc 67226000
67226000 ???????? ???????? ???????? ???????? ????????????????
67226010 ???????? ???????? ???????? ???????? ????????????????
Inside the provided proof of concept, the 0x10 byte structure that’s read is located at offset 0x7faf within the decompressed zlib data. The first dword is the value multiplied by 0x228 for the allocation.
7fa0 00 00 00 00 00 58 64 a0 00 96 00 00 07 07 00 00 .....Xd.........
7fb0 00 00 40 00 00 a0 41 00 00 49 00 00 00 09 00 00 ..@...A..I......
7fc0 00 01 00 01 00 01 00 ff ff ff 00 01 00 8c 8c 8c ................
7fd0 00 00 00 01 00 01 00 ff 78 69 63 00 4a 00 75 8c ........xic.J.u.
2016-03-28 - Discovery
2016-04-19 - Vendor Notification
2016-08-04 - Public Disclosure
Discovered by Cisco Talos.