0x01 漏洞描述
0x02 分析环境
|
|
环境
|
备注
|
|
操作系统
|
winxp sp3
|
网上下的镜像
|
|
虚拟机
|
VMware
|
版本号 15.0.2
|
|
调试器
|
ollydebug
windbg
|
|
|
反汇编器
|
IDA Pro
|
版本号:6.8
|
|
漏洞软件
|
Microsoft office word
|
版本号:2003 sp3
|
0x03 背景知识
RTF文件格式:
0x04 漏洞分析
一、 查看CVE-2010-3333样本数据
用pdfstreamdumper打开一个样本doc文件,查看该样本部分数据如下图:
二、 基于栈回溯的漏洞分析方法
-
首先,通过metasploit生成可触发漏洞的poc样本
ps:
-
漏洞分析:多喜欢用metasploit生成的漏洞样本。
-
exploit技术或shellcode技术:多分析实际的病毒样本。
由于我们分析漏洞,故target选择6
2.打开winword.exe,并用windbg附加进程,然后打开生成的样本文件msf.rtf
先用windbg附加进程
打开样本文件msf.rtf:
!address edi 报错:
解决:由于要联网下,此处未解决。
书上图片:
用lmm命令查看mso模块的详细信息
从上面分析,触发异常的指令地址为30e9eb88,原因是在mso.dll上有一处栈溢出漏洞,由于在循环复制内存数据到栈空间时,未检测复制的内存大小,导致覆盖到edi(书里的edi是0x00130000,我的由于symbol并没有出来。但从最开始的输出的edi值也可以看出来。)这个只读内存地址,最后造成访问违例。
关闭调试,重新启动,在30e9eb88 处下断点,再打开样本文件。
断下后,查看栈回溯,以定位是哪个函数调用到崩溃函数。
由于出异常的位置位于:mso!Ordinal6426+0x64d,那么查看是谁调的它,由上图可以看出是mso!Ordinal753+0x306e
查看mso!Ordinal753+0x306e
可知函数出错地址为:30f4CC5d
在30f4cc5d处下断点,重新用windbg加载进程。
0:004> bp 30f4cc5d
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files\Common Files\Microsoft Shared\office11\mso.dll -
0:004> g
ModLoad: 76060000 761b6000 C:\WINDOWS\system32\SETUPAPI.dll
ModLoad: 72f70000 72f96000 C:\WINDOWS\system32\winspool.drv
ModLoad: 095e0000 095ec000 C:\WINDOWS\System32\spool\DRIVERS\W32X86\3\mdiui.dll
ModLoad: 0a190000 0a25b000 C:\WINDOWS\System32\spool\DRIVERS\W32X86\3\mdigraph.dll
ModLoad: 75ff0000 76055000 C:\WINDOWS\system32\MSVCP60.dll
ModLoad: 76d70000 76d92000 C:\WINDOWS\system32\appHelp.dll
ModLoad: 0d870000 0d8ce000 C:\Program Files\360Safe\safemon\360UDiskGuard.dll
ModLoad: 0d8d0000 0d93d000 C:\Program Files\360sd\ShellIco.dll
ModLoad: 76c00000 76c2e000 C:\WINDOWS\system32\WINTRUST.dll
ModLoad: 765e0000 76675000 C:\WINDOWS\system32\CRYPT32.dll
ModLoad: 76db0000 76dc2000 C:\WINDOWS\system32\MSASN1.dll
ModLoad: 76c60000 76c89000 C:\WINDOWS\system32\IMAGEHLP.dll
ModLoad: 76590000 765de000 C:\WINDOWS\System32\cscui.dll
ModLoad: 76570000 7658c000 C:\WINDOWS\System32\CSCDLL.dll
ModLoad: 76960000 76984000 C:\WINDOWS\system32\ntshrui.dll
ModLoad: 76af0000 76b01000 C:\WINDOWS\system32\ATL.DLL
ModLoad: 759d0000 75a7f000 C:\WINDOWS\system32\USERENV.dll
ModLoad: 75ef0000 75fed000 C:\WINDOWS\system32\browseui.dll
ModLoad: 7e550000 7e6c1000 C:\WINDOWS\system32\shdocvw.dll
ModLoad: 765e0000 76675000 C:\WINDOWS\system32\CRYPT32.dll
ModLoad: 76db0000 76dc2000 C:\WINDOWS\system32\MSASN1.dll
ModLoad: 75430000 754a1000 C:\WINDOWS\system32\CRYPTUI.dll
ModLoad: 3e410000 3e4f7000 C:\WINDOWS\system32\WININET.dll
ModLoad: 0dbf0000 0dbf9000 C:\WINDOWS\system32\Normaliz.dll
ModLoad: 43ce0000 43e14000 C:\WINDOWS\system32\urlmon.dll
ModLoad: 3eab0000 3ec9c000 C:\WINDOWS\system32\iertutil.dll
ModLoad: 76c00000 76c2e000 C:\WINDOWS\system32\WINTRUST.dll
ModLoad: 76c60000 76c89000 C:\WINDOWS\system32\IMAGEHLP.dll
ModLoad: 76f30000 76f5c000 C:\WINDOWS\system32\WLDAP32.dll
ModLoad: 76950000 76958000 C:\WINDOWS\system32\LINKINFO.dll
ModLoad: 7de40000 7dfd9000 C:\WINDOWS\system32\NETSHELL.dll
ModLoad: 76bd0000 76bfd000 C:\WINDOWS\system32\credui.dll
ModLoad: 42e00000 42e0a000 C:\WINDOWS\system32\dot3api.dll
ModLoad: 76e50000 76e5e000 C:\WINDOWS\system32\rtutils.dll
ModLoad: 4a5c0000 4a5c6000 C:\WINDOWS\system32\dot3dlg.dll
ModLoad: 5a990000 5a9b8000 C:\WINDOWS\system32\OneX.DLL
ModLoad: 76f20000 76f28000 C:\WINDOWS\system32\WTSAPI32.dll
ModLoad: 762d0000 762e0000 C:\WINDOWS\system32\WINSTA.dll
ModLoad: 4a820000 4a842000 C:\WINDOWS\system32\eappcfg.dll
ModLoad: 582e0000 582ee000 C:\WINDOWS\system32\eappprxy.dll
ModLoad: 76d30000 76d48000 C:\WINDOWS\system32\iphlpapi.dll
ModLoad: 3eca0000 3f73d000 C:\WINDOWS\system32\ieframe.dll
ModLoad: 36c30000 36c39000 C:\Program Files\Microsoft Office\OFFICE11\msostyle.dll
ModLoad: 39800000 399b3000 C:\Program Files\Microsoft Office\OFFICE11\GdiPlus.DLL
Breakpoint 0 hit
eax=00124060 ebx=00000000 ecx=00123ed4 edx=00000000 esi=00000000 edi=00000000
eip=30f4cc5d esp=00123eac ebp=00123ed8 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
mso!Ordinal753+0x2f0e:
30f4cc5d 55 push ebp
按F10单步跟踪,当运行到 (sub_30d2810c),此处调用了出异常的函数
0:000> p
eax=00124060 ebx=00000000 ecx=00124164 edx=00000000 esi=00000000 edi=00124060
eip=30f4cc75 esp=00123e88 ebp=00123ea8 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
mso!Ordinal753+0x2f26:
30f4cc75 e892b4ddff call mso!Ordinal6594+0x596 (30d2810c)
跟进函数sub_30d2810c,继续单步,可以发现req movs指令复制内存时,ecx的值为0x0000c8ac,即复制数据大小,由于是操作dword字节,因此需要再除以4(逻辑右移2位)
0:000> p
eax=0000c8ac ebx=05000000 ecx=0000c8ac edx=00000000 esi=1104000c edi=00123e98
eip=30e9eb85 esp=00123e70 ebp=00123ea8 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
mso!Ordinal6426+0x64a:
30e9eb85 c1e902 shr ecx,2
0:000> p
eax=0000c8ac ebx=05000000 ecx=0000322b edx=00000000 esi=1104000c edi=00123e98
eip=30e9eb88 esp=00123e70 ebp=00123ea8 iopl=0 nv up ei pl nz na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206
mso!Ordinal6426+0x64d:
30e9eb88 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
回头看下msf.rtf样本数据,可以发现上面的0xc8ac其实源自于样本数据,它位于pFragements属性值的第三个字段,偏移8个字符后的四个字符即为复制的数据大小。
而0xc8ac后的数据正是实际内存复制的数据,复制内存源esi刚好指向这里。
复制内存的目标地址edi刚好偏移栈底宫0x10字节,加上ebp本身占的4个字节,刚好0x14个字节,再覆盖下去就是函数的返回地址了。
由于msf.rtf中复制的内存数据较大,导致复制过程中覆盖到不可写的内存地址而触发异常,因此没有去执行覆盖到的返回地址或SEH异常处理函数。
三、漏洞利用
采用实际病毒样本(exploit_clac.rtf)进行分析:
打开ollydebug attach到word进程上,在以下指令处下断点。
30e9eb88 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
用word打开exploit_clac.rtf,此时进程停在了我们下断点的地方,观察堆栈
可以查出此时进程准备将esi指向的内容复制到edi(00123E98)所指向的栈区,而从00123E98往下偏移20个字节即是进程正常返回地址。
继续单步执行,观察覆盖后的程序流程:
程序直接就跑完了。。。
换一个样本(Three Big Risks to China's Economy In 2011.doc)继续学习
用jmp esp指令地址覆盖返回地址
重新构造rtf:将7d1f5fb7修改为指向jmp esp的地址,进行尝试。
以下为用ollydbg的findaddr找到的jmp esp指令:
尝试7e6b1107。
用ollydbg单步跟踪,程序确实按期进行了jmp esp,流程如下:
未覆盖返回地址前的栈情况:
覆盖了返回地址的栈情况:
最后程序跑崩在:
尝试用metasploit生成可用的样本进行实验跟踪:
尝试了自动生成和xp sp3的都不行,估计是因为我机器是中文版的。
由于没有ASLR和DEP,故经过分析,将原shellcode替换成我failwest的shellcode,成功弹窗。
但是如果只是普通的打开这个文档,却不会弹窗,难道说它有调试检测机制?
其实并不是,在这个文档中我们用jmp esp的指令地址0x7e6b1107来覆盖返回地址,可是这个地址并不是很稳定,此处换成call esp指令的地址0x0026762f
成功弹窗
调试跟踪下流程查看:
解释:
用jmp esp不弹出的原因也有可能选择的指令地址在独自运行文档,即不附加调试器时是不行的,所以只能用office 2003中相当于call esp 的指令地址。
以此思路,用msfvenom生成shellcode,尝试下:
查看可用的payload
选择 windows/exec 查看其参数
生成:
然而打开文档是乱码
用-f 选择输出格式 hex(十六进制)
疑问:开始时,用windbg,代码停在30e9eb88处,就是30e9eb88 f3a5 rep movs dword ptr es:[edi],dword ptr [esi],调试时说edi指向的空间是只读,那么构造的恶意代码也应该是写不进去才对啊。
此处需要用我们成功的rtf文档,用windbg从头跟踪下流程。重点注意下几个寄存器的值。
采用payload是msfvnom生成的exec弹出计算器的那个文档,进行windbg单步跟踪,在30e9eb88处跟踪,查看相应寄存器里的值。
其实质就是合理构造payload,让它劫持进程,这就是漏洞利用!
四、Office 2003与Office 2007 Exploit通用性研究
采用“president obama。。。”样本进行学习。
用ollydebug打开,定位到“rep。。。”那条指令,单步运行,查看栈里复制情况。
复制前,esi中的情况
pFragments第三个字段,偏移八个字符就是复制的数据大小
复制前edi:00123E98
复制后edi:00124194
相差2fc,加上Dword的后三个字节即为02ff
程序在77c51025处跑崩,将其换为稳定地址0026762f还是跑崩了。然而0026762f在我之前的两篇里都是指向call esp。
疑问:如何判断指令地址的稳定性。
0x05 漏洞修复
下载官方的补丁文件mso.dll与原来的mso.dll进行比较。
用ida分别加载两个dll,并单击保存,会生成相应的idb文件。
安装bindiff插件用于比对这两个idb文件。
安装bindiff:
jdk:jre1.7
bindiff4.2
ida:6.8
①用ida打开未打补丁前的mso.dll
②打开bindiff
③单击diff database按钮,在弹出的对话框里选择我们要比较的补丁
④等待分析。。。分析结果如下(补丁函数比对)
“similarity”:代表函数相似度
“change”:大多为G标志(即 图标视图发生变化)
ps:如果补丁前后的两个函数不再“matched Functions”中,此时需要手工定位或是尝试别的补丁比较工具。
⑤由于漏洞是发生在函数30f4CC5d,故直接来查看。
先打开bindiff主程序
然后回到ida,选择view Flowgraphs
补丁前后代码对比:
结合对比图,进行动态跟踪分析
0x0S 写作后面
思路:
-
查看异常出错位置。分析出错原因。
-
回溯上层调用函数,并单步跟踪。单步跟踪时关注寄存器里的值所指代的是什么。同时关注实际文档里对应的数据。