<% dim ModuleName,InfoID,ChannelShortName,CorrelativeArticle,InstallDir,ChannelDir,Keyword,PageTitle,ArticleIntro,Articlecontent Keyword=stripHTML("深度,分析,微软,Office RTF,文件,溢出,漏洞,CVE-2016-0010") PageTitle=stripHTML("深度分析微软Office RTF文件堆溢出漏洞(CVE-2016-0010)") ArticleIntro=stripHTML("根本的原因是由于可以控制拷贝至堆缓冲区的长度从而能够造成堆溢出。本文将对其进行分析。") Articlecontent=stripHTML("0×01  摘要  在这个月的微软周二补丁日,微软修复了3个Office漏洞MS16-004。这个漏洞是由于MS Office未能正确解析RTF文档所造成的堆…") ModuleName = stripHTML("exploits") InfoID = stripHTML("223862") ChannelShortName=stripHTML("漏洞") InstallDir=stripHTML("http://www.77169.com/") ChannelDir=stripHTML("exploits") %> 深度分析微软Office RTF文件堆溢出漏洞(CVE-2016-0010) - 华盟网 - http://www.77169.com
您现在的位置: 华盟网 >> 漏洞 >> 最新漏洞 >> 其它漏洞 >> 正文

[组图]深度分析微软Office RTF文件堆溢出漏洞(CVE-2016-0010)

2016/1/23 作者:老王隔壁的白帽子 来源: freebuf
导读 <% if len(ArticleIntro)<3 then Response.Write Articlecontent 'Response.Write "Articlecontent" else Response.Write ArticleIntro 'Response.Write "ArticleIntro" end if %>

  0×01  摘要

  在这个月的微软周二补丁日,微软修复了3个Office漏洞MS16-004。这个漏洞是由于MS Office未能正确解析RTF文档所造成的堆溢出漏洞,成功利用此漏洞可以使得攻击者远程执行代码。  

        0×02  分析

  打开构造好的RTF文件,Word crash信息如下:

     

      首先看一下这个RTF文件。将这个最小化的POC文件和正常文件做对比,会发现在偏移值0x1733D有一处不一样。对比如下所示:

     

      Figure 1. 正常RTF文件和POC文件对比

  从图1可以看出,不同点位于下图的结构当中:

      原始文件结构如下:

     

      很明显,由于word在处理RTF文件中的“pict”结构造成的漏洞。

  简单介绍一下RTF的文件格式,具体信息可以从官网找到。RTF文件通常采用7位编码,由控制字、控制符和组构成。RTF的控制字是用来标记打印控制符和管理文档信息的一种特殊格式的命令。一个控制字最长32个字符。控制字的使用格式如下:\字母序列<分隔符>。

  在这里我们只需关注控制字“\pict”。一个RTF文件可以包含由其他应用创建的图象。这些图象可以是16进制(默认的)或2进制格式。图象属于目标引用,由\pict 控制字开始。一个图象引用具有如下语法:

     

      这些控制字的解释见下表:

     

     

 

  在POC文件中,使用的是“\dibitmap0” 和 “\wbmwidthbytes16”控制字。

     

      根据“\dibitmapN”的定义,图片源为包含在RTF中的一个Windows设备无关位图信息,来源于实际象素数据前的BITMAPINFO结构之中。那么问题是这些元数据是如何对应到BITMAPINFO结构中的呢?

     

      我们知道这是一个Windows设备无关的位图。因此我们用画图板创建一个BMP文件,010editor的BMP模板解析之,得到如下图信息:

     

      Figure 2.  解析BMP文件

  在BITMAPINFO结构中对应到如下元数据。BITMAPINFOHEADER结构数据如下,长度是0×028。

     

      BITMAPLINE结构数据如下所示,长度为0×10。

     

  现在将POC文件中的BITMAPINFOHEADER结构数据替换上述数据,得到组合后的BMP文件,如下所示:

     

      Figure 3. 解析组合后嵌入RTF文件中的BMP位图

  更多关于BMP的文件格式详见这里。

  接着分析,为了跟踪这些BMP文件中的元数据,在Windbg下如下断点:

  bu mso!Ordinal7809+0x138 " .if(poi(eax+4)==0x0c000004) {.printf \"test1:\\n\"; db eax;} .else{gc}"

  断下后,Windbg调试信息如下:

     

      可以看到堆缓冲区起始地址为0x1c32eff0-0x1c32f027,存储的是”pict”控制字的元数据,长度是0×38。

  下面是一些调试信息:

     

     

     

     

 

  从上面的缓冲区中可以看到biSizeImage设置等于0。

     

      查看函数mso!Ordinal1181: 

     

     

      继续跟踪这个函数 mso!Ordinal1181 ,代码如下:

     

 

  根据上面的分析,可以看到在sub_3279c4b0返回了一个无效的像素数据长度,而这个值接下来会作为函数MS0_8609的参数,MS0_8609函数是用来创建堆缓冲区的,后果就是创建的缓冲区的过小,最终在拷贝数据的时候造成了缓冲区溢出

  继续跟踪这两个关键函数sub_3279c4b0和MS0_8609。函数MS0_8609(v5,4u,0x28u,Size)是用来创建堆缓冲区的,代码如下:

      可以看到,传入的四个参数如下:

     

 

  · a1 应该是 biClrUsed, 这里的值是0.· a2 = 0x4.· a3 = 0x28.· a4 是像素数据的大小。应该是0x10,但是这里的值却是0,正是因为这个才导致缓冲区分配过小。

  看看函数MS0_8609分配的堆缓冲区

     

     

 

  函数sub_3279C4B0是计算像素数据大小的,下面是其部分汇编代码:

     

     

 

  从上面的分析可以看出来,函数0x31d8c4f2重新计算大小,Windbg跟踪一下这个函数。

     

      上述代码IDA反编译后的代码如下:

     

 

  原本bWidth的值应该是0×00000004,在Windbg中计算一下这个值应该是多大

     

  这才是正确的值,但是当我们将其设置成0x0c000004时,计算结果为0。

  在函数0x31d8c4f2处,标记成绿色的两个函数0x31bf817a 和 0x31d8c606是计算这些值的,下面看一下这两个函数是如何计算的。

     

      IDA反编译代码如下:

     

      最终的crash信息如下:

     

 

  0×03  结论

  综上所述,这是个典型的堆溢出漏洞,通过构造特定的值能够使得拷贝用户提供长度大小的值至缓冲区中,成功利用此漏洞可以远程执行代码。

 



  • 上一篇漏洞:

  • 下一篇漏洞: 没有了