手把手一起分析最新Flash样本
标签:
杂谈 |
友情提示:
1.
写这篇文章的目的是想简单介绍一下Flash样本分析的流程,以及一些分析Flash样本常用的工具包括自己写的小程序。
本文涉及的内容包括:Flash文件的提取、结构查看、ActionScript的反汇编和反编译、ActionScript中shellcode的定位和提取、shellcode调试。
本文不会涉及对漏洞成因进行分析调试的相关内容。
2.
本文中使用是一个利用CVE-2012-0754漏洞的Flash样本,还算是比较新的Flash漏洞样本。
样本来源是:ContagioDump
这里向大家推荐一下这个blog,该blog经常会放出一些最新的病毒样本,仔细挖掘的话还能找到一些样本的合集,非常有用。
不过国内应该无法直接访问,需要翻墙先。懒得翻墙的同学,我把样本打包传到附件里了,可以直接下载附件。
3.
下载样本解压后,原始样本在original文件夹中,名为“Iran's
等等,不是Flash样本吗,怎么是doc文件?你可能在想LZ是不是发错链接了。
其实真正的Flash样本是嵌在这个doc文件中的,这种手法并不是第一次被使用了,当年CVE-2010-0609(没记错的话)样本也是嵌在Excel文件里流出的。
打开word文档的话最后会有一只貌似熊(??)的谜样生物对你说“Hi~”,LZ觉得好诡异。。。
https://lh4.googleusercontent.com/-h6vUamwIxb0/T1rVki_DKBI/AAAAAAAAAKI/MT77Z1nJglU/s284/image001.jpg
用16进制编辑器打开word文档,可以看到该文件是OLE
这种情况下,一般直接搜索字符串“FWS”(未压缩的SWF头部特征)和“CWS”(压缩过的SWF头部特征)就可以定位其中的Flash文件。
https://lh4.googleusercontent.com/-t9wSfcqWRMI/T1rVlE1dImI/AAAAAAAAAKU/fdpuzbS2boo/s512/image002.jpg
我写了一个python小脚本,用来从Office文档中提取内嵌的Flash文件,名为extract_swf.py,使用方式如下:
Code:
extract_swf.py[office文件路径]
Code:
C:\CVE-2012-0754_E92A4FC283EB2802AD6D0E24C7FCC857\original\extract_swf>extract_s
wf.py"C:\CVE-2012-0754_E92A4FC283EB2802AD6D0E24 C7FCC857\original\Iran's Oil and
Nuclear Situation.doc_"
Code:
extract_swf.py 1.0
[+] Searching embeded swf file in C:\CVE-2012-0754_E92A4FC283EB2802AD6D0E24C7FCC
857\original\Iran's Oil and Nuclear Situation.doc_
[+] Find embeded swf file at offset 0x2e08
[+] Save embeded swf file to C:\CVE-2012-0754_E92A4FC283EB2802AD6D0E24C7FCC857\o
riginal\Iran's Oil and Nuclear Situation.doc__offset_0x2e08.swf=
4.
下面要重点介绍的是Adobe
功能十分强大,可以查看Flash文件结构、反汇编ActionScript、编译ActionScript、直接运行flash、甚至可以用来Fuzz
是不是有点心动了呢,猛击如下链接下载吧:[下载SWF
使用SWF
将前面提取出来的SWF文件拖到SWF
点击“Tag
选中DoABC2标签后,可以在右侧窗口中看到反汇编后的ActionScript代码,下图中一连串的pushint…writeInt其实是在做heap
https://lh4.googleusercontent.com/-Vm_YbDXAD3A/T1rVmVJAL2I/AAAAAAAAAKc/-ls_y1GF2oU/s496/image003.jpg
直接看字节码有点吃力,这时我们需要一个ActionScript
5.
这里使用的工具是AS3
也可以使用Sothink
将前面提取出的SWF文件拖入AS3
ActionScript
https://lh3.googleusercontent.com/-5-6Ljj3Sitg/T1rVnL-ASHI/AAAAAAAAAKg/RbzsV9g6Am0/s512/image004.jpg
通过分析源代码可以看出,这里的_local2变量中包含shellcode数据。
_loca2写入shellcode的流程如下:
1.首先定义_local2,类型为为ByteArray(字节数组)
2.使用一系列的writeInt函数调用写入数据
3.调用自定义的Encrypt2函数解密出真正的shellcode。
相关代码整理如下:
Code:
var _local2 = new ByteArray();
_local2.endian = Endian.LITTLE_ENDIAN;
_local2.writeInt(2590463591);
_local2.writeInt(213916234);
_local2.writeInt(3076656754);
_local2.writeInt(1088421207);
_local2.writeInt(700118367);
……………………
Encrypt2(_local2);
1.读懂整个逻辑包括Encrypt2函数,使用自己熟悉的编程语言还原整个逻辑,得到shellcode数据。
这种方法的缺点在于,如果shellcode生成逻辑非常复杂,还原成其他语言的难度会很大。
2.直接执行相应的ActionScript,打印出shellcode数据
这里我们将介绍第二种方法。
6.
SWF
选中菜单中的Utilities
下面我们开始准备要运行的脚本,首先加入如下代码:
Code:
namespace ns = "utils.AS3Compiler";
use namespace ns;
namespace nu = "flash.utils"
use namespace nu;
var HexChr:Array=new Array();
HexChr[0] = '0';HexChr[1] = '1';HexChr[2] = '2';HexChr[3] = '3';HexChr[4] = '4';HexChr[5] = '5';HexChr[6] = '6';HexChr[7] = '7';HexChr[8] = '8';HexChr[9] = '9';HexChr[10] = 'A';HexChr[11] = 'B';HexChr[12] = 'C';HexChr[13] = 'D';HexChr[14] = 'E';HexChr[15] = 'F';
public function Bin2HexString(arr:ByteArray):String
{
var str = "";
var len = arr.length;
var i = 0;
while (i < len) {
var b = arr[i];
str += HexChr[(b >> 4) & 0xf];
str += HexChr[b & 0xf];
i ++;
}
return str;
}
下一步需要把和_local2相关的代码和Encrypt2函数的代码复制进来,注意去掉Encrypt2函数定义中的“static”属性。
最后加入如下代码来打印出_local2中的数据:
Code:
Printer.print(Bin2HexString(_local2));
将完整的代码拷贝到AS3
https://lh4.googleusercontent.com/-PtXnru6JXVE/T1rVn1hKpeI/AAAAAAAAAKo/ESb8ErlUjv0/s512/image005.jpg
7.
将前面输出地shellcode字符串在转换成二进制数据(附件中的sc.bin),就可以开始调试了。
调试shellcode大家各有各的工具和方法,我使用的是自己写的一个名为ShellcodeDbg小工具。
用什么工具调无所谓,唯一要注意的是,在调试文档类shellcode时需要在调试进程中先打开原始文档,并保留这个原始文档的句柄,理由接下来会说明。
将OllyDbg设置为即时调试器,运行ShellcodeDbg.exe
跳过这个Int3断点后,单步几下,最后一个jmp
Shellcode一开始无非是解密,获取API地址等例行公事,接着可以看到这样一个循环:
Code:
00343E1B33DB xor ebx, ebx
00343E1D83C3 04 add ebx, 4
00343E206A 00 push 0
00343E2253 push ebx
00343E23FF57 FC call dword ptr [edi-4] ; kernel32.GetFileSize
00343E263B07 cmp eax, dword ptr [edi]// edi=01a06c,即原始doc文件的大小
00343E28^ 75 F3 jnz short 00343E1D
上述代码循环测试文件句柄值(从4开始),并使用对应句柄值来调用GetFileSize,并查看返回的size是不是等于01a06c(原始doc文件的大小),找到了合适的句柄才会继续运行。
这是文档类样本shellcode的常见行为,因为很多时候原始文件中包含进一步的shellcode或者PE文件数据,shellcode需要从中提取这些数据。
这就是为什么我们一开始讲要打开并保留一个原始文档句柄的理由了。
shellcode之后的代码,以及随后生成的PE文件的行为这里就不讲了,有兴趣的同学自己玩吧。
最后是本文中用到的相关文件包括原始样本,解压密码为:

加载中…