CVE-2018-8174:从UAF到任意地址读写

2018 年 6 月 12 日 FreeBuf

0x00 背景

2018年5月9日,360发表Blog “Analysis of CVE-2018-8174 VBScript 0day and APT actor related toOffice targeted attack” 揭露了利用“双杀”0day发起的APT攻击,其中使用的漏洞就是IE vbscript 0day:CVE-2018-8174,不久该样本就在互联网被公布。由于360的Blog并没有对漏洞原理和任意地址读写的利用方法详细介绍,且原始样本混淆严重,笔者对样本进行了简化,重点说明该漏洞的原理和如何利用该漏洞实现任意地址读写,希望帮助大家更好的理解这个漏洞利用程序。

0x01 漏洞原理

poc如下:

poc中首先定义了两个数组array_a和array_b,并声明了一个类Trigger,Trigger中重载了析构函数Class_Terminate,在UAF函数中,创建了一个Trigger的实例赋值给数组array_a (1),并通过Erase array_a清空array_a中的元素,这时候在析构array_a中的元素的时候会触发脚本中Class_Terminate的调用,在Class_Terminate中增加了一个array_b(0)对Trigger实例的引用(Trigger实例引用计数+1),再通过array_a (1)= 1删除array_a (1) 对Trigger实例的引用(Trigger实例引用计数-1)来平衡引用计数,这时候Trigger实例会被释放,但是array_b(0)仍然保留了这个Trigger实例的引用,从而array_b(0)指向了被释放的Trigger实例的内存,最终在TriggerVuln中通过b(0) = 0访问未分配内存触发漏洞。开启hpa和ust观察漏洞现场:

显然eax已经在vbscript!VbsErase的调用栈中被释放了,vbscript!VbsErase即对应了脚本中的Erase,而eax正是被VBScriptClass::Release函数释放的VBScriptClass对象也就是脚本中的Trigger实例。这里看下VBScriptClass::Release的逻辑:

VBScriptClass::Release中首先对VBScriptClass的引用计数-1(&VBScriptClass+0x4),如果引用计数=0则调用VBScriptClass::TerminateClass,调用VBScriptClass::TerminateClass时因为在脚本中重载了Class_Terminate函数,所以获得了一次脚本执行的机会,这里就可以在释放VBScriptClass的内存前将即将释放的VBScriptClass内存地址保存脚本控制的变量中(Set array_b(0) =array_a(1)),并通过array_a (1) = 1平衡引用计数,最终释放内存。

1) Set array_a(1) = New Trigger:此时VBScriptClass引用计数=2

2) Erase array_a返回后:

此时Trigger指向的内存已经被释放,但是array_b(0)仍然指向这块被释放的内存,形成悬挂指针。

0x02 漏洞利用

UAF漏洞利用的关键是如何使用这个悬挂指针操作内存。通过分析漏洞原理知道array_b(0)指向被释放的VBScriptClass的内存(大小为0x30),这时候可以用一个VBScriptClass占位(这里称为MyClass2),接着利用悬挂指针array_b(0)释放这块内存再用另外一个VBScriptClass占位(这里称为MyClass1),此时MyClass1和MyClass2将同时指向这块内存。此外VBScriptClass在+0x08处是保存了VBScriptClass成员变量和成员函数NameTbl对象(大小为0x88)的指针,NameTbl对象从+0x48开始保存成员变量和成员函数的指针:

可以理解为下图,通过UAF MyClass1 和MyClass2都指向VBScriptClass的内存,同时MyClass1 MyClass2的变量也都保存在NameTbl中,如果MyClass1 MyClass2的变量在NameTbl内存是错位排列的,那么就有可能通过控制其中一个对象变量的值来修改另一个对象变量的属性,从而实现类型混淆:

简化后的任意地址读写poc:

首先在UAF函数中创建了一些VBScriptClass对象占据系统堆碎片为后面UAF准备,然通过触发漏洞获得指向已释放的Trigger对象内存的array_b,接着通过“Set mycls2 = New MyClass2”,用MyClass2占位释放的内存,此时array_b的7个元素和MyClass2都指向这块内存。

在InitObjects函数的“mycls2.SetProp(myconf)”中会触发Confusion类的Public Default Property Get P函数调用,并将返回值“P=174088534690791e-324”保存在MyClass2的成员变量mem中。在PublicDefault Property Get P函数调用中,再次利用悬挂指针array_b(i)释放了MyClass2的内存,然后用MyClass1占位并将字符串FAKESAFEARRAY赋值给MyClass1的成员变量mem,由于MyClass2依然指向这块内存,因此MyClass2.mem = MyClass1.mem = FAKESAFEARRAY。

注意到之前Public Default Property Get P函数调用的返回值“P=174088534690791e-324”会保存在MyClass2的成员变量mem中,但是此时MyClass2内存已经被释放,返回值“P=174088534690791e-324”仍然会保存在原来的MyClass2的mem指向的内存地址,poc中的被释放的MyClass2的mem和MyClass1的mem有0xC字节的错位,而“P=174088534690791e-324”对应的VARIANT在内存中的值为“00000005 00000000 00000000 0000200C”,从而利用错位的“0000200c”将BSTR混淆为VARIANT|ARRAY,而FAKESAFEARRAY的内容正好是一个起始地址为0x00000000长度为0x7FFFFFFF每个元素占1Byte的数组,最终实现任意地址读写。

1)Set mycls2 = New MyClass2后MyClass2的内存布局:

2)PublicDefault Property Get P中MyClass2被释放,MyClass1占位:

可以看到MyClass1.mem(0x020066C6C)和释放前的MyClass2.mem(0x020066C60)相差0xC Byte

3)PublicDefault Property Get 返回后通过“P=174088534690791e-324”修改释放前的 MyClass2.mem为“00000005 00000000 00000000 0000200c”实现类型混淆:

最终myClass2.mem获得任意地址读写权限。

同理BSTR也可以被混淆成Long类型用来泄露shellcode的内存地址:

关于对象地址泄露和shellcode执行,可以参考360那篇Blog,当然DVE也是可行的,不再详述。

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

登录查看更多
0

相关内容

Visual Basic Script 的简称。
[ICML-Google]先宽后窄:对深度薄网络的有效训练
专知会员服务
34+阅读 · 2020年7月5日
【斯坦福CS520】向量空间中嵌入的知识图谱推理,48页ppt
专知会员服务
100+阅读 · 2020年6月11日
专知会员服务
30+阅读 · 2020年5月20日
斯坦福2020硬课《分布式算法与优化》
专知会员服务
118+阅读 · 2020年5月6日
【图神经网络(GNN)结构化数据分析】
专知会员服务
115+阅读 · 2020年3月22日
Transformer文本分类代码
专知会员服务
116+阅读 · 2020年2月3日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
95+阅读 · 2019年12月4日
Python用于NLP :处理文本和PDF文件
Python程序员
4+阅读 · 2019年3月27日
如何编写完美的 Python 命令行程序?
CSDN
5+阅读 · 2019年1月19日
已删除
AI科技评论
4+阅读 · 2018年8月12日
深度学习线性代数简明教程
论智
11+阅读 · 2018年5月30日
教程 | 如何通过PyTorch上手Tensor Comprehensions?
机器之心
5+阅读 · 2018年3月12日
学习|使用autograd来自动求导
全球人工智能
4+阅读 · 2017年11月27日
q-Space Novelty Detection with Variational Autoencoders
Meta-Learning with Latent Embedding Optimization
Arxiv
6+阅读 · 2018年7月16日
Bidirectional Attention for SQL Generation
Arxiv
4+阅读 · 2018年6月21日
Arxiv
4+阅读 · 2018年4月30日
Arxiv
3+阅读 · 2018年4月5日
VIP会员
相关VIP内容
[ICML-Google]先宽后窄:对深度薄网络的有效训练
专知会员服务
34+阅读 · 2020年7月5日
【斯坦福CS520】向量空间中嵌入的知识图谱推理,48页ppt
专知会员服务
100+阅读 · 2020年6月11日
专知会员服务
30+阅读 · 2020年5月20日
斯坦福2020硬课《分布式算法与优化》
专知会员服务
118+阅读 · 2020年5月6日
【图神经网络(GNN)结构化数据分析】
专知会员服务
115+阅读 · 2020年3月22日
Transformer文本分类代码
专知会员服务
116+阅读 · 2020年2月3日
【干货】大数据入门指南:Hadoop、Hive、Spark、 Storm等
专知会员服务
95+阅读 · 2019年12月4日
相关资讯
Python用于NLP :处理文本和PDF文件
Python程序员
4+阅读 · 2019年3月27日
如何编写完美的 Python 命令行程序?
CSDN
5+阅读 · 2019年1月19日
已删除
AI科技评论
4+阅读 · 2018年8月12日
深度学习线性代数简明教程
论智
11+阅读 · 2018年5月30日
教程 | 如何通过PyTorch上手Tensor Comprehensions?
机器之心
5+阅读 · 2018年3月12日
学习|使用autograd来自动求导
全球人工智能
4+阅读 · 2017年11月27日
相关论文
Top
微信扫码咨询专知VIP会员