一、漏洞的公开信息:查询
得知该漏洞允许远程攻击者在装有Adobe Flash Player的机器上执行恶意代码。通过访问一个恶意页面或者恶意文件这中用户交互方式来进行漏洞的溢出。漏洞存在于flash player解析流媒体的sequenceParameterSetNALUnit组件,由于num ref frames_ in pic_order_cnt_cycle设置了无效的数值造成解析进程没有检查就将用户提供的数据(通过offset_for_ref_frame)拷贝到堆栈上一段固定长度的缓冲区造成溢出。因此,攻击者可以在浏览器中通过此漏洞来执行恶意代码。
二、漏洞触发原因分析:
分析工具:IDA pr0 5.5+Ollylce l.1英文版分析环境:windows xp SP3英文版+ IE6+ Adobe Flash Player 10 ActiveX 10.2.159.1拿到POC之后,将POC放到一个搭建好的Web服务器指定目录下。用分析环境中的IE6访问POC所在的网址,比如本例中/raw. swf。产生异常.EIP此时为ODODODOD,堆栈ESP所指的内存区域如下图所示:
很显然,堆栈在触发异常时被特定的数据所覆盖,如图含有ODODODOD的二进制数据。通过栈回溯,我们找到最临近的调用函数:
在函数调用处设置断点,重启调试器加载IE6,打开指定网页(仍是http://xxx. com/raw. swf)。调试期果然断在断在指定断点处。(注意:flashlOp. ocx基址变化,可能是OxXXXX9675)通过一步步的跟踪,最后定位到距离异常最近的一个call上,我们设置这个函数为EvilTrigger。如下图所示:
在此,我们记录下函数返回地址保存的位置,稍后我们会发现,返回地址会被覆盖。
根据公开信息的提示,我们会猜测稍后在此函数中可能有内存拷贝操作会覆盖这个地址,我们在Ox0013e570处设置内存写入断点。调试器果然断下来了。
图5中的注释已经很明白,每次拷贝时,通过call 021eafed这个函数来设置eax,也就是拷贝的源数据。从esp+14地址处获取拷贝目的地址并保存到ecx中去,ebp作为counter,拷贝长度保存在esi+4c中,每次拷贝一个DWORD,然后拷贝目的地址加4。
既然拷贝目地地址到了函数返回地址保存的位置,本例中是Ox0013e570。那么说明这个往堆栈拷贝数据的操作中,拷贝长度过长。也就是本例中的[esi+4c]=Ox200。我们重启调试器,重点关注拷贝长度是如何获取的。
通过公开信息的提示,这个拷贝长度很可能是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之间取值,包括边界值。Ox200显然远大于这个值,造成了函数返回地址的覆盖,在函数执行返回时,EIP指向了拷贝的DWORD从而获得了执行控制权。
我们重启调试器让其加载IE6,观察拷贝长度的来源。在调试中我们发现拷贝长度保存的地址是固定的Ox0013e114。我在其上设置内存访问断点。果然,在相关地方断下来了。
021EBAIB 8946 50 mOv dword ptr[esi+50], eax 、 ‘’ 021EBA23 8946 4C mov dword ptr[esi+4C], eax 021EBA26 85CO test eax, eax 021EBA28 76 1F jbe short 021EBA49
上面红色标记的汇编指令call 021eafbe就是设置eax,下一句指令将eax赋值给[esi+4c],而这个正是拷贝长度所在内存地址。我们打开IDA,反汇编flashlOp. ocx,定位到函数021eafbe,通过F5翻译为C代码。如下所示:
unsigned int fastcall sub_ 1005AFBE (int al) { int vl;// edi@l unsigned irit nESI; // esi@l vl=al: nESI=0: while ( !(unsigned int8)sub_1005AEF4(al) && nESI < Ox20 ) { ++nESI: al=vl: ) return sub_1005AF23(vl, nESI) +(1<<nESI) -1: )
此函数最终设置了拷贝长度为Ox200,在拷贝过后,相关的堆栈内存状态如下所示:从Ox0013E120开始,拷贝到Ox0013e91c结束。此时查看Ox0013e91c处的内存状态:
函数EvilTrigger在返回时:
unsigned int fastcall sub_ 1005AFBE (int al) { int vl;// edi@l unsigned irit nESI; // esi@l vl=al: nESI=0: while ( !(unsigned int8)sub_1005AEF4(al) && nESI < Ox20 ) { ++nESI: al=vl: ) return sub_1005AF23(vl, nESI) +(1<<nESI) -1: )
此时堆栈的状态如下图所示:
最终程序流程跳转到OxOdOdOdOd上去执行。
三、漏洞利用技术分析:
本例中没有找到稳定的IE8、IE9利用,由于该漏洞能控制EIP指向,只需要通过堆喷射来设置指定地址的堆内容数据,填充shellcode即可利用。但是如果开通了DEP/ASLR,则目前没有稳定的利用。
目前堆喷射有两种模式,一种为在网页中通过进行喷射,另外一种是基于flash的ActionScript喷射。目前比较流行第二种。
四、shellcode分析:
在Ox021E3D8A处设置断点,去除掉所有其他断点。重新启动调试器加载IE并打开指定网页。在断点处成功断下后单步跟踪,EIP指向了OdOdOdOd。由于喷射已然完成,成功跳转到shellcode上执行:
ODOD3F34 /EB 10 jmp short ODOD3F46 ODOD3F36 5B pop ebx ODOD3F37 4B dec ebx ODOD3F38 33C9 xor ecx, ecx ODOD3F3A 66:B9 9904 mov cx, 499 ODOD3F3E 80340B E2 xor byte ptr [ebx+ecx], OE2 ODOD3F42 -IE2 FA loopd short ODOD3F3E ODOD3F44 EB 05 jmp short ODOD3F4B ODOD3F46 \E8 EBFFFFFF call ODOD3F36
上面是一段解密程序,将OxOdOd3f34开始的数据逐字节与OxOE2异或。我们查看异或后shellcode尾部,发现了端倪:
出于安全性的考虑,事例中已经将exe地址全部修改为http://127.0.0.1/calc. exe。以防止出现不必要的麻烦。接下来就是获取相关需要的函数,然后下载恶意exe到本地并执行。就不赘言分析了。有兴趣者可以自行分析。
本文为网络安全技术研究记录,文中技术研究环境为本地搭建或经过目标主体授权测试研究,内容已去除关键敏感信息和代码,以防止被恶意利用。文章内提及的漏洞均已修复,在挖掘、提交相关漏洞的过程中,应严格遵守相关法律法规。