Microsoft RTF栈溢出漏洞(CVE-2010-3333)漏洞分析

漏洞描述

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

分析环境

环境
操作系统 Windows XP SP3
虚拟机 VMware
调试器 windbg
反汇编器 IDA Pro
漏洞软件 Office 2003 SP3与2007 SP0中文版

RTF文件格式

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

控制字是RTF用来标记打印控制符和文档信息的一种特殊格式的命令,RTF用它作为正文格式的控制代码,每个控制字均以一个反斜杠开头,由a-z小写字母组成,通常应该不包含任何大写字母,而分隔符标志着控制字名称的结束。它的使用格式为:\字母序列<分隔符>

控制符号由一个反斜杠跟一个单独的非字母的字符,表示一个特定的符号

群组由包含在大括号中的文本 控制字或控制符组成。左括号表示组的开始,右括号表示组的结束。每个组包括文本和文本的不同属性。RTF文件也能同时包括字体 格式 屏幕颜色 图形 脚注 注释 文件头和文件尾 摘要信息 域和书签的组合,以及文档区段 段落和字符的格式属性

一个完整的RTF文件包括文件头<header>和文档区<document>两大部分,可以用下列的语法表示

<File>{<header><document>}

通过微软官方文档的目录,我们大体可以了解到文件头和文档区各自所包含的数据,如下所示:

Content of an RTF file
	Header
		RTF Version
		Character Set
		Unicode RTF
		Font Table
		Color Table
		Style Sheet
		List Table
		Track Changes(Revision Marks)
    Document Area
    	Information Group
    	Document Formatting Properties
    	Section Text
    	Paragraph Text
    	Character Text
    	Document Variables
    	Bookmarks
    	Pictures
    	Objects
    	Drawing Objects
    	Word 97-2000 RTF for Drawing Object(Shapes)
        Footnotes
        Comments(Annotations)
        Fields
        Form Fields
        Index Entries
        Bidrectional language Support

我们回头看下CVE-2010-3333(cve-2010-3333_exploit.doc)的部分数据,如图所示

[外链图片转存失败(img-HytgrTLN-1564825057651)(E:\博客\漏洞分析\Microsoft RTF栈溢出漏洞(CVE-2010-3333)]漏洞分析\assets\1560046133473.png)

样本数据分析如下:

\rtf1——RTF版本
\ansi——支持ANSI字符集
\shp——绘图对象
\*\shpinst———图片引用
\sp——绘图对象属性定义
\sn pFragments——定义属性名称,pFragments段是图形的附加部分 属于数组结构。它允许图形包含多个路径和分段,该属性值列出图形的各个碎片
\sv——定义属性值

RTF分析器正是在解析pFragments属性值时,没有正确计算属性值所占的空间大小,导致栈溢出漏洞的发生

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

首先打开winword.exe,接着用windbg附加进程,输入g命令直接运行。接着打开poc.rtf,此时触发异常,如下图:

在这里插入图片描述

查看一下堆栈

在这里插入图片描述

此时当前栈已经被样本生成的垃圾数据覆盖,接着用lmm命令查看mso模块的详细信息

0:000:x86> lmm mso v
start             end                 module name
30c90000 31837000   MSO        (export symbols)       MSO.DLL
    Loaded symbol image file: MSO.DLL
    Image path: 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开始的不可写页面,触发指令的地址位于0x30e9eb88位于sub_30ED4406中,我们暂且标记为CrashFun函数

此时我们重新运行windbg,在0x30e9eb88下断点,运行后让程序断下

在这里插入图片描述

断下后,查看调用堆栈,以定位到是哪个函数奔溃的

在这里插入图片描述

在这里插入图片描述

由上可知,CrashFun函数是在0x30f4cc5d函数中被调用的。重新加载windbg,并在0x30f4cc5d下断点,让程序断在0x30f4cc5d处。

在这里插入图片描述

按F10单步跟踪

在这里插入图片描述

这里开辟了0x14个字节大小的栈空间,我们继续跟踪下去

在这里插入图片描述

当运行到0x30f4cc93时,就调用到了CrashFun函数进行内存数据复制。接着按F8跟进CrashFun函数,然后一直单步

在这里插入图片描述

可以发现用rep movs指令复制内存时,ecx的值为c8ac,即复制数据的大小,由于的操作dword字节,所以需要再除以4,回头看下poc.rtf样本数据

在这里插入图片描述

可以发现上面的0xc8ac其实是源于样本数据的,它位于pFragements属性值的第三个字段,而0xc8ac后面的数据正是实际内存复制的数据,复制的内存源地址esi刚好指向这里

在这里插入图片描述

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

在这里插入图片描述

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

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

漏洞利用

将漏洞成因分析清楚之后,利用该漏洞相对还是比较容易的。我们只需要将返回地址用jmp esp指令覆盖,也就是复制数据大小的值之后再偏移0x14字节,即可覆盖返回地址;然后将ShellCode放置在后面,即可执行任意代码。由于在漏洞函数的结尾处,它在返回时会弹出0x14大小的栈空间,因此我们在jmp esp中填充一些垃圾指令以填充这一空缺

在这里插入图片描述

某实际样本的分析情况如上图,当漏洞函数返回后,会先从栈顶弹出0x14字节空间,然后执行0x7d1f5fb7处的jmp esp指令,进而跳入shellcode起始地址,导致执行任意代码

Office 2003与Office 2007 Exploit通用性研究

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

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

该地址适用于Office 2003 SP0和SP3等各个子版本,属于稳定的跳转地址。对于Office 2007,0x0026762F已不再是call/jmp esp等类似指令,当我们用0x0026762F这个地址覆盖掉Office 2007上的返回地址,只要能够让它触发异常,就可能执行SEH结构。这样的话,我们只需加大内存拷贝的大小,使其覆盖到最近的SEH结构就可以劫持EIP。也就是说,我们需要同时覆盖返回地址和SEH结构。

我们构造的数据如下:

111111111111111111111111111111111111111111111111111111111111112f762600111111111111111111111111111111111111111111111111111111111111aaaaaaaaffffffff

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

发布了99 篇原创文章 · 获赞 89 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/qq_38474570/article/details/98355995
今日推荐