随着互联网技术的发展,网络应用变得越来越多样化和重要。然而,在网络应用中,由于协议的规定和网络技术的限制,脚本语言如Javascript必须以开放的方式传播和分发。任何使用浏览器访问网络应用程序的人都可以访问和查看脚本代码,如网络应用程序的Javascript。这给网站的安全带来了很大的隐患。如果这些代码被攻击者使用、破解或篡改,将会给用户带来巨大的经济损失。保护脚本代码的安全性非常重要,混淆技术应运而生。混淆是一种特殊的编码技术。混淆后的代码在语义上保持不变,在功能上与原始代码相同。然而,由于变量名或结构的变化,攻击者无法破解,或者破解的成本大大增加,以保护脚本代码的安全性。在现有混淆方法的基础上,提出了一种基于谷歌闭包编译器的Javascript混淆方法。第一节介绍了常见的混淆方法和混淆评价指标。第二节提出了一种基于谷歌闭包编译器的混淆方法。在第3节中,测试了第2节中的方法,并评估了混淆效果。最后,对文章进行了总结和展望。1混淆变换的形式定义[1]研究如下。假设是从原始程序P到目标程序P’的转换,其中P’=T(P)。如果变换满足以下条件,则称之为模糊变换:1)如果P不能结束或以不正确的状态结束,则P’可能结束,也可能不结束。2)如果P结束,P’也必须结束并产生与P相同的输出。3)为了完成特定的计算任务,P’在有限的范围内比P消耗更多的运行时间。4)攻击者将“P”恢复为“P”比将“P”转换为“P”花费的时间更长。其中,“P”是未被混淆的原始程序,“P”是被混淆的程序。代码混淆技术主要分为四种类型:布局混淆、数据混淆、控制混淆和防止混淆[2]。布局令人困惑,并且改变了代码中攻击者能够理解的有用信息。常见的方法包括指令重排、等价指令替换、垃圾指令插入等。数据混淆,转换程序的数据部分,使其失去原来直观的表达形式,并分类或合并成更难理解的形式。常用的方法包括标量提升、类结构融合和分割、数组重构和数据类型隐藏。控制混乱,使用各种技术手段隐藏或修改程序的真实控制流,防止攻击者分析。常见的方法包括计算混淆、聚合混淆和排名混淆。为了防止混淆,针对具体反汇编器的混淆方法,通过研究反汇编器使用的反汇编工具和算法的实现特点,有针对性地设计混淆方法,达到混淆反混淆器的目的。对某种混淆效应的评价主要有三种:混淆强度、混淆弹性和附加费用[3]。混淆强度,即程序复杂性的增加,表征了程序的复杂性和理解它的难度。混淆灵活性是程序抵抗机器攻击的能力。额外的开销,包括混淆过程的时间和计算成本,以及与源代码相比混淆代码增加的时间和空间成本。2基于抽象语法树的混淆方法2.1谷歌闭包编译器简介谷歌闭包编译器是由谷歌开发的一个Javascript编译器。与传统编译器不同,闭包编译器不将源代码编译成机器可执行的目标代码,而是优化Javascript源代码并输出优化的Javascript代码。通过对源代码的分析,编译器将对源代码执行语法检查、变量引用分析、类型检查等工作。在编译器的语法分析阶段,闭包编译器可以将源代码解析成抽象语法树。树中的每个节点代表源代码中的一个结构,如变量、保留关键字等。由多个节点组成的子树表示源代码中的一个代码实体。2.2抽象语法树中节点的约束为了确保对应于抽象语法树的源代码语法的正确性 根据分支的数量,如果节点的子节点数量不同。If节点有两个或三个子节点,最左边的节点代表If条件语句判断的条件,第二个节点代表条件为真时执行的分支,分支是以块节点为根节点的子树;如果有第三个节点,则该节点代表条件为假时执行的分支。while循环和for循环都是使用For节点表示的。for节点有四个子节点,第一个子节点是在For循环中定义的初始化变量;第二子节点是for循环中的条件表达式;第三个节点是for中的循环体,第四个子节点是for循环的每个变量都自行增加的节点。闭包编译器也将while节点解析为For节点,但是第一个节点和第四个节点用空节点填充,这意味着While循环中没有这样的部分。switch语句的子节点数量取决于开关中事例的分支数量。如果案例分支的数量是n,交换机有n 1或n 2个子节点。其中最左边的节点代表交换机中的一个变量,当交换机有默认分支时,最右边的子节点代表交换机中的默认分支。中间的n个节点对应于n个案例分支。

try语句对应于两个子节点,左边的子节点是try中的代码语句,右边的子节点是catch中的代码语句。通常这两个节点是以块为根节点的子树。在图1中,根节点脚本对应于整个代码片段,if节点及其子树表示所有if语句,名称节点表示if的条件x,块节点及其子树表示当if条件为真时执行的分支,即y(z)。因为这里没有其他分支,所以if节点只有两个子节点。2.3 Javascript混淆方法在抽象语法树中,对应于要混淆的代码的子树被称为目标子树,对应于要混淆的代码的子树被称为包装子树。包装子树有四种类型:if条件语句、switch branch语句、for循环体和try-catch语句。代码片段1中的代码被用作混淆目标代码,并且用try-catch语句包装。当使用闭包编译器执行上述操作时,它分为以下三个步骤。1)将目标代码解析成抽象语法树,如图1所示,并使用脚本节点作为插入点,在该语法树中找到脚本节点。2)根据try-catch代码的语法特征,逐个定义节点,添加子节点,生成try-catch的抽象语法树。在图1中,try-catch中try节点的左子节点被以块为根的子树替换。3)用步骤2中生成的try-catch抽象语法树替换图1中的块节点,并将抽象语法树恢复为Javascript代码。混乱抽象语法树如图2所示。在图中,实线节点形成子树是原始if语句的抽象语法树,虚线节点形成的子树是混淆后添加的try-catch语句的抽象语法树。通过混淆,原来的if语句变成了try-catch语句的子树。当它被转换成源代码时,if语句将被嵌套在try-catch语句附近,从而加深了语句层次。类似地,可以使用if语句、switch语句、for循环或while循环来包装目标代码。当用if语句包装时,目标语句必须在if可执行分支中;用开关包装时,确保目标代码在可以执行的案例分支中。当用for或while循环包装时,请确保循环至少执行一次。3实验效果评估在实验中,我们选择了源文件大小为5560字节的Javascript代码进行实验,并分别在不同混淆程度下进行了5个实验,从文件大小、混淆时间和源代码执行时间三个方面来评估混淆后的效果。4 .在总结现有混淆技术的基础上,提出了一种利用谷歌闭包编译器进行Javascript混淆的方法。本文首先介绍了编译器中对节点的约束。其次,提出了使用谷歌闭包编译器深化Javascript代码层次的混淆方法。最后,测试代码用于评估混淆效果。实验表明,随着混淆程度的加深,代码越大,执行代码所需的时间越长。在实际使用中,我们应该在混淆效果与文件大小和执行效率之间选择适当的混淆级别。这种方法还存在一些不足,如if的条件语句或switch语句中使用的变量是否与源代码中的变量同名,从而干扰了源代码的功能。在接下来的工作中,本文将对上述问题进行研究。