前言

本文是这次flash 0day出来之后对这个漏洞的调试报告,文中的大部分都已经发布在核心安全技术博客的综合分析文章上。限于篇幅,原文中没有包含本文中的部分章节,特别是调试部分,即本文的“在调试器中看上述两个过程”对应章节,该部分对于理解这个漏洞的利用还是很有帮助的。

360威胁情报中心给出的分析部分shellcode分析得不错,可以两篇文章互补着看一下。

感谢核心安全成都分析团队对本次漏洞成因部分的精彩分析,感谢360高级威胁应对团队的大牛和小伙伴们对本文的指导。

水平有限,文中不足之处请见谅。由于截图较多,隐藏页边距时全文排版会好一点。

概述

该漏洞位于TVSDK内Metadata类的setObject函数,setObject在将String类型(属于RCObject)对象保存到Metadata类对象的keySet成员时,没有使用DRCWB(Deferred ReferenceCounted, with Write Barrier)。攻击者利用这一点,通过强制GC获得一个悬垂指针,在此基础上通过多次UAF进行多次类型混淆,随后借助两个自定义类的交互操作实现任意地址读写,在此基础上泄露ByteArray的虚表指针,从而绕过ASLR,最后借助HackingTeam泄露代码中的方式绕过DEP/CFG,执行shellcode。

我们完全逆向了整套利用代码,为方便读者阅读,下文所引述的代码均为重命名后的代码。

漏洞成因

1、Metadata类的setObject对应的Native函数如下图所示,实际实现在setObject_impl里。

2、在setObject_impl内,会直接将传入的键(String对象)保存到Metadata的keySet成员里。

Buffer结构体定义如下。(keySet成员的结构体与Buffer有一定差异,此处是为了便于说明)

3、add_keySet中保存传入的键(String对象)的汇编代码如下所示。

4、此时如果强制触发GC(垃圾回收机制),GC会认为传入的键未被引用,从而回收相应内存,然而Metadata对象的keySet成员中仍保留着指向被回收内存的指针。

UAF

准备工作

原利用代码首先申请0x1000个String对象,然后立即释放其中的一半,从而造成大量String对象的内存空洞,为后面的利用做准备。

第1次UAF

随后,利用代码定义了一个Metadata对象,借助setObject方法将key-value对保存到该对象中,Metadata对象的keySet成员保存着一个指向一片包含所有key(以String形式存储)的内存区域的指针。紧接着强制触发GC,此时keySet内保存着一个指向上述内存区域的(间接)悬垂指针(这里更准确的描述应该是:该内存区域内那些指向已被释放的String对象的指针没有被清零,导致可以通过keySet去操作已被释放的内存),随后读取keySet到arr_key数组,供后面使用。

得到悬垂指针后,利用代码立即申请256个Class5类对象保存到vec5(vec5是一个向量对象),由于Class5类对象的内存大小和String对象的内存大小一致(32位Class5对象为0x18字节),且相关对象分配在同一个堆内,根据MMgc内存分配算法,会有Class5对象占据之前被释放的(连续两个)String对象的内存空间。

其中Class5对象定义如下,可以看到该Class5有2个uint类型的成员变量,分别初始化为0x18和2200(0x898)。

随后遍历key_arr数组,找到其中长度变为0x18的字符串对象(在内存中,String对象的length字段和Class5的m_1成员重合),在此基础上判断当前位于32位还是64位环境,据此进入不同的利用分支。

第2次UAF


接上图,可以看到:在找到被Class5对象占用的String索引后,利用代码将arr_key的相关属性清零,这使得arr_key数组内元素(包括已占位Class5对象)的引用计数减少变为0,在MMgc中,对象在引用计数减为0后会立刻进入ZCT(zero count table)。随后利用代码强制触发GC,把ZCT中的内存回收,进入后续利用流程。下面我们主要分析32位环境下的利用流程。

在32位分支下,在释放了占位的Class5对象后,利用代码立即申请256个Class3对象并保存到另一个向量对象vec3中,此过程会重用之前被释放的某个(或若干)Class5对象的内存空间。

其中Class3对象的定义如下,它和Class5非常相似,两者在内存中都占用0x18字节。

可以看到Class3有一个m_ba成员和一个m_Class1成员,m_ba被初始化为一个ByteArray对象,m_Class1被初始化为一个Class1对象,Class1对象定义如下:

Class3对象占位完成后,利用代码立即遍历vec5寻找一个被Class3对象占用内存的原Class5对象。找到后,保存该Class5对象的索引到this.index_1,并保存该对象(已经变为Class3对象)的m_Class1成员到this.ori_cls1_addr,供后续恢复使用。

任意地址读写

32位下的任意地址读写

两轮UAF之后,利用代码紧接着利用上述保存的index_1索引,借助vec5[index_1]去修改被重用的Class3对象的m_Class1成员。随后立即遍历vec3去寻找被修改的Class3对象,将该对象在vec3中的索引保存到this.index_2。

到目前为止,利用代码已经得到两个可以操纵同一个对象的vector(vec5和vec3),以及该对象在各自vec中的索引(index_1和index_2)。接下来利用代码将在此基础上构造任意地址读写原语。

我们来看一下32位下任意地址读写原语的实现,从下图可以看到,借助两个混淆的Class对象,可以实现任意地址读写原语,相关代码在上图和下图的注释中已经写得很清楚,此处不再过多描述。关于减去0x10的偏移的说明,可以参考我们之前对cve-2018-5002漏洞的分析文章。

64位下的任意地址读写

64位下的任意地址读写原语和32位下大同小异,只不过64位下将与Class5混淆的类对象换成了Class2和Class4。此外还构造了一个Class0用于64位下的地址读取。

以下是这三个类的定义。

以下是64位下的任意地址读写原语,64位下的读写原语一次只能读写32位,所以对一个64位地址需要分两次读写。

在调试器内看上述两个过程(32位)

前面讲了那么多,还是调试器里见真章。我们在调试器内看一下32位环境下的两次UAF以及任意地址读写原语的工作过程。

第1次UAF


某次调试时,申请的Metadata对象在内存中如下:

第一次UAF之后,Class5对象进行了内存重用,我们在内存中看一下vec5以及其对应Class5对象:

可以看到上面两幅图中绿色高亮的对象地址由String对象变为了Class5对象。vec5中某个Class5对象重用了arr_key内第0n10(以及第0n11)个String对象的内存。

第2次UAF

随后,Class3对象会重用上述Class5对象的内存地址,从下图可以看到vec3中的第0n256个Class3对象重用了vec5中第0n33个Class5对象的内存地址。从这里我们已经可以得知index_1 = 0n33,index_2 = 0n256。

重用内存的Class3对象的初始元素如下,我们可以看到它的两个成员变量及它们对应的对象类型。

在执行下述代码后,上述Class3对象的m_Class1成员被修改。

在内存中查看被修改的Class3对象前后对比(m_Class1成员变成m_ba-1):

随后利用代码查找被修改后的Class3定位index_2,即0n256。

任意地址读写

借助index_1和index_2,分别用Class5对象和Class3对象对同一片内存区域进行操作,可以构造出任意地址读写原语,下面的调试日志展示了利用任意地址读原语读取ByteArray对象虚表指针的过程。

假设我们要读取addr地址处的4个字节,将m_Class1对象设为addr-0x10。利用代码中需要读取ByteArray对象首地址开始的4个字节,所以将m_Class1对象设为m_ba-0x10 = 0x0815e3f0。

可以看到ByteArray虚表指针已被成功读取:

任意地址写的过程和上述原理一致,此处不再描述。

Bypass ASLR/DEP/CFG

泄露ByteArray虚表指针Bypass ASLR

将ByteArray对象首地址传入任意地址读原语,从上一小节的图中已经看到ByteArray对象的虚表地址被读出并返回。在此基础上,借助任意地址读原语搜索32位下内存空间,找到flash模块基地址,从而绕过了ASLR。

利用代码还借助任意地址读原语构造了一系列功能函数,并借助这些功能函数最终读取kernel32.dll的VirtualProtect函数地址,供后面Bypass DEP使用。

利用HackingTeam的方法Bypass DEP/CFG


利用最终采用与HackingTeam完全一致的手法来Bypass DEP/CFG。由于相关过程在网上已有描述,此处不再过多解释。

Shellcode


原样本32和64位下的shellcode分别放在的Class6和Class7两个类内,我们用scdbg工具对32位下的shellcode做一个简单模拟,结果如下:

shellcode最终调用cmd启动WINRAR相关进程,相关命令行参数如下:

结语

本次flash 0day和今年年初的CVE-2018-4878一样都是TVSDK内的UAF问题。这类漏洞触发稳定,而且本次0day并未使用此前已经被增加额外校验的ByteArray利用方式,而采用另一种较为通用的利用手法实现任意地址读写。后面极有可能再次出现TVSDK内其他对象的UAF漏洞利用。

我们也预计该漏洞样本一旦被披露,会被立即加入各大EK,请大家做好防范准备。

- End -

看雪ID:银雁冰                              

https://bbs.pediy.com/user-628056.htm

本文由 银雁冰 原创

转载请注明来自看雪社区

新书推荐:

立即购买!

热门技术文章推荐:

  • 看雪CTF.TSRC 2018 团队赛 第六题 『追凶者也』 解题思路

  • CVE-2014-6332 修改浏览器安全属性开启Godmode

  • 看雪CTF.TSRC 2018 团队赛 第五题 『交响曲』 解题思路

  • 关于LOL动态皮肤修改的逆向与实现

公众号ID:ikanxue

官方微博:看雪安全

商务合作:wsc@kanxue.com

CVE-2018-15982 flash 0day漏洞分析报告相关推荐

  1. RiskSense Spotlight:全球知名开源软件漏洞分析报告

     聚焦源代码安全,网罗国内外最新资讯! 编译:奇安信代码卫士团队 RiskSense 公司最近发布了关于全球当前知名开源软件 (OSS) 的漏洞分析报告.奇安信代码卫士团队编译如下.   摘要 开源软 ...

  2. Hacking Team Flash 0day漏洞学习笔记

    周日的夜晚,与囧桑下载下来Hacking Team之前爆出的flash 0day漏洞,怀着紧张激动的心情,在自己的机子上做了实验,经测试,在我的虚拟机(一个sp3的XP,貌似没装Flash)上根本跑不 ...

  3. Office 2003 sp3(CVE-2012-0158)漏洞分析报告

    文章目录 Office 2003 sp3(CVE-2012-0158)漏洞分析报告 1.漏洞背景 2.漏洞成因 2.1 触发漏洞 2.2 定位漏洞模块 2.3 定位漏洞函数 2.4 分析漏洞成因 2. ...

  4. 用哪种语言写的应用漏洞最严重?六大主流语言代码漏洞分析报告出炉

    来源:机器之心 本文约1600字,建议阅读5分钟 静态代码分析安全公司 Veracode 近日发布了一份应用程序分析报告,结果发现比起 JavaScript 和 Python 等语言,C++ 和 PH ...

  5. 安天移动安全发布“大脏牛”漏洞分析报告(CVE-2017-1000405)

    一.背景简介 脏牛漏洞(CVE-2016–5195)是公开后影响范围最广和最深的漏洞之一,这十年来的每一个Linux版本,包括Android.桌面版和服务器版都受到其影响.恶意攻击者通过该漏洞可以轻易 ...

  6. 比葫芦娃还可怕的百度全系APP SDK漏洞 - WormHole虫洞漏洞分析报告

    瘦蛟舞 · 2015/11/02 10:50 作者:瘦蛟舞,蒸米 "You can't have a back door in the software because you can't ...

  7. android 漏洞发布,CVE发布2016年软件漏洞排行榜报告:安卓以523处位居第一

    IT之家讯 1月3日消息,近期CVE Details公布了2016年软件漏洞数量最新报告,根据报告显示,漏洞存在数量最多的是安卓系统,以523处漏洞位居第一,排名第二的为Debian Linux系统, ...

  8. CVE-2017-11882漏洞分析报告

    漏洞简介: 软件名称及版本:Microsoft Office2016以下 漏洞模块:EQNEDT32.EXE 漏洞编号:CVE-2017-11882 危害等级:高危 漏洞类型:缓冲区溢出 威胁类型:远 ...

  9. [转帖]最新FLASH 0DAY 漏洞总结分析篇

    首先必须感谢的X.G.C.Team的OPEN在几个关键的地方给予我分析,解决办法的帮助.与及咱们论坛好几位兄弟的帮助.最终我才把这个东西给分析出来.. -------------- 最近FLASH出了 ...

  10. 金融行业安全漏洞分析报告

    报告介绍 互联网+时代的到来,人们充分享受新时代科技创新成果的便利同时,万物互联带来的信息安全风险也日渐提高,信息泄密事件层出不穷,在资金体量庞大.用户信息集中.安全隐患影响深远的金融领域,所面临的安 ...

最新文章

  1. 显色指数测试软件,显色性
  2. validate做前端表单验证
  3. blocked java线程_Java线程状态:BLOCKED与WAITING的区别
  4. Alpine Linux 3.9.1 发布,面向安全的轻量级 Linux 发行版
  5. jQuery的UI框架 Liger UI
  6. git pull 报错:The following untracked working tree files would be overwritten by merge
  7. 【Java】计算1+3+5+7+9和100以内的素数
  8. 15个实用的管理mysql的MySQLadmin命令
  9. base64解密后乱码_php实现php代码的加密解密
  10. .NET 4.0 的Web Form和EF的例子 Employee Info Starter Kit (v4.0.0)
  11. Region proposal学习笔记
  12. JupterNoteBook
  13. 从 0 开始学习 GitHub 电子书免费送
  14. ssm框架整合springSecurity
  15. 高项_第三章项目立项管理
  16. GIAC全球互联网架构大会2017上海站圆满结束,PPT合集下载
  17. 解决Nokia PC SUITE无法识别DELL E6400 WIDCOMM bluetooth的问题
  18. constructor构造函数(React)
  19. Icons - Material Design各种ICON图标大全
  20. Java简单实现猜拳游戏

热门文章

  1. 前端导出Excel兼容写法
  2. 以一种访问权限不允许的方式做了一个访问套接字的尝试。
  3. mysql 数据导入导出说明
  4. matlab %%?
  5. Machine Learning(Andrew)Week6(上)
  6. 三种方法教你如何在 Mac 上检查磁盘空间使用情况
  7. Houdini特效资源如何导入?Houdini工程文件导入教程
  8. 95 后程序员一出校门就拿年薪 30多万?
  9. [svc]Linux中Swap与Memory内存简单介绍
  10. 1.3_对于Servlet规范的一点理解