CVE-2011-2140 Flash漏洞分析
前置知识:汇编
关键词:Flash,漏洞,溢出
图/文 wingdbg
漏洞的公开信息
查询Uhttp://www.zerodayinitiative.com/advisories/ ZDI-11-276/U 得知该漏洞允许远程攻击者在装有Adobe Flash Player的机器上执行恶意代码。通过访问一个恶意页面或者恶意文件这中用户交互方式来进行漏洞的溢出。
漏洞存在于Flash Player解析流媒体的sequenceParameter SetNALUnit组件,由于num_ref_frames_in_pic_order_ cnt_cycle设置了无效的数值造成解析进程没有检查就将用户提供的数据(通过offset_for_ref_frame)拷贝到堆栈上一段固定长度的缓冲区造成溢出。因此,攻击者可以在浏览器中通过此漏洞来执行恶意代码。
漏洞触发原因分析
分析工具:IDA pro 5.5 + OllyIce 1.1 英文版
分析环境:Windows XP SP3 英文版 + IE6 + Adobe Flash Player 10 ActiveX 10.2.159.1
拿到POC之后,将POC放到一个搭建好的Web服务器指定目录下。用分析环境中的IE6访问POC所在的网址,比如本例中 http://xxx.com/raw.swf。产生异常,EIP此时为0D0D0D0D,堆栈ESP所指的内存区域如图1所示。
图1 异常时堆栈窗口
很显然,堆栈在触发异常时被特定的数据所覆盖,如图2所示,含有0D0D0D0D的二进制数据。通过栈回溯,我们找到最临近的调用函数。
图2 栈回溯函数地址
在函数调用处设置断点,重启调试器加载IE6,打开指定网页(仍是http://xxx.com/raw.swf)。调试期果然断在指定断点处。(注意:flash10p.ocx基址变化,可能是0xXXXX9675)
通过一步步的跟踪,最后定位到距离异常最近的一个call上,我们设置这个函数为EvilTrigger。如图3所示。
图3 异常产生所在的函数
在此,我们记录下函数返回地址保存的位置,如图4所示。稍后我们会发现,返回地址会被覆盖。
图4 异常前esp所指栈内存状态
根据公开信息的提示,我们会猜测稍后在此函数中可能有内存拷贝操作会覆盖这个地址,我们在0x0013e570处设置内存写入断点。调试器果然断下来了。
图5中的注释已经很明白,每次拷贝时,通过call 021eafed这个函数来设置eax,也就是拷贝的源数据。从esp+14地址处获取拷贝目的地址并保存到ecx中去,ebp作为counter,拷贝长度保存在esi+4c中,每次拷贝一个DWORD,然后拷贝目的地址加4。
图5 堆栈拷贝的指令操作
既然将目的地址拷贝到了函数返回地址保存的位置,本例中是0x0013e570。那么说明这个往堆栈拷贝数据的操作中,拷贝长度过长。也就是本例中的[esi+4c] = 0x200。我们重启调试器,重点关注拷贝长度是如何获取的。
通过公开信息的提示,这个拷贝长度很可能是num_ref_ frames_in_pic_order_cnt_cycle这个值,num_ref_frames_in_pic_ order_cnt_cycle在解码过程中被用来计算图像顺序值。num_ref_frames_in_pic_order_cnt_cycle在0到255之间取值,包括边界值。0x200显然远大于这个值,造成了函数返回地址的覆盖,在函数执行返回时,EIP指向了拷贝的DWORD,从而获得了执行控制权。
我们重启调试器让其加载IE6,观察拷贝长度的来源。在调试中我们发现拷贝长度保存的地址是固定的0x0013e114。我在其上设置内存访问断点。果然,在相关地方断下来了。
021EBA1B 8946 50 mov dword ptr [esi+50], eax 021EBA1E E8 9BF5FFFF call 021EAFBE 021EBA23 8946 4C mov dword ptr [esi+4C], eax 021EBA26 85C0 test eax, eax 021EBA28 76 1F jbe short 021EBA49
上面红色标记的汇编指令call 021eafbe就是设置eax,下一句指令将eax赋值给[esi+4c],而这个正是拷贝长度所在内存地址。我们打开IDA,反汇编flash10p.ocx,定位到函数021eafbe,通过F5翻译为C代码。如下所示:
unsigned int __fastcall sub_1005AFBE(int a1) { int v1; // edi@1 unsigned int nESI; // esi@1 v1 = a1; nESI = 0; while ( !(unsigned __int8)sub_1005AEF4(a1) && nESI < 0x20 ) { ++nESI; a1 = v1; } return sub_1005AF23(v1, nESI) + (1 << nESI) - 1; }
此函数最终设置了拷贝长度为0x200,在拷贝过后,相关的堆栈内存状态如图6所示。
从0x0013E120开始,拷贝到0x0013e91c结束。此时查看0x0013e91c处的内存状态:
图6 拷贝结束后堆栈内存状态
函数EvilTrigger在返回时:
021E3D84 B0 01 mov al, 1 021E3D86 5F pop edi 021E3D87 5E pop esi 021E3D88 5B pop ebx 021E3D89 C9 leave 021E3D8A C2 0800 retn 8
此时堆栈的状态如图7所示。
图7 EIP的终极跳转
最终程序流程跳转到0x0d0d0d0d上去执行。
漏洞利用技术分析
本例中没有找到稳定的IE8、IE9利用,由于该漏洞能控制EIP指向,只需要通过堆喷射来设置指定地址的堆内容数据,填充Shellcode即可利用。但是如果开通了DEP/ASLR,则目前没有稳定的利用。
目前堆喷射有两种模式,一种为在网页中通过JavaScript进行喷射,另外一种是基于Flash的ActionScript喷射。目前比较流行第二种。
Shellcode分析
在0x021E3D8A处设置断点,去除掉所有其他断点。重新启动调试器加载IE并打开指定网页。在断点处成功断下后单步跟踪,EIP指向了0d0d0d0d。由于喷射已然完成,成功跳转到Shellcode上执行:
0D0D3F34 /EB 10 jmp short 0D0D3F46 0D0D3F36 |5B pop ebx 0D0D3F37 |4B dec ebx 0D0D3F38 |33C9 xor ecx, ecx 0D0D3F3A |66:B9 9904 mov cx, 499 0D0D3F3E |80340B E2 xor byte ptr [ebx+ecx], 0E2 0D0D3F42 ^|E2 FA loopd short 0D0D3F3E 0D0D3F44 |EB 05 jmp short 0D0D3F4B 0D0D3F46 \E8 EBFFFFFF call 0D0D3F36
上面是一段解密程序,将0x0d0d3f34开始的数据逐字节与0x0E2异或。我们查看异或后Shellcode尾部,发现了端倪:
出于安全性的考虑,事例中已经将exe地址全部修改为http://127.0.0.1/calc.exeU1T,如图8所示。
图8 Shellcode中下载exe的地址
以防止出现不必要的麻烦。接下来就是获取相关需要的函数,然后下载恶意exe到本地并执行,就不赘言分析了,有兴趣者可以自行分析。
小结
Flash漏洞是近期比较流行的,单是从2011年8月9日一直到2011年8月12日,Adobe一口气就一下子公布了CVE-2011-2130, CVE-2011-2134, CVE-2011-2135, CVE-2011-2136, CVE-2011-2137, CVE-2011-2138, CVE-2011-2139, CVE-2011-2140, CVE-2011-2414, CVE-2011-2415, CVE-2011-2416, CVE-2011-2417, CVE-2011-2425, CVE-2011-2424这几个漏洞。2140只是其中一个代表之一(详见Uhttp://www.adobe.com/support/security/bulletins/apsb11-21.htmlU)。
其中大多是Flash Player在处理流媒体时代码缺陷导致的。比如本例中是处理avi文件时对拷贝长度不做有效性检测导致的。足见安全性编程的重要性,相信经此一役,Adobe公司要对Flash Player进行重新加固了,甚至重写代码。我们拭目以待。