深入理解Double Free:CVE-2015-2419 Exploit分析

栏目: 编程工具 · 发布时间: 6年前

内容简介:*本文原创作者:elli0tn0phacker,本文属FreeBuf原创奖励计划,未经许可禁止转载CVE-2015-2419是IE11中jscript9.dll的一个Double Free漏洞。虽然从发现在野攻击样本到今天已有三年多,但是目前依然被一些著名的漏洞利用工具包使用,可见其漏洞利用的稳定。通过分析其漏洞原理和利用技术,对于深入理解Double Free漏洞和jscript9.dll的exploit编写会有一定的帮助。触发漏洞的PoC如下:

*本文原创作者:elli0tn0phacker,本文属FreeBuf原创奖励计划,未经许可禁止转载

0×00 背景

CVE-2015-2419是IE11中jscript9.dll的一个Double Free漏洞。虽然从发现在野攻击样本到今天已有三年多,但是目前依然被一些著名的漏洞利用 工具 包使用,可见其漏洞利用的稳定。通过分析其漏洞原理和利用技术,对于深入理解Double Free漏洞和jscript9.dll的exploit编写会有一定的帮助。

0×01 漏洞成因

触发漏洞的PoC如下:

深入理解Double Free:CVE-2015-2419 Exploit分析 PoC通过create_triggering_json() 创建了一个触发漏洞的Json对象:

深入理解Double Free:CVE-2015-2419 Exploit分析 通过JSON.stringify将这个Json对象转换为JSON字符串,最后通过手动GC触发漏洞,开启HPA UST观察漏洞现场:

深入理解Double Free:CVE-2015-2419 Exploit分析 IE Crash,edx指向了未分配的内存,分析edx的来源,查看  Js::TempArenaAllocatorWrapper<1>::Dispose  函数:

深入理解Double Free:CVE-2015-2419 Exploit分析

这里edx = [this+0x34]-0×8,同时观察绿框代码,可以发现这里存在一个双向链表的卸载操作:

(1)  [[edx+4]]= [edx]                 (Prev pointer)
(2)  [[edx]+4]= [edx+4]             (Next pointer)
(3)  Free[edx]

通过观察Call stack,可以发现这里是在脚本执行CollectGarbage()时调用: jscript9!Js::TempArenaAllocatorWrapper<1>::Dispose  释放已经被释放的内存触发的Double Free漏洞,观察edx保存的地址是在什么时候被释放的:

深入理解Double Free:CVE-2015-2419 Exploit分析

可以看到edx保存的地址是在执行JSON.Stringify操作时,调用了: ThreadContext::ReleaseTemporaryGuestAllocator  被释放的,观察这个函数的释放逻辑:

深入理解Double Free:CVE-2015-2419 Exploit分析

这里当[this+0x3c4]>= 5时就会进入free memory分支,可以看到free memory分支的代码和上面分析的: Js::TempArenaAllocatorWrapper<1>::Dispose  逻辑时一样的,然而两次free memory本身逻辑时没有问题的,这个漏洞的根本原因时free memory释放内存后,保存这块memory地址的指针(edx)没有被清零,而这个指针正是  Js::TempArenaAllocatorWrapper  的成员变量,保存在 Js::TempArenaAllocatorWrapper  + 0×34处。

分析patch过的jscript9.dll可以发现这个漏洞是如何被修复的:

深入理解Double Free:CVE-2015-2419 Exploit分析

深入理解Double Free:CVE-2015-2419 Exploit分析

可以看到patch过的jscript9.dll,在free memory前会先检查edx是否为0,不为0则进入free memory分支,并且在free后将指针置0。

那么触发漏洞条件是什么呢,其实就是[this+0x3c4] >= 5,通过调试可以知道[this+0x3c4]保存的就是Json对象的嵌套深度,所以目前分析得到信息有:

(1)  当Json对象嵌套深度>=5时,GC后会触发Double Free漏洞
(2)  漏洞的根本原因是释放了类的成员变量保存的内存但是没有将该成员变量清零,GC时释放这个对象再次释放这块内存导致Double Free
(3)  利用这个漏洞不能直接RCE,但是可以触发一个双向链表的释放操作

现在我们开始尝试漏洞利用。

0×02 漏洞利用

通过前面的分析可以知道利用这个漏洞我们会获得一次双向链表卸载操作的机会,双向链表的卸载操作可以简化如下:

(1)  [[edx+4]]= [edx]          第一个DWORD被复制到第二个DWORD指向的内存
(2)  [[edx]+4]= [edx+4]      第二个DWORD被复制到第一个DWORD指向的地址+0×4的内存

如果edx可控的话,我们就可以获得一次向任意2个DWORD([edx]和[edx]+4)写入数据的机会。那写入数据的机会如何利用呢,这里就需要HeapSpray,Jscript9.dll里HeapSpray常用的数据类型如下:

Array:

JavaScript的Array在IE11中有两种形式:

(1) Js::JavascriptNativeIntArray

深入理解Double Free:CVE-2015-2419 Exploit分析

主要数据结构:

Js::JavascriptNativeIntArray
+0x0       vftable
+0x10     Array size
+0x14     first buffer address
+0x18     second buffer address
Buffer
+0x4       item size
+0x8       item buffer size (超过这个size会分配一块新内存)

(2) Js::JavascriptArray

深入理解Double Free:CVE-2015-2419 Exploit分析

数据结构同 Js::JavascriptNativeIntArray,当Array中保存了对象后,数字元素会以2N+1的奇数形式存放用来区别对象指针。

ArrayBuffer 和TypedArray:

ArrayBuffer表示通用的、固定长度的原始二进制数据缓冲区。ArrayBuffer不能直接操作,而是要通过类型数组对象TypedArray或 DataView 对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。

深入理解Double Free:CVE-2015-2419 Exploit分析

Js::JavascriptArrayBuffer

+0x0       vftable
+0x1C     ArrayBufferAddress
+0x20     ArrayBufferSize

Js::TypedArray<unsignedint>

+0x0       vftable
+0x10     Js::JavascriptArrayBuffer
+0x1C     ArrayBufferSize
+0x20     ArrayBufferAddress

需要注意的是ArrayBuffer是在CRT堆上分配的。

我们可以使用 Js::TypedArray<unsigned int> 做漏洞利用的数据类型,这里只需要修改+0x1C的ArrayBufferSize和+0×20的ArrayBufferAddress就可以实现用户态任意地址读写。

首先需要通过Heap Spray将Js::TypedArray<unsigned int>放到可预测内存地址。

Heap Spray

利用Heap Spray我们可以将Js::TypedArray<unsignedint>排布在指定内存地址,使用如下代码进行Heap Spray:

深入理解Double Free:CVE-2015-2419 Exploit分析

每个spray[size]分配的内存大小 = 0×20(JavascriptArray Header) + 0x3BF8*4(JavascriptArray Data) + 0×55*0×30(Js::TypedArrayHeader) = 0xFFF0 (对齐)= 0×10000 (64kB):

深入理解Double Free:CVE-2015-2419 Exploit分析

Heap Spray完检查内存:

深入理解Double Free:CVE-2015-2419 Exploit分析

深入理解Double Free:CVE-2015-2419 Exploit分析 这样通过Heap Spray可以在0x128ef000处稳定找到一个Js::TypedArray<unsigned int,0>。 接下来利用这个Double Free的漏洞就可以通过2个DWORD修改的机会篡改这个Js::TypedArray<unsignedint,0>的长度(0x128ef01c)和ArrayBuffer起始地址(0x128ef020),实现任意地址读写。

任意地址读写

jscript9!ThreadContext::ReleaseTemporaryGuestAllocator  + 0x5bc4a 处下断点,查看Double free内存大小:

深入理解Double Free:CVE-2015-2419 Exploit分析

被释放的内存为0x0CBytes,因此这里可以用0x0C Bytes ArrayBuffer占位,并将需要修改2 DWORD地址写到ArrayBuffer数据:

深入理解Double Free:CVE-2015-2419 Exploit分析

这里用0×10000 0xC Bytes的ArrayBuffer尝试占位,占位成功后,在  jscript9!Js::TempArenaAllocatorWrapper<1>::Dispose  :触发漏洞,利用双向链表的卸载操作修改我们之前通过Heap Spray排布在0x128ef000处的Js::TypedArray<unsignedint,0>的长度(0x128ef01c)和Arraybuffer起始地址(0x128ef020):

深入理解Double Free:CVE-2015-2419 Exploit分析

这样就得到了一个起始地址为0x128ef018大小为0x128ef020的Js::TypedArray<unsigned int,0>,再利用这个Js::TypedArray<unsignedint,0>获得一个任意地址读写的Js::TypedArray<unsignedint,0>:

深入理解Double Free:CVE-2015-2419 Exploit分析

泄露基址

执行Shellcode前,需要获得一些关键函数的地址。比如 kernel32!VirtualProtectStub ,通过如下方法泄露函数地址:

(1)利用任意地址写权限,在0x128e0020(即spray[i][0])处写入标记数据0x1BD81BD (0xDEC0DE * 2 |1)
(2)通过遍历spray[i][0]找到被写入标记数据0x1BD81BD的spray[k]
(3)再将JavascriptArray对象保存再spray[k][2]处,通过任意地址写权限,读取0x128e0020处的DWORD,这个就是JavascriptArray的vftable,那么jscript9_base_addr = vftable & 0xffff0000
(4) 搜索jscript9.dll导入表,泄露kernel32!VirtualProtect地址

深入理解Double Free:CVE-2015-2419 Exploit分析

构造ROP

我们依然使用0x128e0000的spray[k]来存放ROP gadget和 shellcode,其中spray[k][0]存放ROP gadget, spray[k][1]存放shellcode:

深入理解Double Free:CVE-2015-2419 Exploit分析

执行Shellcode

spray[k][2][0]= 0会调用 jscript9!Js::JavascriptArray::SetItem 给JavascriptArray赋值,SetItem函数在jscript9!Js::JavascriptArray::`vftable’+0×90处,通过篡改spray[k][2]的JavascriptArray的虚表从而执行最终shellcode:

深入理解Double Free:CVE-2015-2419 Exploit分析 深入理解Double Free:CVE-2015-2419 Exploit分析


以上所述就是小编给大家介绍的《深入理解Double Free:CVE-2015-2419 Exploit分析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

挑战程序设计竞赛

挑战程序设计竞赛

秋叶拓哉、岩田阳一、北川宜稔 / 巫泽俊、庄俊元、李津羽 / 人民邮电出版社 / 2013-7-1 / CNY 79.00

世界顶级程序设计高手的经验总结 【ACM-ICPC全球总冠军】巫泽俊主译 日本ACM-ICPC参赛者人手一册 本书对程序设计竞赛中的基础算法和经典问题进行了汇总,分为准备篇、初级篇、中级篇与高级篇4章。作者结合自己丰富的参赛经验,对严格筛选的110 多道各类试题进行了由浅入深、由易及难的细致讲解,并介绍了许多实用技巧。每章后附有习题,供读者练习,巩固所学。 本书适合程序设计......一起来看看 《挑战程序设计竞赛》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换