该漏洞在微软针对CVE-2017-11882漏洞打上了kb4011604补丁后产生的,该漏洞同样是OLE 对象的“Equation Native”的数据流中的数据导致的,导致漏洞的对象是tagLOGFONT的字体名。在微软对CVE-2017-11882修补后,CVE-2018-0802的漏洞利用构造需要用到两个特别巧合的地方,最终导致了噩梦公式二代利用的出现。
环境 | |
---|---|
操作系统 | Windows 7 SP1_x86 |
虚拟机 | VMware Workstation 14 Pro |
动态分析 | X32dbg、windbg |
静态分析 | IDAPRO |
漏洞软件 | Microsoft Word 2007 SP3(打上kb4011604补丁)中的EQNEDT32.EXE |
Office分析工具 | OffVis、OleFileView、rtfobj.py |
利用MSF生成弹计算器的样本后用010editor将EQNEDT32.EXE的ALSR的开启标志位更改,用Windbg附加正在运行的EQNEDT32.EXE下WinExec
的API断点,然后双击运行样本,断下后查看调用堆栈和寄存器。
发现返回地址是410c18,而eax=410c12,查看该处反汇编。
基本上可以确定是通过栈溢出的jmp eax 或者是 call eax来跳转的。
继续查看上层函数调用返回地址是0043b463 ,在IDA中静态查看。
发现调用的函数是sub_4214C6。使用x32Dbg在该函数内部下断,发现步过sub_421774函数时弹出了计算器。
初步确认,在sub_421774函数中发生了栈溢出破坏了sub_421774函数的返回地址。
对sub_421774的返回地址下硬件写入断点,运行后发现在sub_421E39里面断下,发现是对传进的字体结构体tagLOGFONT
的字体名进行拷贝的时候没有对长度进行校验而导致的栈溢出。
tagLOGFONT
的结构。
这是微软对产生栈溢出的字段的解释,说明该字符串的大小是32,类型或者是CHAR或者是Wchar,以NULL结尾。
于是乎我查看为什么本函数的拷贝能够导致父函数的栈溢出,发现sub_421E39这个函数的第一参数是来自父函数sub_421774的第一参数,那么就能够导致在拷贝的时候产生覆盖父函数的返回地址而导致栈溢出。
但是在查看该函数的时候发现一个疑惑,sub_421774该函数可能存在无限递归调用的可能性么?只要a3=1,那么必定会产生多次递归调用sub_421774,查询a3来源,发现是sub_421774的第三个参数。
然后查看第一次a3的来源,发现第一次调用a3来自sub_4214C6,此时a3必定=1,肯定会产生一次递归调用自身。
然后查询第二次调用来源,发现第二次调用肯定为0。那么便不用担心可能存在的多次递归调用了。
可是问题是,实际的环境中是存在ASLR的,栈溢出是如何突破ASLR而准确跑到栈上来的呢?
找到复制到栈上的数据,该数据是 OLE 对象的“Equation Native”的数据流中的,这个地方同样导致CVE-2017-11882的发生,带上NULL字符总大小为0x96.
拷贝的地址是[ebp+0x10]中的地址+0x1c = 12F2D0,也就到了sub_421774的栈空间中去,而此时距离sub_421774的返回地址12F364只差0x94个字节.96个字节正好可以覆盖低两字节。
可以看到拷贝的数据带上NULL正好修改了函数sub_421774的返回地址低两个字节,为2500,因为模块加载基址的变化不可能导致偏移也发生变化,而模块加载基址一般都是不变化后两字节的,这样就突破了ASLR。
那么查看该返回地址为一个ret所在地址,在该ret返回后来到了栈上的地址,该地址也就是传给sub_421774的第一个参数,而微软的补丁只是加了ALSR,并没有加DEP,所以导致栈上的地址可执行。
然后就是执行栈上的shellcode了,shellcode中push了真正要执行的命令字符串,获取了sub_4214C6函数的返回地址,然后将该返回地址减去偏移A851,得到了CALL Winexec的地址,然后jmp过去了执行了。
在该漏洞利用中有两个特别凑巧的条件缺一不可,第一个条件就是要在本模块中找到一条ret指令地址的偏移是00XX的形式的,如果没有的话,字符串拷贝以NULL结束就不好利用了;第二个条件就是sub_421774第一个参数凑巧是我们可控的栈上的地址lpLogFont;如果没有这两个条件或者是开启了数据执行保护,这个漏洞都将变得难以利用。
[公告]安全测试和项目外包请将项目需求发到看雪企服平台:https://qifu.kanxue.com
最后于 23小时前 被不懂就不懂编辑 ,原因: