首页
论坛
专栏
课程

[原创]Microsoft RTF栈溢出漏洞分析(CVE-2010-3333)

2019-4-15 20:27 2536

[原创]Microsoft RTF栈溢出漏洞分析(CVE-2010-3333)

2019-4-15 20:27
2536

1.APT攻击事件

每当出现一些热点事件,黑客总会借此当做诱饵,将一些包含热点新闻的恶意文档通过邮件等方式发送给受害者,用户在未知情况下,打开恶意文档就会执行恶意文档中的恶意代码,在受害者主机上植入恶意木马,并借此监视受害者,控制受害者计算机,甚至窃取受害者资料。

在“林疯狂”时期,趋势科技公司捕获到APT文档,该恶意文档主要利用CVE-2010-3333漏洞,通过邮件以附件形式发送给受害者打开附件,在受害者者计算机上植入恶意程序,然后通过C&C服务器进行通信和控制,并将窃取的敏感信息回传到C&C服务器上。


2.漏洞描述

Microsoft Office XP SP3,Office 2003 SP3,Office 2007 SP2,Office 2010等多个版本的Office软件中的Open XML文件格式转换器存在栈溢出漏洞,主要是在处理RTF中的“pFragments”属性时存在栈溢出,导致远程攻击者可以借助特制的RTF数据执行任意代码,因此又称之为“RTF栈缓冲区溢出漏洞”。


3.分析环境

操作系统:Windows XP SP3

调试器:Windbg

反汇编器:IDA Pro

漏洞软件:Microsoft Office Word(2003 SP3)


4.RTF文件格式

RTF(Rich Text Format)格式是Microsoft公司为进行文本和图像信息格式的交换而制定的一种文件格式,它适用于不同的设备和操作系统,RTF文件的基本元素是正文(Text),控制字(Control Word),控制符号(Control Symbol)和群组(Group)


1.{\rtf1\ansi\ansicpg936\deff0\deflang1033\deflangfe2052{\fonttbl{\f0\fnil\fcharset134 \'cb\'ce\'cc\'e5;}}
2.{\colortbl ;\red255\green255\blue0;\red255\green0\blue0;\red0\green0\blue255;}
3.{\viewkind4\uc1\pard\cf1\lang2052\f0\fs20 Osamu\cf2  Naga\cf0 y\cf3 am\cf0 a,\par
was unable to pinpoint.//PRD#
\cf1 OQS\par it \cf0 signed a \cf1 definitive\cf0  agreement\par \par }

fcd格式说明

第一行


{\rtf1\ansi\ansicpg936\deff0\deflang1033\deflangfe2052{\fonttbl{\f0\fnil\fcharset134 \'cb\'ce\'cc\'e5;}}

‘;;’rtf1–>RTF版本 
ansi–> 字符集 
ansicpg936–>简体中文 
deff0–>默认字体0 
deflang1033–>美国英语 
deflangfe2052–>中国汉语 
fonttb–>字体列表 
f0->字体0 
fcharset134 ->GB2312国标码 
‘cb\’ce\’cc\’e5–>宋体 
引用方式 f0

第二行

{\colortbl ;\red255\green255\blue0;\red255\green0\blue0;\red0\green0\blue255;}
\colortbl 颜色表 ;颜色1;颜色2;颜色3; 
引用方式 cf1 cf2 cf3

第三行

\viewkind4\uc1\pard\cf1\lang2052\f0\fs20 Osamu\cf2  Naga\cf0 y\cf3 am\cf0 a,\par
\viewkind4正常视图 
uc1->单字节 
pard->默认段落属性 
cf1->颜色1 
lang->2052中国汉语 
f0->字体0 
fs20->字体大小20磅 
Osamu Naga 原文 
\cf0 默认颜色 
y 
\cf2 颜色2 
am\ 
\cf0默认颜色 a, 
\par换行

看看EXP中的部分数据:



5.基于栈回溯的漏洞分析方法

首先通过Metasploit生成可触发漏洞的POC样本,特别是一些经典漏洞,Metasploit上会提供利用代码,通过它可以直接生成样本以供分析漏洞,通过Metasploit获取样本一直是漏洞分析人员的不二选择。

利用search搜索cve-2010-3333相关的的漏洞利用代码




利用use命令指定exploit,并用info命令生成关于此exploit的相关信息,包括:参数值,漏洞描述,参考资料





我们主要的目的是分析漏洞成因,因此选择可触发崩溃的POC样本,直接通过set命令即可设置target参数值,漏洞描述,





获取样本后,打开WINWORD.exe,用WinDbg附加进程,然后选择打开msf.rtf文件,触发异常:

(ee0.e34): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0000c8ac ebx=05000000 ecx=0000019b edx=00000000 esi=1104c24c edi=00130000
eip=30e9eb88 esp=00123d98 ebp=00123dd0 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Program Files\Common Files\Microsoft Shared\office11\mso.dll - 
mso!Ordinal6426+0x64d:
30e9eb88 f3a5            rep movs dword ptr es:[edi],dword ptr [esi]

0:000> db esi
1104c24c  4c 74 36 4c 74 37 4c 74-38 4c 74 39 4c 75 30 4c  Lt6Lt7Lt8Lt9Lu0L
1104c25c  75 31 4c 75 32 4c 75 33-4c 75 34 4c 75 35 4c 75  u1Lu2Lu3Lu4Lu5Lu
1104c26c  36 4c 75 37 4c 75 38 4c-75 39 4c 76 30 4c 76 31  6Lu7Lu8Lu9Lv0Lv1
1104c27c  4c 76 32 4c 76 33 4c 76-34 4c 76 35 4c 76 36 4c  Lv2Lv3Lv4Lv5Lv6L
1104c28c  76 37 4c 76 38 4c 76 39-4c 77 30 4c 77 31 4c 77  v7Lv8Lv9Lw0Lw1Lw
1104c29c  32 4c 77 33 4c 77 34 4c-77 35 4c 77 36 4c 77 37  2Lw3Lw4Lw5Lw6Lw7
1104c2ac  4c 77 38 4c 77 39 4c 78-30 4c 78 31 4c 78 32 4c  Lw8Lw9Lx0Lx1Lx2L
1104c2bc  78 33 4c 78 34 4c 78 35-4c 78 36 4c 78 37 4c 78  x3Lx4Lx5Lx6Lx7Lx

0:000> db esp
00123d98  f0 10 4d 01 88 3f 12 00-96 cc f4 30 f0 10 4d 01  ..M..?.....0..M.
00123da8  c0 3d 12 00 00 00 00 00-00 00 00 00 00 00 00 00  .=..............
00123db8  00 00 00 00 78 a8 5c 59-41 61 30 41 61 31 41 61  ....x.\YAa0Aa1Aa
00123dc8  32 41 61 33 41 61 34 41-61 35 41 61 36 41 61 37  2Aa3Aa4Aa5Aa6Aa7
00123dd8  41 61 38 41 61 39 41 62-30 41 62 31 41 62 32 41  Aa8Aa9Ab0Ab1Ab2A
00123de8  62 33 41 62 34 41 62 35-41 62 36 41 62 37 41 62  b3Ab4Ab5Ab6Ab7Ab
00123df8  38 41 62 39 41 63 30 41-63 31 41 63 32 41 63 33  8Ab9Ac0Ac1Ac2Ac3
00123e08  41 63 34 41 63 35 41 63-36 41 63 37 41 63 38 41  Ac4Ac5Ac6Ac7Ac8A

0:000> db edi
00130000  41 63 74 78 20 00 00 00-01 00 00 00 b8 24 00 00  Actx ........$..
00130010  c4 00 00 00 00 00 00 00-20 00 00 00 00 00 00 00  ........ .......
00130020  14 00 00 00 01 00 00 00-06 00 00 00 34 00 00 00  ............4...
00130030  14 01 00 00 01 00 00 00-00 00 00 00 00 00 00 00  ................
00130040  00 00 00 00 00 00 00 00-00 00 00 00 02 00 00 00  ................
00130050  00 00 00 00 00 00 00 00-00 00 00 00 14 02 00 00  ................
00130060  9c 01 00 00 00 00 00 00-5b 49 59 2d b0 03 00 00  ........[IY-....
00130070  32 00 00 00 e4 03 00 00-d2 02 00 00 00 00 00 00  2...............

lmm命令查看mso模块的详细信息

0:000> lmm mso v
start    end        module name
30c90000 31837000   mso        (export symbols)       C:\Program Files\Common Files\Microsoft Shared\office11\mso.dll
    Loaded symbol image file: C:\Program Files\Common Files\Microsoft Shared\office11\mso.dll
    Image path: C:\Program Files\Common Files\Microsoft Shared\office11\mso.dll
    Image name: mso.dll
    Timestamp:        Fri Aug 08 15:10:06 2003 (3F334CCE)
    CheckSum:         00BA7175
    ImageSize:        00BA7000
    File version:     11.0.5606.0
    Product version:  11.0.5606.0
    File flags:       0 (Mask 3F)
    File OS:          40004 NT Win32
    File type:        2.0 Dll
    File date:        00000000.00000000
    Translations:     0000.04e4
    CompanyName:      Microsoft Corporation
    ProductName:      Microsoft Office 2003
    InternalName:     MSO
    OriginalFilename: MSO.DLL
    ProductVersion:   11.0.5606
    FileVersion:      11.0.5606
    FileDescription:  Microsoft Office 2003 component
    LegalCopyright:   Copyright © 1983-2003 Microsoft Corporation.  All rights reserved.

这是mso.dll上的一处栈溢出漏洞,由于在循环复制内存数据到栈空间时,未检测复制的内存大小,导致覆盖到edi(0x00130000)这个只读内存地址,最后造成访问违例。

触发异常的指令地址0x30e9eb88位于函数sub_30ED4406中,暂且标记为CrashFun函数,用Windbg重新加载程序运行,在0x30e9eb88上下断点,然后打开rtf文件运行后断下:



0:004> bp 0x30e9eb88
*** 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: 76d70000 76d92000   C:\WINDOWS\system32\appHelp.dll
ModLoad: 76590000 765de000   C:\WINDOWS\System32\cscui.dll
ModLoad: 76570000 7658c000   C:\WINDOWS\System32\CSCDLL.dll
ModLoad: 5fdd0000 5fe25000   C:\WINDOWS\system32\netapi32.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 76673000   C:\WINDOWS\system32\CRYPT32.dll
ModLoad: 76db0000 76dc2000   C:\WINDOWS\system32\MSASN1.dll
ModLoad: 75430000 754a1000   C:\WINDOWS\system32\CRYPTUI.dll
ModLoad: 76680000 76726000   C:\WINDOWS\system32\WININET.dll
ModLoad: 76c00000 76c2e000   C:\WINDOWS\system32\WINTRUST.dll
ModLoad: 76c60000 76c88000   C:\WINDOWS\system32\IMAGEHLP.dll
ModLoad: 76f30000 76f5c000   C:\WINDOWS\system32\WLDAP32.dll
ModLoad: 76950000 76958000   C:\WINDOWS\system32\LINKINFO.dll
ModLoad: 325c0000 325d2000   C:\Program Files\Microsoft Office\OFFICE11\msohev.dll
ModLoad: 36c30000 36c39000   C:\Program Files\Microsoft Office\OFFICE11\msostyle.dll
ModLoad: 39800000 399b3000   C:\Program Files\Microsoft Office\OFFICE11\GdiPlus.DLL
ModLoad: 76f20000 76f28000   C:\WINDOWS\system32\WTSAPI32.DLL
ModLoad: 762d0000 762e0000   C:\WINDOWS\system32\WINSTA.dll
Breakpoint 0 hit
eax=0000c8ac ebx=05000000 ecx=0000322b edx=00000000 esi=1104000c edi=00123dc0
eip=30e9eb88 esp=00123d98 ebp=00123dd0 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]
注意:edi=00123dc0

断下后,查看栈回溯,以定位是哪个函数调用到崩溃函数的:

0:000> kb
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
00123dd0 30f4cdbd 00123f3c 00000000 ffffffff mso!Ordinal6426+0x64d
00123e00 30f4a597 00123f88 00123f3c 00000000 mso!Ordinal753+0x306e
0012404c 30d4b199 00000000 0012408c 00000000 mso!Ordinal753+0x848
00124074 30d4b148 30d4ae32 014d14c8 014d1500 mso!Ordinal4196+0x61f
00124078 30d4ae32 014d14c8 014d1500 014d13b0 mso!Ordinal4196+0x5ce
0012407c 014d14c8 014d1500 014d13b0 30dc9d44 mso!Ordinal4196+0x2b8
00124080 014d1500 014d13b0 30dc9d44 00000000 0x14d14c8
00124084 014d13b0 30dc9d44 00000000 014d1118 0x14d1500
00124088 30dc9d44 00000000 014d1118 00124e38 0x14d13b0
0012408c 00000000 014d1118 00124e38 00000000 mso!Ordinal2940+0x158fc
注意:mso!Ordinal753+0x306e
0:000> ub mso!Ordinal753+0x306e
mso!Ordinal753+0x305a:
30f4cda9 23c1            and     eax,ecx
30f4cdab 50              push    eax
30f4cdac 8d47ff          lea     eax,[edi-1]
30f4cdaf 50              push    eax
30f4cdb0 8b4508          mov     eax,dword ptr [ebp+8]
30f4cdb3 6a00            push    0
30f4cdb5 ff750c          push    dword ptr [ebp+0Ch]
30f4cdb8 e8a0feffff      call    mso!Ordinal753+0x2f0e (30f4cc5d)
注意:call    mso!Ordinal753+0x2f0e (30f4cc5d)

由上可知,CrashFun函数是在0x30f4cc5d函数中被调用的,重新用windbg加载进程,并在0x30f4cc5d下断点,打开rtf文件,运行后断下:

0:004> bp 0x30f4cc5d
*** 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: 76d70000 76d92000   C:\WINDOWS\system32\appHelp.dll
ModLoad: 76590000 765de000   C:\WINDOWS\System32\cscui.dll
ModLoad: 76570000 7658c000   C:\WINDOWS\System32\CSCDLL.dll
ModLoad: 5fdd0000 5fe25000   C:\WINDOWS\system32\netapi32.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 76673000   C:\WINDOWS\system32\CRYPT32.dll
ModLoad: 76db0000 76dc2000   C:\WINDOWS\system32\MSASN1.dll
ModLoad: 75430000 754a1000   C:\WINDOWS\system32\CRYPTUI.dll
ModLoad: 76680000 76726000   C:\WINDOWS\system32\WININET.dll
ModLoad: 76c00000 76c2e000   C:\WINDOWS\system32\WINTRUST.dll
ModLoad: 76c60000 76c88000   C:\WINDOWS\system32\IMAGEHLP.dll
ModLoad: 76f30000 76f5c000   C:\WINDOWS\system32\WLDAP32.dll
ModLoad: 76950000 76958000   C:\WINDOWS\system32\LINKINFO.dll
ModLoad: 325c0000 325d2000   C:\Program Files\Microsoft Office\OFFICE11\msohev.dll
ModLoad: 36c30000 36c39000   C:\Program Files\Microsoft Office\OFFICE11\msostyle.dll
ModLoad: 39800000 399b3000   C:\Program Files\Microsoft Office\OFFICE11\GdiPlus.DLL
ModLoad: 76f20000 76f28000   C:\WINDOWS\system32\WTSAPI32.DLL
ModLoad: 762d0000 762e0000   C:\WINDOWS\system32\WINSTA.dll
Breakpoint 0 hit
eax=00123f88 ebx=00000000 ecx=00123dfc edx=00000000 esi=00000000 edi=00000000
eip=30f4cc5d esp=00123dd4 ebp=00123e00 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单步跟踪:

0:000> p
eax=00123f88 ebx=00000000 ecx=00123dfc edx=00000000 esi=00000000 edi=00000000
eip=30f4cc5e esp=00123dd0 ebp=00123e00 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+0x2f0f:
30f4cc5e 8bec            mov     ebp,esp
0:000> p
eax=00123f88 ebx=00000000 ecx=00123dfc edx=00000000 esi=00000000 edi=00000000
eip=30f4cc60 esp=00123dd0 ebp=00123dd0 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+0x2f11:
30f4cc60 83ec14          sub     esp,14h
注意: sub     esp,14h

这里该函数开辟了0x14字节大小的栈空间,继续跟踪下去,当运行到0x30f4cc93时就调用到了Crash_Fun函数sub_30e9eb62进行内存数据复制:

0:000> p
eax=30d9ed10 ebx=05000000 ecx=00123dc0 edx=00000000 esi=014d10f0 edi=00123f88
eip=30f4cc93 esp=00123da4 ebp=00123dd0 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+0x2f44:
30f4cc93 ff501c          call    dword ptr [eax+1Ch]  ds:0023:30d9ed2c=30e9eb62
注意:30e9eb62

F8跟入CrashFun函数,然后单步跟踪进去,可以发现rep movs指令复制内存时,ecx的值为0000c8ac,也就是复制数据的大小,由于是操作dword字节,因此需要再除以4(逻辑右移2位):

0:000> p
eax=0000c8ac ebx=05000000 ecx=0000c8ac edx=00000000 esi=1104000c edi=00123dc0
eip=30e9eb85 esp=00123d98 ebp=00123dd0 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=00123dc0
eip=30e9eb88 esp=00123d98 ebp=00123dd0 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]
注意: ecx=0000c8ac       ecx=0000322b 

回头看下msf.rtf样本数据,可以发现上面的0x0000c8ac其实是源于样本数据的,它位于pFragements属性值的第三个字段,偏移8个字符后的4个字符就是复制的数据大小:



而0xc8ac后面的数据正是实际内存复制的数据,复制内存原地址esi刚好指向这里:

0:000> db esi
1104000c  41 61 30 41 61 31 41 61-32 41 61 33 41 61 34 41  Aa0Aa1Aa2Aa3Aa4A
1104001c  61 35 41 61 36 41 61 37-41 61 38 41 61 39 41 62  a5Aa6Aa7Aa8Aa9Ab
1104002c  30 41 62 31 41 62 32 41-62 33 41 62 34 41 62 35  0Ab1Ab2Ab3Ab4Ab5
1104003c  41 62 36 41 62 37 41 62-38 41 62 39 41 63 30 41  Ab6Ab7Ab8Ab9Ac0A
1104004c  63 31 41 63 32 41 63 33-41 63 34 41 63 35 41 63  c1Ac2Ac3Ac4Ac5Ac
1104005c  36 41 63 37 41 63 38 41-63 39 41 64 30 41 64 31  6Ac7Ac8Ac9Ad0Ad1
1104006c  41 64 32 41 64 33 41 64-34 41 64 35 41 64 36 41  Ad2Ad3Ad4Ad5Ad6A
1104007c  64 37 41 64 38 41 64 39-41 65 30 41 65 31 41 65  d7Ad8Ad9Ae0Ae1Ae

复制内存的目标地址edi刚好偏移栈底ebp共0x10字节,加上ebp本身占用的4字节,刚好一共0x14字节,在覆盖下去就是函数的返回地址了:

0:000> ? ebp-edi
Evaluate expression: 16 = 00000010

由于msf.rtf中复制的内存数据较大,导致复制的过程中覆盖到不可写的内存地址而触发异常,因此没有去执行覆盖到的返回地址或者SEH中的异常处理函数

总结上面的分析过程,由于Word中的RTF分析器在解析pFragment属性值时,没有正确计算属性值所占用的空间大小,只要复制的数据大小超过0x14字节即可覆盖到返回地址,若继续覆盖下去还可以覆盖到SEH结构,进而控制程序的执行流程,用于执行任意代码。

6.漏洞利用

将漏洞成因分析清楚后,利用该漏洞还是比较容易的,只需将返回地址用jmp esp指令地址覆盖,也就是复制数据的大小的值之后再偏移0x14字节,就可以覆盖到返回地址;然后将shellcode放置到后面,就可以执行任意代码。

由于在漏洞函数的结尾处,它在返回时会弹出0x14大小的栈空间,因此我们在jmp esp中填充一些垃圾字节以此来填充这一空缺

某个实际病毒样本的分析情况:






当漏洞函数返回后,会先从栈顶弹出0x14字节空间,然后执行0x7d1f5fb7处的JMP ESP指令,进而跳入shellcode的起始地址,导致执行任意代码

除了利用jmp esp覆盖返回地址的方法,还可以利用jmp 06+ pop pop ret指令地址覆盖SEH结构,也同样可以达到溢出利用的目的。


7.Office 2003与 Office 2007 Exploit通用性研究

上面例子中的0x7d1f5fb7指令地址并不稳定,这种硬编码地址可能受到软件和系统版本影响,较难实现通用性利用,为了实现Office 2003和Office 2007的通用性利用,我们可以在返回地址上用0x0026762f覆盖,它在Office 2003上相当于call esp指令:


0:000> u 0x0026762f l1
0026762f ffd4    call esp


该地址适用于Office 2003 SP0和SP3等各个子版本,属于稳定的跳转地址,对于Office 2007,0x0026762f上已经不再是call/jmp es等类似指令,当我们用0x0026762f这个地址覆盖Office 2007上的返回地址,只要能够让它触发异常,就可以执行SEH结构。

这样的话,只需要加大内存拷贝的大小,使其覆盖醉经的SEH结构就可以劫持EIP,也就是说,我们需要同时覆盖返回地址和SEH结构

构造覆盖栈的数据如下,长度为0x2a18:


111111111111111111111111111111111111111111111111111111111111112f762600111111111111111111111111111111111111111111111111111111111111aaaaaaaaffffffff


关于SEH结构地址的定位,可以使用MSF上的两个工具:pattern_create和pattern_offset定位偏移量

8.漏洞修复

下载补丁后,提取安装后的mso.dll文件和未打补丁之前的mso.dll进行补丁比较,就可以找到针对漏洞的修复方法,首先用ID分别加载上面两个dll文件,点击保存按钮就会在当前目录下生成相应的idb文件,然后用BinDiff插件比对这两个idb文件,然后打开其中一个idb文件(直接拖入IDA),按“ctrl+6”单击“Diff Database”按钮,在弹出的对话框中选择另一个idb文件,之后BinDiff就会对这两个Dll进行补丁比较:




选择“Matched Functions”匹配函数进行对比,其中“similarity”一列代表函数的相似度,通常漏洞函数修改不会太大,多数在0.7~0.9之间,而且在“change”一列中大多数带有G标志,也就是图表视图发生了改变

之前已经分析过漏洞成因,漏洞函数位于unpatch_mso.dll中的0x30f0b5c2,因此直接定位此函数和patch_mso.dll中的匹配函数0x30f39832的对比情况:




.text:30F39832                 push    ebp
.text:30F39833                 mov     ebp, esp
.text:30F39835                 sub     esp, 14h
.text:30F39838                 cmp     [ebp+arg_10], 0
.text:30F3983C                 push    edi
.text:30F3983D                 mov     edi, eax
.text:30F3983F                 jz      loc_31093EC1
.text:30F39845                 mov     ecx, [edi+8]
.text:30F39848                 push    ebx
.text:30F39849                 push    esi
.text:30F3984A                 call    sub_30D2AC85
.text:30F3984F                 mov     esi, [eax+64h]
.text:30F39852                 and     [ebp+var_8], 0
.text:30F39856                 test    esi, esi
.text:30F39858                 mov     ebx, 5000000h
.text:30F3985D                 mov     [ebp+var_C], ebx
.text:30F39860                 jz      loc_30F36F2E
.text:30F39866                 mov     eax, [esi]
.text:30F39868                 push    esi
.text:30F39869                 call    dword ptr [eax+30h] ; 获取复制的内存大小size
.text:30F3986C                 cmp     eax, 4
.text:30F3986F                 ja      loc_30F36F2E    ; 若size > 4 则跳转,并清零后返回
.text:30F39875                 mov     eax, [esi]
.text:30F39877                 push    esi
.text:30F39878                 call    dword ptr [eax+2Ch]
.text:30F3987B                 cmp     eax, dword ptr [ebp+arg_4+4]
.text:30F3987E                 jle     loc_30F36F2E
.text:30F39884                 mov     eax, [esi]
.text:30F39886                 push    esi
.text:30F39887                 call    dword ptr [eax+2Ch]
.text:30F3988A                 cmp     eax, dword ptr [ebp+arg_4]
.text:30F3988D                 jle     loc_30F36F2E
.text:30F39893                 cmp     dword ptr [ebp+arg_4], 0
.text:30F39897                 jl      loc_30F36F2E
.text:30F3989D                 cmp     dword ptr [ebp+arg_4+4], 0
.text:30F398A1                 jl      loc_30F36F2E
.text:30F398A7                 push    dword ptr [ebp+arg_4]
.text:30F398AA                 mov     eax, [esi]
.text:30F398AC                 lea     ecx, [ebp+var_10]
.text:30F398AF                 push    ecx             ; 复制内存大小
.text:30F398B0                 push    esi
.text:30F398B1                 call    dword ptr [eax+1Ch] ; CrashFun
.text:30F398B4                 mov     eax, [ebp+arg_C]
.text:30F398B7                 push    [ebp+arg_10]
.text:30F398BA                 mov     edx, [ebp+var_10]
.text:30F398BD                 neg     eax
.text:30F398BF                 sbb     eax, eax
.text:30F398C1                 lea     ecx, [ebp+var_8]
.text:30F398C4                 and     eax, ecx
.text:30F398C6                 push    eax
.text:30F398C7                 push    [ebp+arg_0]
.text:30F398CA                 call    sub_30F39A68
.text:30F398CF                 test    al, al
.text:30F398D1                 jz      loc_30F36F2E
.text:30F398D7                 mov     eax, [ebp+var_8]
.text:30F398DA                 test    eax, eax
.text:30F398DC                 jnz     loc_30F36E93

最后生成下图所示的函数对比图:



为了更加方便的显示具体的代码行,我将修复前后的两个函数的反汇编代码复制出来,然后用TextDiff进行比较:



通过指令分析可以知道,漏洞主要是在复制内存时未检测复制内存的大小导致的栈溢出,在执行rep movs指令时,控制复制内存大小的是ecx寄存器,因此我们在分析中主要关注ecx的变化,看微软是否对其大小做了检查





红色部分就是微软在漏洞函数中加入的内容, 但是上面补丁后的代码并没有看到有检测复制内存大小的行为,因此我们可以认为检测内存大小的函数位于上面某个调用函数中,但是里面调用的函数都是通过eax偏移来索引的,不便于静态分析,要动态调试来分析

用Windbg加载打补丁后的WINWORD.exe,在漏洞修函数0x30f39832上下断点,先用未打补丁的WINWORD.exe看一下:


(378.328): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0000c8ac ebx=05000000 ecx=0000019b edx=00000000 esi=1104c24c edi=00130000
eip=30e9eb88 esp=00123d98 ebp=00123dd0 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
mso!Ordinal6426+0x64d:
30e9eb88 f3a5            rep movs dword ptr es:[edi],dword ptr [esi]


单步跟下去,直到call dword ptr [eax+30h],然后跟入:


0:000> t
eax=0000c8ac ebx=00123ab0 ecx=00123acc edx=00000000 esi=1104c24c edi=00130000
eip=7c94a950 esp=00123a9c ebp=00123dd0 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ntdll!towlower+0x12a:
7c94a950 8bff            mov     edi,edi
0:000> t
eax=0000c8ac ebx=00123ab0 ecx=00123acc edx=00000000 esi=1104c24c edi=00130000
eip=7c94a952 esp=00123a9c ebp=00123dd0 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
ntdll!towlower+0x12c:
7c94a952 55              push    ebp


获取复制内存大小


0:000> t
eax=0000c8ac ebx=00123ab0 ecx=00123acc edx=00000000 esi=00123ab0 edi=00130000
eip=7c94a964 esp=00123a28 ebp=00123a98 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ntdll!towlower+0x13e:
7c94a964 e8abffffff      call    ntdll!towlower+0xee (7c94a914)


样本中代表复制内存大小的0xc8ac,若size>4则跳转,并清零后返回


0:000> t
eax=0000c8ac ebx=00123ab0 ecx=00123acc edx=00000000 esi=00123ab0 edi=7c99b3c0
eip=7c94a921 esp=00123a14 ebp=00123a20 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ntdll!towlower+0xfb:
7c94a921 393dc0b3997c    cmp     dword ptr [ntdll!NlsMbOemCodePageTag+0x318 (7c99b3c0)],edi ds:0023:7c99b3c0=7c99b3c0
0:000> t
eax=0000c8ac ebx=00123ab0 ecx=00123acc edx=00000000 esi=00123ab0 edi=7c99b3c0
eip=7c94a927 esp=00123a14 ebp=00123a20 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!towlower+0x101:
7c94a927 0f85cc7c0100    jne     ntdll!RtlDeleteAce+0xa4d8 (7c9625f9)   [br=0]
0:000> t
eax=0000c8ac ebx=00123ab0 ecx=00123acc edx=00000000 esi=00123ab0 edi=7c99b3c0
eip=7c94a92d esp=00123a14 ebp=00123a20 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!towlower+0x107:
7c94a92d 32c0            xor     al,al
0:000>
eax=0000c800 ebx=00123ab0 ecx=00123acc edx=00000000 esi=00123ab0 edi=7c99b3c0
eip=7c94a92f esp=00123a14 ebp=00123a20 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!towlower+0x109:
7c94a92f 5f              pop     edi
0:000> t
eax=0000c800 ebx=00123ab0 ecx=00123acc edx=00000000 esi=00123ab0 edi=00130000
eip=7c94a930 esp=00123a18 ebp=00123a20 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!towlower+0x10a:
7c94a930 c9              leave
0:000> t
eax=0000c800 ebx=00123ab0 ecx=00123acc edx=00000000 esi=00123ab0 edi=00130000
eip=7c94a931 esp=00123a24 ebp=00123a98 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!towlower+0x10b:
7c94a931 c20800          ret     8


微软在修复CVE-2010-3333漏洞时,主要通过检测RTF文件中的pFragments属性值的大小是否大于4字节,若大于则跳走并且返回,不再进行内存复制,从而解决了栈溢出问题


参考信息:泉哥《漏洞战争》






[公告]LV6级以上的看雪会员可以免费获得《2019安全开发者峰会》门票一张!!

最新回复 (0)
游客
登录 | 注册 方可回帖
返回