原文链接:https://www.fireeye.com/blog/threat-research/2016/05/how_rtf_malware_evad.html
译者注:这篇文章是FireEye研究员Junfeng Yang在2016年写的关于RTF混淆技巧的一个总结,这是我看过的关于这方面的最好的一篇文章,由于我在国内没有看到过这方面的好文章,因此决定把它翻译一下。
RTF恶意软件如何躲避基于特征的静态检测
Junfeng Yang写于2016年3月20号
富文本格式(RTF)是微软开发的一种文档格式,它被广泛地用在各种平台超过29年。RTF格式非常灵活,因此也非常复杂。这使得开发一个安全的RTF解析器很有挑战性。一些臭名昭著的漏洞,如CVE-2010-3333和CVE-2014-1761都是由于RTF解析逻辑实现部分的错误导致。
事实上,RTF恶意软件并不局限于利用RTF解析漏洞。恶意RTF文档可以嵌入其他与RTF解析器不相关的漏洞,因为RTF支持嵌入对象,例如OLE对象和图像(译者补充:还有链接对象,例如CVE-2017-0199和CVE-2017-8759)。CVE-2012-0158和CVE-2015-1641是两个典型的这种漏洞——它们的根本原因并不位于RTF解析器,但攻击者可以通过其他文件格式利用这些漏洞,例如DOC和DOCX。
另一种RTF恶意软件并不使用任何漏洞。它简单地包含嵌入的恶意可执行文件,并且诱使用户去触发这些恶意文件。这允许攻击者通过电子邮件去传播恶意软件,因为电子邮件显然不是一个可以直接发送可执行文件的好载体(译者注:exe等文件类型会被电子邮件客户端(如outlook)直接锁住)。
大量的恶意软件作者更喜欢用RTF作为一个攻击载体,因为RTF是一种混淆友好型格式。因此,他们的恶意软件可以简单躲避基于如YARA或Snort的静态特征检测。这也是为什么在一个脚本化利用的时代,我们仍然看到大量这类基于RTF攻击的一个很大的原因。
在这篇博客里面,我们呈现了一些被恶意RTF使用的通用逃逸技巧。
让我们来讨论一些不同的RTF混淆策略。
这个漏洞被Team509在2009年报告,是一个典型的栈溢出漏洞。利用这个漏洞是如此稳定和可靠,以至于在今天它仍在野外被使用,距离它被发现已经7年了!最近,攻击者利用这个漏洞针对了印度大使馆。
这个漏洞的根本原因是微软RTF解析器在处理pFragments图形属性时存在一处栈溢出。精心构造一个恶意RTF来利用这个漏洞允许攻击者执行容易代码。微软自漏洞披露就修复了这个漏洞,但是许多老版本的Microsoft Office仍受影响。所以它的威胁评级仍然非常高。
Microsoft Office RTF解析器在拷贝源数据到一个有限的栈缓冲区时缺少合适的边界检查。针对这个漏洞利用可以被简化如下:
因为pFragments在正常RTF文档中相当罕见,许多厂商只使用YARA或Snort简单地检测这个关键字和紧随\sv的超长数字来捕获利用。这个方法对于没有混淆的样本是有用的,包括Metasploit生成的样本。然而,在对抗在野样本时,这类基于特征的检测就显得不足了。举个例子,针对印度大使馆的恶意RTF文档就是一个用来揭示这类基于特征的检测的不利一面的好例子。图1显示了这个RTF文件在16进制编辑器中的样子。我们简化了图1,因为空格限制——在原始文档中有大量重复的符号,例如{}。
图1. 混淆过的CVE-2010-3333样本
正如我们所看到的那样,pFragments关键字被分割成许多部分,这可以绕过大多数基于特征的检测。举个例子,大多数反病毒产品在这个样本第一次提交到VirusTotal都检测失败。事实上,不仅是\sn的分割片段被结合在一起,\sv的片段也被结合在一起。下面的例子证明了这种混淆:
我们可以想出大量与前面提到的样本不同的方法来击败基于特征的静态检测。
注意‘\x0D’和‘\x0A’的混合——它们是‘\r’和‘\n’,RTF解析器会简单地忽略它们。
用户可以在RTF中嵌入多种对象,例如OLE(对象嵌入与链接)控制对象。这使得与OLE相关的漏洞,例如CVE-2012-0158和CVE-2015-1641,在RTF中进行利用成为可能。除了这些利用,在RTF文档中嵌入PE,CPL,VBS和JS这类可执行文件也是不常见的。这些文档要求一些社会工程的形式去诱导用户启动嵌入的对象。我们看到一些数据丢失防护(DLP)解决方案在RTF文档中嵌入PE文件。这是个坏实践,因为它增长了用户的不良习惯。
让我们首先来看一下嵌入对象的语法:
<objtype>指明了对象类型。\objocx是RTF恶意软件中最常见的类型;因此,让我们以它为例。紧随\objdata的数据是OLE1 native数据,定义如下:
攻击者会尝试插入多种元素到<data>以躲避静态特征检测。让我们看一些例子来理解这些技巧:
a. 举个例子,\binN可以被#SDATA替换。紧随\binN的数据是原生二进制数据。在下面的例子里,数字123会被当作二进制数据,因此在内存中被转换位十六进制值313233。
让我们看一下另一个例子:
如果我们尝试去以上表中标记为红色的数字参数字符串作为参数调用atoi或atol,我们会得到0x7fffffff,然而它的真实值应当是3。这会发生是因为\bin会获取一个32位有符号整型值作为参数。你也许会认为RTF解析器调用atoi或atol来转换数字字符串到一个整数;然而,实际情况并不是这样的。Microsoft Word的RTF解析器并不使用这些标准的C运行时函数。相反,Microsoft Word的RTF解析器中的atoi函数实现如下:
b. \ucN和\uN
这两个都会被忽略,但紧随\uN的字符不会被跳过。
c. 空格字符(回车,换行和制表符):0x0D (\n), 0x0A (\r), 0x09 (\t)都会被忽略。
c. 转义字符
RTF有一些特殊的被保留的符号。正常使用时,用户需要转移这些符号。这里是一个不完全的列表:
\}
\{
\%
\+
\-
\\
\'hh
所有这些转移符号都会被忽略,但有个有趣的情况,\’hh除外。让我们先来看一个例子:
当解析\’11时,解析器会将11当作一个被编码过的十六进制字节。这个十六进制字节然后被丢弃,接着继续解析objdata剩下部分。\’11前面的1也会被忽略。一旦RTF解析器解析\’11前的1时,这是一个8位字节的高4位,然后它们马上遇到\’11,高4位将会被丢弃。那是因为用来解码16进制字符串到二进制字节的内部状态被重设了。
(may be used to identify 8-bit values).
下表显示了处理过程,黄色行的两个1来自\’11。显然这个混合的\’11扰乱了状态变量,这导致第二个字节的高4位被丢弃。
e. 超长的控制字和数字参数
RTF格式规范规定控制字长度不能超过32个字母,并且控制字相关的数字参数必须是16位有符号整数或是32位有符号整数,但微软office的RTF解析器并没有严格遵循这一规范,它的实现中只保留了一块大小为0xFF的缓冲区用来存储控制字字符串和数字参数字符串,这两者都是以null结尾的,长度大于0xFF之后的所有字符都不会被作为控制字或者参数字符串的一部分。相反,控制字和数字参数会被强制结束。
在第一个混淆例子中,超长控制字的长度是0xFE。通过添加一个null终止符,控制字字符串将会到达0xFF的最大长度,接下来的数据属于objdata。
在第二个混淆例子中,“bin”控制字和它的参数的整个长度是0xFD。通过添加它们的null终止符,长度等于0xFF。
f. 额外的技术
Word程序会使用列表中的最后一个\objdata控制字,如下所示:
{\object\objocx\objdata 554445\objdata 444454545}
OR
{\object\objocx{{\objdata 554445}{\objdata 444454545}}}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课