-
-
[翻译]通过Javascript中的CFI实现混淆阻止解密分析
-
发表于:
2018-4-6 17:19
7793
-
[翻译]通过Javascript中的CFI实现混淆阻止解密分析
能够读懂恶意软件的代码对于恶意软件分析来说是一个绝好的方式,因为它使我们能够了解恶意软件的真实行为。不幸的是,并不是在任何时候我们都能够获得恶意软件的实际代码,比如在分析的时候可能需要使用反汇编工具和调试器来猜测恶意软件的行为。然而,当样本是由解释性语言,比如Java、JS、VBS、.NET等写成时是存在几种方法来阻止获知源代码的。
由于攻击者知道安全人员常使用的一些分析技术,因而会使用一些混淆技术来使理解和分析变得困难。存在一种技术可以检测代码是否运行在虚拟机中或者可以保证代码只有在指定的环境下才能运行,并且可以避免调试器链接和反汇编引擎分析。
今天的文章就是关于这一点,我想向读者介绍一种有趣的创新方式,用于逃避基于Javascript的逆向工程技术。
Javascript作为攻击向量显得日益重要,它的实现受到许多编码风格的影响。但是,几乎所有的Javascript恶意软件都是经过混淆的了。 下图显示了一个经过混淆的JavaScript有效载荷的示例(从我的一个分析中取出)
作为分析的第一步,需要尝试将这些代码消除混淆。从简单的剪切和粘贴开始到使用更强大的替换脚本,分析师会尝试重新命名函数和变量的名称,以分离复杂性并明确每个代码段的功能。在Javascript中,有一个好办法来于获取被调用函数的名称,这个名称可用于了解函数名称是否在随时间进行改变。该函数是arguments.callee.caller。通过使用该函数,攻击者可以创建一个栈回溯其中储存着已执行函数的名称链。攻击者会抓取函数名称并将其用作动态解密特定Javascript代码的密钥。使用这种技术,攻击者会拥有一个隐式的控制流完整性,因为如果函数被重命名或者函数顺序与设计的顺序有所不同,那么产生的hash也将会不同。如果hash值不同,则生成的密钥也会不同,所以就无法解密并加载被加密过的代码。
下面的片段解释了这种技术原生的(而不是混淆后的)示例。 我在这里展示未混淆的代码,只是为了简单起见。
每个内部阶段执行(eval())一个content。在第21行、第25行的cow001和pyth001函数进行xor运行解密content。 xor_decrypt函数接收两个参数:decoding_key和欲被解密的payload。每个内部阶段都使用arguments.callee.name函数将被调用者的名称用作解密密钥。 如果函数名称是攻击者设计的那个(用来加密payload的那个),加密内容将被正常执行没有例外。但是如果函数名称被重命名(比如被分析人员更改),执行函数就会失败,攻击者很有可能会去触发其他的代码路径。
在进行实际的野外攻击之前,攻击者需要编写恶意JS并对其进行混淆来准备“攻击路径”。进行混淆之后,攻击者需要使用额外的脚本(如下面的脚本)根据混淆的函数名称对有效载荷进行加密,并将加密好的有效载荷替换为最终的Javascipt文件。
攻击者现在可以编写拥有自己的控制流的Javascript代码。 如果攻击者一遍又一遍地重复这样的概念,他会完成一个完整的逆向工程规避技术来阻止或控制代码执行。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!