Javascript代码混淆综合解决方案-Javascript在线混淆器


Posted in Javascript onDecember 18, 2006

 文章来源:javascriptOnlineObfuscator">http://www.BizStruct.cn/JavascriptOnlineObfuscator

Javascript 代码混淆的目的

Javascript 是一种解释执行的脚本语言,主要应用于 Web 领域的客户端的浏览器中;由于 Javascript 解释执行的特性,代码必须明文下载到客户端,并且可以很容易的进行调试,使得 Javascript 代码的保护非常困难;

不同的人对 Javascript 代码的保护有不同的看法;有的人辛苦努力的代码,却可以被竞争对手轻易获得,他们就非常希望能有保护 Javascript 代码的方案,但现有的方案可能无法满足他们的要求;很多人认为 Javascript 语言很简单,Javascript 代码没有保护的价值,可能是他们的代码确实简单,或者他们并不了解 Javascript 语言强大的功能;还有的人认为现在都开源了,还保护代码干什么,当然开源的人是值得敬佩的,但对别人的代码的开源要求,却不是合理的。

为了提高用户的体验,出现了 Web 2.0 技术,并随着 AJAX 和富界面技术的发展,Javascript 在 Web 应用上的重要性越来越高,Javascript 代码的复杂性、功能和技术含量也越来越高,对Javascript 代码保护的需要也越来越迫切。

Javascript 在线混淆器的目的是为 Javascript 代码保护的需求,提供一种全新的综合解决方案,包括编码规则和免费的在线混淆器。

 

混淆和加密的区别

很多人将这两者混在一起讨论,实际上两者的目的有一定的区别,采取的手段也有很大的不同。加密主要是为了防止未经授权的使用,对这种情况即使破解了加密,也只能非法使用,并不一定能获得软件的代码逻辑;但对于脚本来说,防止对代码进行访问的措施,也属于加密,对这种情况,破解了加密,就获得了代码;而混淆是在无法阻止他人获取代码的情况下,采取的保护代码的逻辑不被他人理解的措施;对于混淆的代码,他人很难理解,无法进行修改和重新应用;
对于生成机器码的语言,比如 C 语言,只需要考虑未经授权的访问,几乎不需考虑代码的保护;因为对编译后的软件,只能反汇编为汇编语言代码,几乎无法分析出代码的逻辑。
对于生成中间代码的语言,比如 Java 和 C#,即需要考虑未经授权的访问,又需考虑代码的保护;;因为对编译后的软件,可以很容易的反编译为较高级的语言,从而了解到代码中的逻辑,并较容易的破解加密。而混淆后,即难于理解代码的逻辑,也不易找到加密点所在。
对于脚本语言,比如 Javascript,只能混淆,难以加密;因为脚本都是明文存在的,很容易调试的,通过跟踪可以较容易的破解上面两种目的的加密。但是混淆后的代码是难于理解代码的逻辑的。

我们只涉及到对 Javascript 脚本进行混淆,而不涉及加密;对于涉及到 Javascript 的系统的加密,我们建议不要将加密点放在 Javascript 脚本内,而是放在服务端的编译程序内,因为编译程序的加密可以采用更多的保护方式,加密的强度也更高。

我们首先要分析 Javascript 语言和混淆相关的特点,和现有的混淆产品的不足,然后再提出我们对 Javascript 代码混淆的解决方案,最后是我们的 Javascript 在线混淆器。

Javascript 语言和混淆相关的特性

Javascript 是一种解释执行的脚本语言,相对编译类型的语言有很多自身的特性,而其中一些特性会对代码混淆带来很大的困难。

无法定义类的属性和方法的名称是否需要被混淆

Javascript 是一种基于原型的语言,没有严格的类型定义。在自定义的类中,对于需要外部访问的属性和方法,不能进行混淆;对于内部访问的属性和方法,需要进行混淆;但Javascript 语言本身,无法对属性和方法进行这样的区分。为此我们要寻找一种变通的机制来识别属性和方法的名称是否需要混淆。

存在大量的系统定义的核心的和客户端的方法和属性不能被混淆

Javascript 语言本身定义了大量的核心的类、方法和属性;浏览器中也定义了大量的客户端的类、方法和属性;这些类、方法和属性都不能够被混淆,然而这些类、方法和属性的数量太大,无法通过枚举来避免混淆;为此我们需要寻找一种方法来标识这些类、属性和方法。

无法定义全局变量是否需要被混淆

全局变量是 window 对象的属性,局部变量是函数对象的属性;所有的局部变量都是可以和应该被混淆的,而全局变量有的需要混淆,有的不能混淆;但全局变量和局部变量的表现形式是一样的,难以区分;而且全局变量本身更无法定义是否需要被混淆。为此我们要找到一种方法来区分不能混淆的全局变量,和需要混淆的全局变量及局部变量。

Javascript 语言的这些特点,都对代码的混淆带来了很大的困难,如果不解决这几个问题,Javascript 代码的混淆就缺少实用的价值。

 

现有 Javascript 混淆产品的问题

当我们需要混淆 Javascipt 代码的时候,首先考察了市面上现有的产品,和一些论坛里对混淆的思路,但这些产品和思路都不能满足我们的要求。

有一个商品化的 Javascript 混淆产品,采用了和一种 C# 混淆工具相似的混淆方式,分析了代码里所有的标识符,对一些系统预设的标识符不混淆,对其他的进行混淆,同时提供用户对标识符的混淆进行选择和配置;这个产品的功能很多很复杂,但有一个很大的问题,就是预设的标识符有限,对于代码中用到的大量的系统定义的属性和方法,会进行混淆,为此需要自己手工配置,避免对这些属性和方法的混淆,这对于大型的系统几乎是一个不可能完成的任务。

有一些论坛里也讨论到混淆的思路,包括一些示例,这些思路更多的是改变标识符的表现形式,有的是用编码字符串的关联数组替换属性,比如将 xx.dd 替换为 xx["\x64\x64"];更复杂的是把 "\x64\x64" 之类保存到字符串数组,然后调用字符串数组作为关联数组的下标;这种思路可以避免上面的问题,但有一个更大的问题,就是混淆是可逆的,被混淆的标识符仅仅是被转换成了16进制的形式,可以很容易的恢复。

正是现有产品的不足,促使我们不得不研究自己的解决方案。我们的解决方案也是经过了几个版本,一开始的版本要复杂的多,花费了很大的工作量,但结果并不理想;几经修改才找到现有的解决方案;虽然开始的大量工作,最后几乎都废弃了,但没有前面的工作,也就没有后面的结果;所以即使您可能会认为我们的方案简单,那也只是我们努力的结果,而不是过程;而且简单的东西,往往是有效的。

Javascript 代码混淆综合解决方案

通过前面对 Javascript 的特性和相关混淆产品的分析,使我们认识到如果仅仅是在混淆器上下功夫是不够的;因为 Javascript 语言本身对混淆的功能有很大的限制,无法解决。为此我们设计了一个综合的解决方案,就是 Javascript 在线混淆器规则,只要是按照规则编写的 Javascipt 代码,都能使用 Javascript 在线混淆器混淆进行混淆。

Javascript 在线混淆器的规则并不复杂,但能够解决 Javascript 语言本身的特性和其他混淆产品遇到的问题。

规则一、所有用 window 约束的类、变量和函数都不混淆,其他的类、变量和函数都混淆。

全局的类、变量和函数本身都是 window 的属性,用不用 window 约束,从逻辑的角度是一样的。但我们可以借用 window 的约束来区分对全局的类、变量和函数是否需要进行混淆。

用 window 的约束必须是前后一致的,不但包括类、变量和函数的定义,也包括类、变量和函数的调用。

局部的类、变量和函数,因为没有 window 约束,所以都是混淆的。

类型 混淆 不混淆
类定义 function Class1(){...} window.Class1 = function(){...}
函数定义 function Method1(){...} window.Method1 = function(){...}
变量定义 var Param1 = 1; window.Param1 = 1;
生成类的实例 var object1 = new Class1(); var object1 = new window.Class1();
函数调用 Method1(); window.Method1()
变量引用 var newParam = Param1; var newParam = window.Param1;

规则二、所有以小写字符开头的属性和方法都不混淆,以其他字母开头的属性和方法都混淆,用 window 约束的属性和方法应用规则一。

JavaScript 核心和客户端中有大量的系统定义的方法和属性不能被混淆,而这些方法和属性绝大多数都是以小写字母开始的,本规则保证了系统定义的方法和属性不被混淆。在 Javascript 客户端中仅有极少数的系统定义的以大写字符起始的方法和属性,对于这种情况,可以采用关联数组的方式避免被混淆,比如 object1["Method1"]();此方法也适用于第三方控件中可能会有的以大写字符起始的方法和属性的情况。

此规则也使我们可以在自定义的类中标识方法和属性是否被混淆,对于需要外部调用不能混淆的方法和属性,采用小写字母起始,对于内部的方法和属性,采用其他字母起始。

类型 混淆 不混淆
类方法定义 Class1.Method1 = function(){...} Class1.method1 = function(){...}Class1["Method1"] = function(){...}
对象方法定义 Class1.prototype.Method1 = function(){...} Class1.prototype.method1 = function(){...}Class1.prototype["Method1"] = function(){...}
类属性定义 Class1.Prop1 = 1; Class1.prop1 = 1;Class1["Prop1"] = 1;
对象属性定义 object1.Prop1 = 1; object1.prop1 = 1;object1["Prop1"] = 1;
类方法调用 Class1.Method1(); Class1.method1 ();Class1["Method1"]();
对象方法调用 object1.Method1(); object1.method1 ();object1["Method1"]();

Javascript 在线混淆器的核心规则就是以上两点,另外还有几点说明。

标识符的混淆采用 Hash 算法,不可逆

Hash 算法是不可逆的,所以不能根据混淆后的标识符,来直接推出混淆前的标识符;但 Hash 算法依赖于 .Net 系统的实现,大多数的时候,.Net 的 Hash 算法是不变的,就是同一个标识符的混淆结果是一样的;如果能够枚举足够多的标识符,仍然可能根据相同的混淆结果,知道混淆前的标识符。

如何调用混淆后的类、方法和属性

对于混淆代码的内部调用,只要采用相同的规则,要么都混淆,要么都不混淆,就能正确的调用。

对于混淆代码的外部调用,可以有两种方式,一种是不混淆,代码内部采用不混淆的规则,外部采用不混淆的可理解的标识符调用;另一种是混淆,代码内部采用混淆的规则,外部也采用混淆后的不可理解的标识符调用,但此方式依赖于 .Net Hash 算法的实现,在不同版本的 .Net 实现中的 Hash 算法有可能不同,以至混淆后的标识符不一致,从而导致重新混淆后,需要替换原来混淆的标识符。

为何有“清除空格,保留分号后的回车”的选项

Javascript 语法要求全局函数的结尾必须有分号或回车,如果遗漏了分号,而又清除了所有的回车,总是提示第一行缺少分号,无法定位错误所在;采用本选项可以有助于寻找缺少的分号的位置。

以下 Javascript 语言的保留字不混淆

break, case, catch, continue, debugger, default, delete, do, else, false, finally, for, function, if, in, instanceof, new, null, return, switch, this, throw, true, try, typeof, var, while, with

混淆器预定义了一些 window 的属性和方法

Javascript 核心类和函数是不能被混淆的,他们实质上都是 window 的属性和方法,按照规则应该用 window 约束,以避免被混淆;但对于 Object、Array、Date、ActiveXObject 等核心类,混淆器已经预定义不会混淆,不需要再用 window 约束。对于 alert 等 window 常用的方法和 document 等 window 常用的客户端属性,也有预定义。其他需要预定义的类和方法,我们会逐步添加;没有预定义的全局类和函数,如果不能混淆,必须用 window 约束。

以下全局的类、变量和方法不混淆

ActiveXObject, alert, Array, Boolean, Date , document, Math, Number, Object, RegExp, String, window

 

Javascript 在线混淆器

 

请访问 http://www.BizStruct.cn/JavascriptOnlineObfuscator/JavascriptOnlineObfuscator.aspx 。

Javascript 相关文章推荐
给Javascript数组插入一条记录的代码
Aug 30 Javascript
基于jquery的页面划词搜索JS
Sep 14 Javascript
解决Jquery load()加载GB2312页面时出现乱码的两种方案
Sep 10 Javascript
js setTimeout opener的用法示例详解
Oct 23 Javascript
JavaScript中的依赖注入详解
Mar 18 Javascript
JavaScript来实现打开链接页面的简单实例
Jun 02 Javascript
jQuery数据检索中根据关键字快速定位GridView指定行的实现方法
Jun 08 Javascript
jQuery简单实现遍历单选框的方法
Mar 06 Javascript
实战node静态文件服务器的示例代码
Mar 08 Javascript
JS实现把一个页面层数据传递到另一个页面的两种方式
Aug 13 Javascript
利用JS判断元素是否为数组的方法示例
Jan 08 Javascript
JavaScript实现4位随机验证码的生成
Jan 28 Javascript
XP折叠菜单&仿QQ2006菜单
Dec 16 #Javascript
prototype 1.5相关知识及他人笔记
Dec 16 #Javascript
飞鱼(shqlsl) javascript作品集
Dec 16 #Javascript
XHTML-Strict 内允许出现的标签
Dec 11 #Javascript
JS的IE和Firefox兼容性集锦
Dec 11 #Javascript
不错的新闻标题颜色效果
Dec 10 #Javascript
用脚本调用样式的几种方法
Dec 09 #Javascript
You might like
PHP实现定时生成HTML网站首页实例代码
2008/11/20 PHP
PHP数组操作汇总 php数组的使用技巧
2011/07/17 PHP
MooTools 页面滚动浮动层智能定位实现代码
2011/08/23 Javascript
extjs3 combobox取value和text案例详解
2013/02/06 Javascript
js同比例缩放图片的小例子
2013/10/30 Javascript
jQuery Ajax调用WCF服务详细教程
2015/03/31 Javascript
JS设置cookie、读取cookie、删除cookie
2015/04/17 Javascript
利用jquery实现下拉框的禁用与启用
2016/12/07 Javascript
React Native实现地址挑选器功能
2017/10/24 Javascript
使用webpack-dev-server处理跨域请求的方法
2018/04/18 Javascript
vue首次赋值不触发watch的解决方法
2018/09/11 Javascript
微信实现自动跳转到用其他浏览器打开指定APP下载
2019/02/15 Javascript
Vue列表如何实现滚动到指定位置样式改变效果
2020/05/09 Javascript
详解JavaScript中的this指向问题
2021/02/05 Javascript
[49:31]DOTA2-DPC中国联赛 正赛 Elephant vs LBZS BO3 第二场 1月29日
2021/03/11 DOTA
使用Python判断IP地址合法性的方法实例
2014/03/13 Python
你眼中的Python大牛 应该都有这份书单
2017/10/31 Python
Python(Django)项目与Apache的管理交互的方法
2018/05/16 Python
Python操作mongodb的9个步骤
2018/06/04 Python
Python 实现「食行生鲜」签到领积分功能
2018/09/26 Python
解决pandas.DataFrame.fillna 填充Nan失败的问题
2018/11/06 Python
Django项目中使用JWT的实现代码
2019/11/04 Python
Python enumerate() 函数如何实现索引功能
2020/06/29 Python
丝芙兰香港官网:Sephora香港
2018/03/13 全球购物
Tom Dixon官网:英国照明及家具设计和制造公司
2019/03/01 全球购物
网络事业创业计划书范文
2014/01/09 职场文书
幼儿园庆六一游园活动方案
2014/01/29 职场文书
学校卫生检查制度
2014/02/03 职场文书
《商鞅南门立木》教学反思
2014/02/16 职场文书
幼儿园优秀班主任事迹材料
2014/05/14 职场文书
单位证明范文
2015/06/18 职场文书
2016党员干部廉洁自律心得体会
2016/01/13 职场文书
SQL Server代理:理解SQL代理错误日志处理方法
2021/06/30 SQL Server
实操Python爬取觅知网素材图片示例
2021/11/27 Python
JavaScript流程控制(分支)
2021/12/06 Javascript
Redis全局ID生成器的实现
2022/06/05 Redis