Office Equation类型的漏洞从2017年底开始被发现,到目前一共可用的有11882,0802,0798三个漏洞,可以说2018年office中使用最多的也是这三个漏洞,也是office中混淆利用最繁杂的一类漏洞(应该没有之一),由于equation本身的问题导致这三个漏洞的在利用的混淆上有很多的变种,有意思的是这些混淆的技巧在三个漏洞中基本是通用的,本文通过几个样本来对这几个漏洞的混淆利用进行一次总结。
首先无论是11882,0802,还是0798,一个正常的利用样本的结构如下所示,即eqnolefilehdr,mtef head,mtef byte stread(这是EquationNative流的形式),当为Ole10Native流时,结构变为4字节+ mtef head,mtef byte stread。
mtef head正常情况如下所示,如上图中的03 01 01 03 0A
之后的mtef record按类型一共包含14类,其中漏洞出在其中的type 5(matrix,0798),type 8(font,11882/0802中)
样本一
Vt上也是报的11882,但是vt上大多报的不准,因此我决定确认一下到底是不是11882.
上调试器,来个断点,11882溢出点断下。
覆盖返回地址。
进入shellcode。
现在基本确认是11882,如下红框部分就是对应的equation head,mtef head,之后是对应的shellcode部分,长度47,符合11882的溢出长度,接下来一步一步看这个样本是如何进行的混淆。
首先是equation head部分,在有Equationnative 流的情况下,这部分的长度为0x1c,以0x1c开头,而值得注意的是绿色部分的值。
通过对比解析equation的流程就可以知道,读取0x1c长度的头部之后,会判断其第二个字节开始的四字节的值是否小于0x20000,因此这个地方是一个混淆点,只要保证值小于0x20000即可。
可以看到之后的比较,之后的equation head中的内容实际是没有太多要求的(至少在解析代码的流程中是没有看到对应的作用的)。
之后到metf head,这个和之前熟悉的03 01 01 03 0A完全不一致(之前的报告里也遇到过,但第一个和第三个字节从文档来看是不能变的,难道文档有毒?)。
Metfhead的解析在以下函数。
进去之后发现,确实2,4,5位是没有检验的,第一位是version,但是version是可以有多个值的,只要不小于2,不大于3即可,甚至当你大于了3,还有贴心的减掉100的机会,也就是说第一位可用的值有02,03,102,103,而该样本中用的是02,因此符合判断条件,而位于第三位的值如果不为01,则会进入到函数sub_4184A0中,该函数比较复杂,但是却没有相关异常的操作,即应该是可以正常返回的。
调试样本可以看到metf第三位的值为a4,不等于1,会进入对应的函数流程。
但是该函数直接运行之后,似乎并不影响之后的程序。
因此可知,metf除了第一个字节有所要求外,其余字节也是可变的。
之后就对应的font部分,正常的情况一般为0A 08 00 00,可以看到这个地方基本都变了。
Metfhead check之后继续往后读取值,此时可以看到直接读取的是01,之后进入正常的11882漏洞执行流程。
判断前一步中读取的是否为font的type 8,如果不是分两个流程如果大于9,则依次再读取下一个字节的内容(这也是之前11882普遍喜欢使用的一个混淆方式,即在08 type前插入任意大于9的字节,皆可起到混淆的作用,同时不影响漏洞的利用),第二种流程即小于9则直接返回,很明显这个样本属于第二中情况,结合上面的调试,我们知道该样本11882是利用成功的,即攻击者使用了另外的执行流程来利用该漏洞(这样做的好处是可以绕过hook指定函数检测漏洞利用的方式)。
由于fun_CheckrecordHead是唯一的入口,因此我们在这个函数下断点,看看到底还有哪个地方能导致漏洞触发,结果如下所示,可以看到,入口是0798这个漏洞的入口。
那是如何进入到这个0798的触发点的了?如上述所示正常流程的11882函数由于值为01,会直接返回,返回值为01,直接进入到switch中。
可以看到当case等于1时,进入到0798的漏洞函数。
继续往里。
此时可知,实际在进入0798的漏洞派发函数前,还有一次调用1188/0802的机会,熟悉0798的漏洞就应该知道,实际上前面的地方除了01外,04也是可以导致进入0798的,因此这个地方的混淆可以有01,04两种选择,本质上确是通过0798中MATRIX record触发的11882/0802漏洞。
08之后的两个字节实际上也没用,因此也是可混淆的。
样本二
这个样本中可以看到metf的第一位为被设为66(102),比较有趣的是蓝色部分,可以看到其使用了01的标记用于进入到0798的流程,通过0798进入对应的11882.此时中间有11,22,33,44四个字节的混淆字节,F8为font tag。
校验完meft head头,读取type类型,由于此处的类型为01,所以正常的11882漏洞流程直接将其返回,进入之后的case 1流程。
在case1流程中,进入0798函数。
0798函数中包含了11882流程,进入并传入11参数,11882直接返回1,dispatch函数进入case 0流程。
Case 0 流程进入的函数如下所示,if 判断成功,直接返回,需要注意的是else中实际也是一处可供利用点,下两处红框中的函数都是可以进入到11882/0802漏洞触发流程的(需要注意的是这样利用依赖与a4的值,因此需要特殊构造)。
Case 0流程执行完毕,dispatch函数返回,循环再次读取下一位,此时读取22,并再次进入dispatch函数。
22作为11882漏洞函数流程参数,直接返回2,进入dispatch 1流程。
Case 1流程的处理函数如下,首先通过函数sub_43B449A再次往下读取一位,即33,函数中通过判断读取的值减掉0x80的值来判断返回1还是其他(依赖于一块内存变量word_45ABE6),此处返回0,之后判断版本,及sub_43B449A的返回值,由于返回值为0,这将导致if 判断失败,进入else流程,else中再次读取一位,即44,最终进入最后的0798流程,此时0798中读取F8,最终进入到11882的利用流程。
sub_43B449A函数如下,可以看到通过33这个位置的值是可以在一定程度上控制返回值的,0x89,0x90可以保证返回1,其余情况则依赖于word_45ABE6这个位置的值。
实际上如果能控制sub_43B449A,及sub_420AE3 ,sub_44B324的返回值,进入if同样也是一条11882的触发流程,但是目前来看难度较高。主要是首先需要保证sub_43B449A的返回值小于0,这就要求word_45ABE6这个位置可控。
word_45ABE6引用的地方如下,在fun_shell1_11882进行了设置。
但是需要注意的是该函数是在11882流程里,且在利用返回后设置,因此word_45ABE6的值控制起来没有任何意义。
由上文的分析可知,11882/0802这两个函数有多种可能的触发方式,除了常规的ParseMTEFData外,其实大部分都集中在0798的dispatch函数中。
转载请注明出处