CVE: CVE-2019-16338
Tested Versions:
- Hancom Office NEO (HwordApp)
Product URL(s): https://www.hancom.com/cs_center/csDownload.do
Description of the vulnerability
Hangul Office is published by Hancom, Inc. and is considered one of the more popular Office suites used within South Korea.
When opening a specially crafted Office Open XML Document (.docx), HwordApp does not properly process a tfo_common
object which will cause a use-after-free.
This may lead to code execution under the context of the application.
Vulnerability
Crash context:
(d4c.2f8): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=2e2e0f58 ebx=0000004b ecx=2e2e0f58 edx=02f110d0 esi=57848fe8 edi=57848fe8
eip=70a4d8cf esp=0070a3d8 ebp=0070a3e0 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00210206
HwordApp!HwordDeletePropertyArray+0xb6f68f:
70a4d8cf 8b01 mov eax,dword ptr [ecx] ds:002b:2e2e0f58=????????
ECX points to a block of freed memory:
address 2e2e0f58 found in
_DPH_HEAP_ROOT @ 2f11000
in free-ed allocation ( DPH_HEAP_BLOCK: VirtAddr VirtSize)
5b8d071c: 2e2e0000 2000
73a290b2 verifier!VerifierDisableFaultInjectionExclusionRange+0x00003162
7779180c ntdll!RtlpNtEnumerateSubKey+0x00004935
7774a8fe ntdll!RtlUlonglongByteSwap+0x0000db5e
776f2c45 ntdll!RtlQueryPerformanceCounter+0x00000281
75f714ad kernel32!HeapFree+0x00000014
7256ecfa MSVCR120!free+0x0000001a
701a3d1e HwordApp!HwordDeletePropertyArray+0x002c5ade
70a4d8cc HwordApp!HwordDeletePropertyArray+0x00b6f68c
70a5572f HwordApp!HwordDeletePropertyArray+0x00b774ef
7020ff31 HwordApp!HwordDeletePropertyArray+0x00331cf1
70b0be74 HwordApp!HwordDeletePropertyArray+0x00c2dc34
70adfb4b HwordApp!HwordDeletePropertyArray+0x00c0190b
70491857 HwordApp!HwordDeletePropertyArray+0x005b3617
701564de HwordApp!HwordDeletePropertyArray+0x0027829e
70154e7a HwordApp!HwordDeletePropertyArray+0x00276c3a
6fef74b3 HwordApp!HwordDeletePropertyArray+0x00019273
As indicated by the verifier, this is a use-after-free bug.
There is also a call dword ptr [eax]
following with the crash instruction, that means if we can control the freed memory, we can easily cause arbitrary code execution.
We are going to see what object it is and when it is going to be freed. ECX comes from EDI , so we are going to add a breakpoint at 0x70A4D8B8
. When the breakpoint is hit, we will see what the object it is.
Breakpoint 0 hit
eax=00000000 ebx=0000004b ecx=57838fe8 edx=57838fe8 esi=57838fe8 edi=57838fe8
eip=70a4d8b8 esp=0070a3d8 ebp=0070a3e0 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200206
HwordApp!HwordDeletePropertyArray+0xb6f678:
70a4d8b8 837f0400 cmp dword ptr [edi+4],0 ds:002b:57838fec=2da66f58
Breakpoint 0 hit
eax=00000000 ebx=0000004b ecx=57838fe8 edx=57838fe8 esi=57838fe8 edi=57838fe8
eip=70a4d8b8 esp=0070a3d8 ebp=0070a3e0 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200206
HwordApp!HwordDeletePropertyArray+0xb6f678:
70a4d8b8 837f0400 cmp dword ptr [edi+4],0 ds:002b:57838fec=2da66f58
0:000> dd edi
57838fe8 70f1d1c8 2da66f58 00000000 c0c00000
57838ff8 0000004b d0d0d0d0 ???????? ????????
57839008 ???????? ???????? ???????? ????????
57839018 ???????? ???????? ???????? ????????
57839028 ???????? ???????? ???????? ????????
57839038 ???????? ???????? ???????? ????????
57839048 ???????? ???????? ???????? ????????
57839058 ???????? ???????? ???????? ????????
0:000> dd 2da66f58
2da66f58 70ecc3d8 70ecc3e4 00000020 00000000
2da66f68 00000000 41700000 00000002 49000000
2da66f78 00000001 00000000 00000001 00000001
2da66f88 00000000 00000001 00000001 70ecc330
2da66f98 70ecc33c 00000000 c0c0c001 00000000
2da66fa8 70ec9584 00000002 00000007 00000000
2da66fb8 00000000 00000000 70ec9584 00000002
2da66fc8 00000088 00000000 00000000 00000000
address 2da66f58 found in
_DPH_HEAP_ROOT @ 2f11000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize)
2db61ed4: 2da66f58 a8 - 2da66000 2000
? HwordApp!HwordDeletePropertyArray+fee198
73a28e89 verifier!VerifierDisableFaultInjectionExclusionRange+0x00002f39
7779103e ntdll!RtlpNtEnumerateSubKey+0x00004167
7774abe2 ntdll!RtlUlonglongByteSwap+0x0000de42
776f34a1 ntdll!RtlQueryPerformanceCounter+0x00000add
7256ed63 MSVCR120!malloc+0x00000033
7256ee1f MSVCR120!operator new+0x0000000e
72606184 MSVCR120!operator new+0x0000000b
70a56397 HwordApp!HwordDeletePropertyArray+0x00b78157
7020ff31 HwordApp!HwordDeletePropertyArray+0x00331cf1
We now know this object is created at 0x70A56392
, when we look into the code near this location, we find an interesting string:
v9 is the object and sub_701A3A60
seems to be the initialization function:
Thus we conclude that this object is called tfo_common
.
But when is the object is freed? At 0x70A4D8C9
, there will a call to 0x701a3cc0
, and its only parameter is the integer 1.
When we jump to 0x701A3CC0
, we can see the logic behind this:
Let’s go back to function sub_70A4D8A0
, the free and re-use behaviour is depicted here:
Timeline:
- 2019-01-09 Vendor disclosure
- 2019-01-10 Vendor silently patched
Vendor Response
The vendor has silently released a fix for the issue some time after reporting.