【AICon】探索RAG 技术在实际应用中遇到的挑战及应对策略!AICon精华内容已上线73%>>> 了解详情
写点什么

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

  • 2015-07-29
  • 本文字数:5286 字

    阅读完需:约 17 分钟

声明:为了更好地向读者输出更优质的内容,InfoQ 将精选来自国内外的优秀文章,经过整理审校后,发布到网站。本篇文章作者为乌云白帽子 blast,原文链接。本文是《IE 安全系列》第四篇,已由乌云网授权InfoQ 中文站转载。欢迎转发,但请保留原作者信息!


作者 blast

正文

接着上一篇的来,本文多为JavaScript 的脚本阅读和解释,阅读都是自行完成,所以不免可能会出现一些错误或者联想过度的情况,如果你发现了哪儿有问题请重重地拍出来。

1、HTML 与网马攻击 4 — Virus In the Wild

本篇中我们将从真实的 Exploit Kit 的利用代码入手介绍分析方式,文中例子采用 Angler Exploit Kit 和 Magnitude Exploit Kit(下简称为 AEK 和 MEK)在 2015 年 4 月初最新的代码。

AEK 和 MEK 是互联网上最著名的漏洞利用工具包,在 Phoenix Exploit Kit 作者锒铛入狱之后,这两个 Exploit Kit 的“市场份额”一下子窜到了前面,因为作者更新快,采用加密方式繁多,导致杀毒软件更新特征也较为困难,这让它们有充足的机会去攻击有漏洞的电脑。本文将介绍这两个 Exploit Kit 的加密方式和解密方法。

首先,让我们从 AEK 开始,AEK 和 MEK 都需要有一个 Landing Page,用于将用户定向到恶意页面上,打开 Landing Page,我们会发现 AEK 为了做混淆,给 Landing Page 加了很多无用的垃圾数据,并将加密后的数据混淆插入在这些代码中:

(点击放大图像)

图:code 部分是加密后的代码

将页面向下拖动,快到最后的地方就是它的解密脚本了:

图:AEK 的脚本

是的,这就是一个高度混淆后的脚本,因为JavaScript 代码(或者说类C 语言语法)的宽松性,作者在这里面使用了大量的空白、回车、缩进符,同时还替换了变量名,使用大量的数学函数来做混淆。

对于人来说,要阅读这样的代码简直是一个非常恶心的工作,所以在此推荐使用一些代码规范化工具,例如Malzilla 提供的JS 标准化,或者这里还有一个小技巧:使用Notepad++ 或者类似工具的括号匹配功能:

将光标移动到function 的大括号处,此类软件会自动标示出函数范围,可见上图中该函数范围是LN268-LN385。这样,我们就能清晰的知道这个代码的结构了:

而之前我们也说过,Function 除外的Global 代码,会从上往下执行,因此,攻击者如果想要实现读取- 解密- 执行的步骤,执行必然是最后一步,因此我们只需要在它执行之前将要执行的数据找到即可。

翻到最后,可以发现LN568-574 的Script 段其实和上面LN558-565 几乎一样。这意味着这段代码很可能包含着解密和执行两步的内容。

从最后一句入手,

LN564:

复制代码
rqNNhndhLxLVVb[nmfAbWwoA]('TQgaaGLDVYlaQT',QXuSacI)

逐个查看变量的作用,

LN267 表明:

复制代码
rqNNhndhLxLVVb = window;

这是因为 JavaScript 中允许将任何对象赋值给某个变量,因此 rqNNhndhLxLVVb 此时实际上可以看作是 window 的“别名”或者“同义词”。

看看第二个变量 nmfAbWwoA 的来源:

LN561 可以发现是该变量的第一次使用的地方:

复制代码
nmfAbWwoA = "ezVI"+"Migbc".substr(6,8) //ezVI
nmfAbWwoA = nmfAbWwoA+[].join(dLpy) + "xlyG"

变量 dLpy 经过阅读可知在:

LN437 处赋值:

复制代码
dLpy= ('EoVzQHTfRyGU').substr(12,12) //””

因此 nmfAbWwoA 的值实际上只是“ezVIxlyG”。

第三个变量: LN558 可以发现是该变量第一次赋值的地方:

复制代码
var QXuSacI;
QXuSacI= ['Y', 'r', 'a', 'd', 'P'].join(dLpy)

由于 dLpy 我们已经知道是空字符了,所以实际上 QXuSacI 的值就是”Yradp”。

这样,将三处组合,LN564 的原始语句实际上是:

复制代码
window[”ezVIxlyG”]('TQgaaGLDVYlaQT', ‘Yradp’);

这个 ezVIxlyG 的原型是什么呢?搜索代码,找到它的赋值点:

LN438:

复制代码
var D1Kx;
ezVIxlyG= !!D1Kx?true:( function (){ ……} );

这里有一个约定俗成的内容,可以看到 D1Kx 是刚刚定义而且未赋值的,将其作为布尔型来处理时,其默认值是 false,因此,!!D1Kx 的值实际也是 false。

这样该三目表达式实际上只是相当于一个普通的赋值:

复制代码
ezVIxlyG = function(){……}

由于此时我们还没处理该函数,因此这个混淆后的代码应该是十分难读的,所以,我们对其进行一个简单的处理: 复制 LN439-545

  • 替换所有双空格、三空格 -> 单空格,直到没有 2 个以上连续空格为止。
  • \n、\r 全部删除
  • 使用工具将代码重新格式化。

完成后,代码如下所示:

(点击放大图像)

可见代码还是难以理解,这是因为其中包含了大量的变量:

你可以看到这个地方定义的变量大部分都会分散地被之后的代码使用到。

所以我们要关注的还是函数的最后:

复制代码
if(flag == 1)
{
rqNNhndhLxLVVb [YPub] ( UjcS )
}
else
{
rqNNhndhLxLVVb [YPub] ( UjcS )
}

这里又是一个无用分支,rqNNhndhLxLVVb 我们已经知道是 window 对象了,YPub 是什么呢,可以看看上面的代码,最好倒着看,我的注也是从 5 开始倒着写到 1 处的,请注意:

复制代码
YPub=tP+yMwnso (注:eval)
tP= 'e' 、 yMwnso= ('Rv'+('uapt') ['re'+'place'] ( 'u', dLpy)) [iCQl0] ( K1DMU, 2 ) +'l' (注:val)
iCQl0= (wRxKW+'snubnstrn') [F9k2c] ( /n/g , qm3sXy) (注:substr)
F9k2c=qm3sXy+'r'+ yMwnso + 'pl' + qm3sXy + 'ac' +yMwnso (注:replace)
K1DMU=3-2

因此我们看到了这句实际上是:

复制代码
window[”eval”](UjcS);

现在知道做什么了吗?对,先把 eval 换成 alert!

然后,直接运行该 HTML,得到解密后数据:

(点击放大图像)

等等,共4 次,将这些内容合起来就是解密后的代码了。可以看到这个代码利用了多个新漏洞,甚至包括卡巴斯基控件的安全漏洞。

2、HTML 与网马攻击 5 - Virus In The Wild

让我们再看看 Magnitude Exploit Kit 这款 EK 的代码,相比 AEK 而言,难度是高还是低。

(点击放大图像)

图:MEK 的Landing Page

可以看出来,相比而言它的代码貌似要简单得多,可以清晰的看到document 和eval 被分别赋予了两个不同的变量。

通过将eval 修改为alert,执行后得到:

完了?显然没有,将eval 换成alert 之后得到的数据是一个function,而点击确定之后,得到了一个脚本错误:

图:脚本错误

仔细阅读一下,首先,这个eval 的范围是:

(点击放大图像)

在它之后出现了一个从未见到过的函数:

(点击放大图像)

而对比我们之前弹出的alert 可以发现,这个函数就是eval 解出来的结果,因此,我们应该做的是把eval 部分换成解密后的内容:

复制代码
function t1g6(a,b){var inn =
document.getElementById('avp6').innerText;var out='';var
c=inn.split('*');for(var k=a;k<b;k++) out +=
String.fromCharCode(c[k]-21);return out;}

用上述内容替换掉 eval 块,得到:

(点击放大图像)

但是之后显然没有eval 了,这时,其实我们只需要了解document[”XXX”] 将返回document 下的XXX 对象,这个对象是可以作为函数来调用的(或者不如说函数就是一个对象:) )就可以了:

(点击放大图像)

因此后面的c1h82by0(document)就显得很是危险,所以让我们看看s4tb[0] 的内容并注释掉后面的内容,记得之前说的嘛?一个script 块中的代码一直到出错为止都是可以正常运行的,所以不用管之后的代码会不会出错了,主要是后面的代码很可能是恶意代码,不能让恶意代码在我们自己的电脑上跑起来。

图:执行结果

因此,可以知道这里是在做document[“createElement”] 这个操作,司马昭之心,路人皆知,再将其内容改为alert(s4tb1),执行可得:

图:执行结果

串上后面的内容可以知道,这段代码事实上正在创建一个iframe,其src 执行漏洞代码页面: hXXp://bf29df.e66.83.1c.3d8a.54.1393d.bc7dc6b.6.scg512374t1.changesmoves.in/47b1d0b4466375c9306821f48abcd6b5(放心,此时这个网站已经无法访问了。)

至此,这个页面的核心内容我们已经全部了解了,至于后面的几个变量,解法也是一样的,如果想要练手的话,可以试着将页面内容全部还原成无混淆状态试试看。页面内容见附件(密码drops.wooyun.org )。

3、HTML 与网马攻击 6- 利用 arguments.callee 实现“递归解密”的网马以及解密

希腊神话中有一条名为 Ouroboros 的蛇,它咬着自己的尾巴,它的姿态象征着“不死”、“完全、“无限”、“世界”、“睿智”等种种意味。

图:乌洛波洛斯,网络图

在编程中,称作递归,递归在 JavaScript 中可以像 C 的代码一样来调用:

复制代码
function a(){ a();}

不仅如此,JavaScript 还支持一种 arguments.callee 的方式来调用。callee 为对当前函数的引用,故可以作为类似递归的方式来调用自身。

不过,递归还是需要谨慎的,稍有不慎,一个 bug 即可导致整个程序出现不可知的情况。

图:IE10 递归导致死循环,栈空间全部用完导致崩溃

言归正传,先让我们看两个例子大致理解一下普通递归和 arguments.callee:

以下两个例子输出均为:1 2 3。

普通递归,

复制代码
function mylog(current, max)
{
if(current <= max)
{
console.log(current);
add(current+1, max);
}
}
mylog(1,3);

以及 arguments.callee:

function f(x)
{
console.log(x);
return arguments.callee;
}
f(1)(2)(3);

从实际入手吧,请参考如下网马的例子:

(点击放大图像)

是否第一眼就看到了倒数第二行出现了

eval(I3qVh4gPT);

如果你试图将它改为 alert(I3qVh4gPT);,那么这个函数的解密结果必然会失败:

(点击放大图像)

原因是什么呢?请看第一行出现了。

复制代码
v ar
eJmF3VT3H=arguments.callee.toString().replace(/\W/g,'').toUpperCase();

我们知道 arguments.callee 是对当前函数的引用,那么这个引用转为字符串是什么呢?让我们测试一下:

原来就是返回了当前函数。

仔细一看,这里会把函数自己当成参数来解密。

所以,如果我们想要解开这个脚本的加密应该怎么弄呢?

A、简单阅读代码

从最后来,

①eval(I3qVh4gPT); 引用了变量 I3qVh4gPT。

②I3qVh4gPT+=String.fromCharCode(EHxDfdAM5); 引用了变量 EHxDfdAM5。

③EHxDfdAM5=e3FP5e1M6-IA17ef3d3[bqjtxUvBR];if(EHxDfdAM5<0) {EHxDfdAM5=EHxDfdAM5+256;} 引用了变量 e3FP5e1M6、IA17ef3d3[0]。

④e3FP5e1M6=parseInt(EWX1TnOBq,16); 引用了变量 EWX1TnOBq,将其作为十六进制解析。

⑤var EWX1TnOBq=mXSYkqH0X.substr(PwgNCEKQL,2); 中,mXSYkqH0X 是参数,PwgNCEKQL 是计数器。

⑥for(PwgNCEKQL=0;PwgNCEKQL

⑦Oq32NWn5D=mXSYkqH0X.length; ,也即参数的长度,因此,这段代码在解密传入的参数。

还有,③中出现了另一个变量 IA17ef3d3,这个变量出现在⑧IA17ef3d3[PwgNCEKQL]=fgMN0vK2r.charCodeAt(va31p5um0);,这之中还引用了 fgMN0vK2r、va31p5um0 两个变量

⑨fgMN0vK2r=RsIkkqdYi[(fgMN0vK2r^eJmF3VT3H.charCodeAt(gMKy026SO))&255]^((fgMN0vK2r>>8)&16777215); 中出现了 fgMN0vK2r。RsIkkqdYi 是一个预设密钥组,eJmF3VT3H 是当前函数(arguments.callee.toString() 等处理后的结果),gMKy026SO 是计数器。因此这句是在基于一个密钥组产生一个密钥组;

⑩for(PwgNCEKQL=0;PwgNCEKQL<8;PwgNCEKQL++) {var va31p5um0=Oq32NWn5D+PwgNCEKQL;xy3D07u0l[PwgNCEKQL]=1;xy3D07u0l[PwgNCEKQL]=FSB4JaYie;if (va31p5um0>=8) {va31p5um0=va31p5um0-8;IA17ef3d3[PwgNCEKQL]=fgMN0vK2r.charCodeAt(va31p5um0);} 同样,va31p5um0 也在参与解密。

也即,将传入参数每隔 2 个字符作为一个 HEX,然后解出来,与将函数自身的字符串通过解密算法解出来的数据相减,两者结果小于 0 的话,加上 256,最终对所有字符都如此操作,将结果连接起来得到解密数据。

既然函数本身不能轻易修改,那么只好从最终的 eval 做突破了,JavaScript 中允许“劫持”一个对象。即和操作普通变量的赋值一样,函数也是可以通过赋值来覆盖的,请看第二部分。

B、函数劫持

(点击放大图像)

针对这个代码,因为最终它会通过eval 来运行恶意代码,所以添加eval=alert,在运行到eval 之前将其劫持即可。

运行代码可以得到:

(点击放大图像)

最后,总结一下,在 Jscript9.dll 中,脚本的函数中调用 arguments.callee.toString() 时,大致经历了如下几个步骤:

  • 解析脚本文字(ScriptSite::ParseScriptText);
  • 送与解析内核,生成字节码,通过字节码解释器(即 Intepreter)来执行;
  • 在处理到 arguments.callee.toString() 时,jscript 会将函数自身 marshal 成 BSTR,然后转换成 JsVar,传递给后续要使用它的代码。

题外话,这个代码其实是 2010 年发现的一个广告软件(是当时流行的 Rogue antivirus,也就是伪装成杀毒软件的广告程序)安装页的 Landing Page,当时我还特地上论坛和大家讨论了怎么解决,大家给出的思路也相当多,除了上述我说的方法之外,一些自动化解密工具也可以处理此类网马,例如 Malzilla 。不过建议大家不要过于依赖工具,而是把工具当作可以简化重复劳动的工具是最好。

到此为止,脚本先锋系列的解密部分就告一段落了,下一篇开始,将简单的介绍调试器的用法以及如何对网马中使用的 Shellcode 进行调试,其中也包括简单的对恶意 SWF、PDF 的分析的内容。

参考资料

  1. 文中恶意脚本打包下载,请在虚拟环境下测试与调试(密码 drops.wooyun.org )

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

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

2015-07-29 06:591424

评论

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

大模型时代下的我们,破茧重生探索新开发范式!|WAVE SUMMIT 开源论坛

飞桨PaddlePaddle

人工智能 百度 开发者 百度飞桨 WAVE SUMMIT

关于MYSQL引擎在物理层面存储那些事

谐云

SpringBoot+Vue3打造企业级一体化PaaS系统

高端章鱼哥

Vue PaaS spring-boot JNPF

有自动化运维功能的堡垒机有哪些?大家推荐哪款?

行云管家

高可用 堡垒机 IT运维 自动化运维

断点重传、错误自动重传,优秀的文件传输工具应该具备这些特性

镭速

文件传输 文件传输工具

【华秋推荐】新能源汽车中的T-BOX系统,你了解多少?

华秋电子

新唐

探索未知,即刻搭建AI原生应用!WAVE SUMMIT Workshop等你来参加

飞桨PaddlePaddle

人工智能 百度飞桨 百度AI WAVE SUMMIT

基于卷积神经网络的MAE自监督方法

华为云开发者联盟

人工智能 华为云 华为云开发者联盟 企业号 8 月 PK 榜

如何选择适合自己的文件传输工具

镭速

文件传输 文件传输工具

【您的意见很重要】天翼云文档“找茬”活动

天翼云开发者社区

云计算

TIKV节点数据文件误删后不更换服务器快速恢复

TiDB 社区干货传送门

管理与运维 故障排查/诊断

Placement Rules in SQL 使用案例

TiDB 社区干货传送门

新版本/特性解读 6.x 实践

环路检测在风控领域的应用实践丨 Fabarta 技术专栏

Fabarta

大数据 算法 图分析 智能风控 风控算法

用于共享大文件的4种大文件传输工具和软件

镭速

大文件传输软件

支付宝小程序云云测产品最佳实践

TRaaS

支付宝小程序 支付宝 IoT

与传统IT开发相比,低代码开发具备哪些优势?

互联网工科生

低代码 应用开发 私有化部署 可视化引擎 JNPF

TiDB 源码编译之 TiUP 篇

TiDB 社区干货传送门

版本测评 新版本/特性解读 7.x 实践

直播源码连麦技术功能分享,你要的这里全有

山东布谷网络科技

直播源码

GaussDB(DWS)函数不同写法引发的结果差异

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号 8 月 PK 榜

基于大模型的数据血缘异常归因分析

奇点云

元数据 黑客马拉松 奇点云 对象体系

Lighting web 测试使用

TiDB 社区干货传送门

迁移 管理与运维 备份 & 恢复 6.x 实践

智慧云 打造您的商城APP,与5G时代社交电商融为一体

知者如C

直播|深入解析 StarRocks 存算分离--云原生湖仓 Meetup#2

StarRocks

数据库 云原生 存算分离 国产数据库 湖仓一体

Photoshop Elements 2020 for Mac(图形处理工具) v18.0(2020.01.20)激活版

mac

苹果mac Windows软件 Photoshop Elements 2020 ps elements 2020

软件研发的道德情操

阿里技术

研发 软件研发

AirServer 7 for Mac(Mac专用投屏工具) v7.2.6激活版

mac

AirServer 投屏软件 苹果mac Windows软件

新利好带动 POSE 持续上扬,月内几近翻倍

西柚子

INFINI Labs 产品更新 | Easysearch 支持 SQL 查询、Console 告警功能支持邮件等多渠道

极限实验室

sql console 邮件 告警 easysearch

安全易用的运维会诊平台选哪家?可以免费试用吗?

行云管家

运维 IT运维 运维会诊

情景规划与财务建模2.0,如何促进企业全面预算管理的实施

智达方通

智达方通 全面预算管理 财务建模 情景规划

MES系统可解决方案

万界星空科技

MES系统

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