*本文中涉及到的相关漏洞已报送厂商并得到修复,本文仅限技术研究与讨论,严禁用于非法用途,否则产生的一切后果自行承担。
*本文原创作者:elli0tn0phacker,本文属于FreeBuf原创奖励计划,未经允许禁止转载
0x00 背景
2018年12月5日,360发表博客《“毒针”行动 – 针对“俄罗斯总统办所属医疗机构”发起的0day攻击》披露了其在2018年11月29日捕获到的使用Flash 0day:CVE-2018-15982漏洞配合微软Office Word文档发起的APT攻击事件。文章从攻击流程,漏洞成因,漏洞利用,补丁分析,攻击载荷分析等多角度全面介绍了这次攻击的技术细节,非常值得大家仔细阅读学习。
也许是因为篇幅有限,文章关于漏洞成因和漏洞利用部分细节描述略简,阅读完文章后可能会有如下一些问题:
1)在没有符号表的情况下,如何定位存在漏洞的函数add_keySet;
2)DRCWB是什么;
3)漏洞利用部分动态调试情况;
4)HackingTeam Bypass DEP/CFG执行Shellcode的技术细节。
笔者在学习了这篇文章后,完成了该CVE的Exploit复现,在此记录下完整的分析过程,并尝试解释上述问题,与大家分享。但水平有限,文中错误之处恳请斧正。
0x01 Flash调试
众所周知,Flash没有符号表,难以对相应的Native Code下断点。同时AVM拥有自己的Custom Heap,因此也无法通过开Page Heap第一时间定位漏洞现场。所以Flash的调试往往比有符号表的浏览器的调试略微复杂一些。在学习了前人的经验后,笔者一般通过如下方法调试Flash:
Flash编译器会将AS3 code编译成ABC code,在执行阶段AVM2会对每一段ABC code验证后生成对应的一段JIT code,在没有符号表的情况下,如果可以对生成的JIT code下断点,再单步跟踪就可以找到调用的Native Code了。
以调试Metadata::setObject为例,首先构造如下测试代码:

命中testMetadata() JIT后的代码,继续跟入,很快就找到了setObject的Native Code实现:
这样就找到了setObject_impl,进一步跟入最终可以找到add_keySet的代码。
需要注意的是这个工具中inline hook的几个native 函数的特征码不同flash版本是不同的,因此需要根据flash版本更新 Hook函数的特征码才可以正常使用。
如果不熟悉这款工具的话,还可以通过另一种方法来定位JIT Code:借助已知符号表函数下断点,再根据Call Stack定位。AS3提供ExternalInterface.call(functionName:String,…arguments)方法来调用JS,而mshtml.dll和jscript9.dll的符号表是已知的,因此我们可以在需要断下AS3方法入口点插入类似的辅助调试语句:

0x02 漏洞成因
CVE-2018-15982是一个存在于flash PSDK com.adobe.tvsdk.mediacore.metadata包的UAF漏洞。Metadata类提供了一个类似Key-Value的容器,Key为String,Value为Object。该漏洞存在于Metadata的SetObject方法, SetObject方法用来向Metadata对象存放数据:

1.传入Key(String)和value(Object),调用setObject_impl:



所以这个Bug的根本原因是:将String对象传递给KeySet后,没有增加String对象的引用计数,GC后String对象被释放,但是KeySet中仍然保存了该String对象的地址,最终形成悬挂指针。
触发漏洞的PoC如下:
通过setObject向Metadata的KeySet属性存放了0x100个String(“0”, “1”, “2” … “255”),然后通过触发异常强制GC,最终array_key这个Vector.<String>中将包含指向已释放内存的String的悬挂指针, 动态调试如下:
1.通过setObject向Metadata的KeySet属性存放了0x100个String(“0”, “1”, “2” … “255”):


0x03 漏洞利用
由漏洞原理分析可以知道,通过触发漏洞可以获得一个包含一系列悬挂指针的Metadata.KeySet,每个悬挂指针指向的内存大小为0x18 Bytes(StringClass大小)。接下来考虑如何占位并利用这些悬挂指针实现远程代码执行。
这里的利用思路是:利用UAF将两个自定义类Class3,Class5的对象指针都指向这块内存,通过操作这两个对象实现类型混淆,从而进一步实现任意地址读写,混淆方法如图所示:
这样就可以通过Class5的m_1, m_2读取Class3的m_ba, m_Class1地址,也可以通过操作Class3.m_Class1.m_1实现任意地址的读写。
具体实现步骤如下:
1.内存准备,触发漏洞,获得一个包含一系列悬挂指针的KeySet,并保存到变量arr_key中,为后面遍历占位对象使用:










0x04 参考文献
1)http://blogs.360.cn/post/PoisonNeedles_CVE-2018-15982.html
2)https://developer.mozilla.org/en-US/docs/Archive/MMgc
3)https://help.adobe.com/en_US/primetime/api/psdk/asdoc-dhls_2.3/index.html
4)https://www.freebuf.com/column/191383.html
5)https://www.freebuf.com/vuls/73074.html
*本文原创作者:elli0tn0phacker,本文属于FreeBuf原创奖励计划,未经允许禁止转载
来源:freebuf.com 2018-12-27 10:00:36 by: elli0tn0phacker


0x02 漏洞成因

0x03 漏洞利用 



