<% dim ModuleName,InfoID,ChannelShortName,CorrelativeArticle,InstallDir,ChannelDir,Keyword,PageTitle,ArticleIntro,Articlecontent Keyword=stripHTML("CVE-2015-1641,漏洞,分析,利用") PageTitle=stripHTML("CVE-2015-1641漏洞分析与利用(一)") ArticleIntro=stripHTML("对CVE-2015-1641漏洞的分析,看看他的危害") Articlecontent=stripHTML("0x01 漏洞概述  微软于今年2015-04-14发布一个编号CVE-2015-1641的Office漏洞,微软的简单描述为“当 Office 软件无法正确处…") ModuleName = stripHTML("exploits") InfoID = stripHTML("217677") ChannelShortName=stripHTML("漏洞") InstallDir=stripHTML("http://www.77169.com/") ChannelDir=stripHTML("exploits") %> CVE-2015-1641漏洞分析与利用(一) - 华盟网 - http://www.77169.com
您现在的位置: 华盟网 >> 漏洞 >> 最新漏洞 >> win 漏洞 >> 正文

[组图]CVE-2015-1641漏洞分析与利用(一)

2015/11/20 作者:91ri团队-L… 来源: 91ri
导读 <% if len(ArticleIntro)<3 then Response.Write Articlecontent 'Response.Write "Articlecontent" else Response.Write ArticleIntro 'Response.Write "ArticleIntro" end if %>

  0x01 漏洞概述

  微软于今年2015-04-14发布一个编号CVE-2015-1641的Office漏洞,微软的简单描述为“当 Office 软件无法正确处理内存中的丰富文本格式文件时,Microsoft Office 软件中会存在一个RCE漏洞。”

  查了一下这个漏洞,发现危害确实很大,而对于这个漏洞的分析网上很少。阿里基础安全威胁情报中心在2015-10-15发布了一篇“CVE-2015-1641漏洞分析—CVE-2012-0158或将退出历史舞台”而这篇博客也被各大安全网站和论坛争相转帖。

  “word在解析docx文档处理displacedByCustomXML属性时未对customXML对象进行验证,可以传入其他标签对象进行处理,造成类型混淆,导致任意内存写入,最终经过精心构造的标签以及对应的属性值可以造成远程任意代码执行。” “CVE- 2015-1641这个漏洞的触发非常稳定,几乎影响微软目前所支持的所有office版本(最新推出的Office 2016除外),影响范围十分广泛。目前无论是在VirusTotal还是在野外抓到的样本,利用这个漏洞的攻击样本已经开始逐渐增加。根据以上原因可以推断,在今后很长的一段时间内都会存在该漏洞的攻击,并且有替代CVE-2012-0158的趋势。”这是该篇博客对于这个漏洞的定义以及严重危害性的介绍。

  作者无意中在野外抓到这个漏洞的样本,对该漏洞的进行了分析一般,准备从2个阶段着手分析,第一个阶段对样本进行分析,包括利用细节以及shellcode分析;第二个阶段对该漏洞成因进行分析。本文为第一个阶段。

  0x02 样本分析

  本文件名:ammendment.doc

  文件大小:371.8KB

  文件类型:RTF文件

  MD5:ae6b65ca7cbd4ca0ba86c6278c834547

  有兴趣的可以根据这些信息去网上搜索相应的样本文件。该漏洞的样本乍一看跟0158和1761的样本相似,都是RTF文件嵌入OLE对象。



  可以看到样本中嵌入了4个对象,第一个是加载一个ActiveX/COM objects otkloadr.WRAssembly.1,通过这个调用MSVCR71.DLL(bypass ASLR),这种技术并不是第一次出现了,1761就是通过加载模块MSCOMCTL.OCX来bypass ASLR 的;其余三个分别是嵌入的docx文档,将这三个文档从样本中提取出来。我们这里只需关注第一个docx文档,这里使用了Heap Spray,这个类似于cve-2013-3906的利用方式。在目录word/activeX的activex1.bin文件中,被加载了40次。

  在activex1.bin中可以看到,首先是构造了大量的地址为0x7c342404 的ret-sled,随后是一段ROP chain,最后“9090909090”标志着第一阶段的shellcode开始的位置,并且在activex1.bin文件中每隔0x20000 字节出现一段,总共出现16次。这是典型的Heap Spary技术来执行内存中的shellcode。

  0x03 调试样本

  环境:windows 7

  Word 版本:office word 2010

  载入样本,断点为0x7c342404。


  RET-sled、 ROP chain、shellcode均已经拷贝至堆区了,起始地址为0x09000810。当这一系列的RET-sled执行完,接下来执行ROP chain。单步执行,查看执行过程。


  通过调用VirtualProtect关闭起始地址0x090008b4后的DEP保护。下图所示。


  接着执行地址0x090008b4处的shellcode。

  0x04 shellcode分析

  Stage1 shellcode

  在activex1.bin中的shellcode比较简单,因此可以推断是第一阶段的shellcode,通过egg hunter执行第二阶段的shellcode。为了分析第一阶段的shellcode(即egg),可以将其放在onlinedisassembler进行反编译,具体细节查看分析完的反汇编代码,onlinedisassembler。过程分为以下几个部分:

  获取kernel32.dll基址。

  函数名经过ror-7 hash计算出摘要,函数导出表匹配函数摘要,查找出指定函数地址。

  VirtualAlloc分配可执行的内存空间(用于保存第2阶段的shellcode)。

  GetFileSize搜索文件句柄,CreateFileMapping创建该文件的共享文件数据,MapViewOfFile来获取共享的内存地址。

  判断几个标志位是否为’{\rt’,0xfefefefe,0xfe,0xffffffff。是则将第2阶段的shellcode拷贝到VirtualAlloc分配可执行的内存空间。否则返回4。Shellcode2位于原始RTF文档偏移值为0x41400处。

  根据这个过程的汇编代码得到的伪代码如下所示。

以下是代码片段:
//获得指定函数地址,分配可执行区域。
VirtualAlloc = rorExtractFunction(0x1EDE5967h, kernel32Base);
Buffer = VirtualAlloc(0, 0x500000, 0x3000, 0x40);
funcArr = {0x0AC0A138E, 0x14B19C2, 0x9AA5F07Dh, 0x0};
{GetFileSize, CreateFileMappingA, MapViewOfFile} = rorExtractFunction(lpvBuffer, kernel32Base);
  
hFile = 0;
  
// 通过标志位’{\rt’将RTF文件起始位置加载至内存中
while (true) {
  do {
    hFile += 4;
    dFileSize = GetFileSize(hFile, 0);
  } while (dFileSize < 0xA000 || dFileSize > 0x200000);
  
  hFileMappingObject = CreateFileMappingA(hFile, 0, 2, 0, 0, 0);
      
  if (hFileMappingObject) {
    lpvFileView = MapViewOfFile(hFileMappingObject, 4, 0, 0, 0);
    if (lpvFileView) {
      if (&lpvFileView == "{\rt") {
        break;
      }
    }
  }
}
  
lpvFileView += 0x10000;
  
// 通过标志位fefefefe fefefefe ffffffff 定位第二阶段的shellcode,并将其拷贝至指定内存区域。
while (true) {    
  do {
    lpvFileView += 4;
  } while (&lpvFileView != 0xFEFEFEFE);
    
  do {
    lpvFileView++;
  } while ((char*)lpvFileView == 0xFE);
    
  if (&lpvFileView == 0xFFFFFFFF) {
    scAddr = Buffer + 0x1000;
    memcpy(Buffer, lpvFileView + 4, 0x1000);
    scAddr(kernel32Base, lpvFileView, hFile, dFileSize, Buffer);
  }
}

  Stage2 shellcode

  偷个懒,在scdbg中快速执行之,结果如下所示。



  分为以下几个阶段:

  1.在偏移0x2e处解码shellcode

  2.调用ZwQueryVirtualMemory获得原始RTF文件的名称,并通过WideCharToMultiByte将文件名转化成ASCII码。

  3.获得要释放的payload文件exe的完整路径。

  4.在原始RTF文件标志位为0xBABABABA和0xBABABA处获得payload,xor 0xCAFEBABE解码payload,终止标志为0xBBBBBBBB和0xBBBBBB。随后将解码后的Payload写入exe文件中。

  5.释放payload。

  6.在原始RTF文件标志位为0xBCBCBCBC处获得正常文档,xor 0xBAADF00D解码正常文档。随后将解码后的文档写入原始RTF文件中。

  7.清理注册表中的HKCUSoftwareMicrosoftOffice1{2,4,5}.0WordResiliency避免当再次打开文档时由于之前的崩溃导致word报错或者弹出其他警示消息。

  8.释放正常文档。

  0x05总结

  通过未开启ASLR的MSVCR71.DLL bypass ASLR,利用Activex 对象Heap Spray定位shellcode,ROP过DEP,shellcode egg hunter。

  这里个人感觉第二阶段的shellcode比较有亮点,通过清除注册表中的HKCUSoftwareMicrosoftOffice1{2,4,5}.0WordResiliency来屏蔽word警示信息。

  至于该漏洞第二阶段的分析,准备近期完成。

  由于写的比较仓促,分析的不到位的地方还请拍砖。。。