CVE-2018-0802 Microsoft Office stack overflow 漏洞分析
文章目录
环境
- win7 x64 + x32dbg
- IDA
- oletools
此漏洞是在CVE-2017-11882补丁基础上触发的,所以需要把EQNEDT32.exe换成打了补丁的版本。微软的补丁下载地址不知为什么404了,我用的是这篇文章分享的文件。
分析
溯源
参考上一篇文章(本blog中的CVE-2017-11882分析)设置注册表、关闭aslr。
打开样本文件cve-2018-0802.rtf,跳过断点发现直接弹了计算器。
在winexec处下断点发现能断下
通过调用堆栈找到00430c12处调用了winexec
虽然通过其他公开的分析文章可以知道漏洞点在哪,但是还是尝试通过蛛丝马迹来寻找
此时继续往上追溯并不顺利,可能是在shellcode执行过程中把堆栈和调用栈搞乱掉了。
我的方法是根据堆栈和调用栈上的返回地址一个个试,比如下图中体现出来的可能是call 421c4b的过程中程序流程被劫持了,也就是说运行不到下一句了,于是我就在call和call的下一句分别打上“条件打印断点”。
在断点页面编辑断点,使得在call的时候打印“start”,call之后打印“end"
重新打开一次,一直f9运行结束,查看log发现start和end都是成对出现的,说明不是421c4b
按照上述方法,分别又试了421ff4、44c430、4214c6,发现只有call 4214c6的调用是没有返回的(这里的call只走到了一次)。
这里不要在4214c6里面下断点,因为call 4214c6的地方走到了一次,而4214c6自身可能被其他地方调用,可能在错误的时间点断下。
在call 4214c6的地方下断点,f7进去,用单步跳过的方法发现执行call 421774后程序跳到exec,那就继续调试这个函数。
函数较长,调试方法参考上篇文章
最后找到了是在函数421e39里面改变了421774的返回地址。发生的原因是没有检查第一个参数字符串的长度,而复制目的地是421774中的栈变量ebp-AC,复制长度过长就会覆盖返回地址。
调试这段复制过程会发现421774的返回地址只被覆盖了低位两个字节,从004214e2变成00420025,这么做是为了绕过aslr,而00420025地址处是一个ret指令,这就会把执行流程带到栈上。
先是把esp减小了0x200(18f30c->18f10c),之后call 18f35e, 这个跳转使得ret没了,变成了inc ebx,程序继续往下执行,执行到jmp eax时eax指向winexec,后面就是弹计算器了。
shellcode分析
这段shellcode很有意思,仔细看看。
- shellcode从0018f350开始
- 在0018f358处把esp减小0x200
- 在0018f35A处有指令
E8 FFFFFFFF
,e8表示相对下一条指令地址跳转,这里即0xffffffff+0x18f35f=0x18f35e ,所以是call 18f35e
(🙃这么做的作用是“自定位”,call会把下一指令压入栈中,后面就可以根据这个地址加上偏移来定位) - 18f35e处的指令是
FFC3
, 被解释为inc ebx
,这样ret就被”吃掉了“,程序会继续向下执行
- 0018f360处pop ebx把call跳转之前的地址(18f35f)放入ebx中,注意在后面jmp eax之前压入的最后一个值是ebx+1c(18f37b),这是提前计算过的,恰恰指向那段cmd.exe命令
-
0018f361处把0压栈,作为后面winexec的第二个参数
-
0018f362和0018f366处获取程序的基址。 FS寄存器指向当前活动线程的TEB结构,fs[30]是PEB结构地址(7efde000),PEB偏移8位是程序基址(400000)
-
后面用基址加上0x30c12得到
call winexec
的地址 -
0018f378处把”cmd.exe…“压栈
-
运行到
jmp eax
的时候,eax指向call winexec
的地址,参数也都正确。😘
此shellcode中通过相对寻址和自定位等技术,可以绕过aslr。经测试在开启ASLR后仍然能利用成功
样本
使用 rtfobj cve-2018-0802.rtf -s 0
提取rtf中的ole object。
格式说明参考上一篇文章
拖入010editor中查看,08是font name record,后面两个字节是record的标识符,不用关心,橙框部分就是shellcode
参考
文章作者 b1tg
上次更新 2020-01-15