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 DOM 添加事件
Feb 14 Javascript
实现连缀调用的map方法(prototype)
Aug 05 Javascript
js 调用百度地图api并在地图上进行打点添加标注
May 13 Javascript
jQuery扁平化风格下拉框美化插件FancySelect使用指南
Feb 10 Javascript
javascript实现下拉提示选择框
Dec 29 Javascript
动态创建按钮的JavaScript代码
Jan 29 Javascript
详解AngularJS1.6版本中ui-router路由中/#!/的解决方法
May 22 Javascript
简单理解Vue中的nextTick方法
Jan 30 Javascript
vscode 开发Vue项目的方法步骤
Nov 25 Javascript
VUE安装使用教程详解
Jun 03 Javascript
Angular封装表单控件及思想总结
Dec 11 Javascript
vue中实现回车键登录功能
Feb 19 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将字符分解为多个字符串的方法
2014/11/22 PHP
yii2.0数据库迁移教程【多个数据库同时同步数据】
2016/10/08 PHP
PHP date()格式MySQL中插入datetime方法
2019/01/29 PHP
PHP添加文字水印或图片水印的水印类完整源代码与使用示例
2019/03/18 PHP
PHP设计模式之建造者模式(Builder)原理与用法案例详解
2019/12/12 PHP
基于jquery实现的移入页面上空文本框时,让它变为焦点,移出清除焦点
2011/07/26 Javascript
jquery插件冲突(jquery.noconflict)解决方法分享
2014/03/20 Javascript
JavaScript实现的购物车效果可以运用在好多地方
2014/05/09 Javascript
AngularJS实现全选反选功能
2015/12/08 Javascript
JS运动相关知识点小结(附弹性运动示例)
2016/01/08 Javascript
jQuery ajax提交Form表单实例(附demo源码)
2016/04/06 Javascript
在js中实现邮箱格式的验证方法(推荐)
2016/10/24 Javascript
单行 JS 实现移动端金钱格式的输入规则
2017/05/22 Javascript
详解vue.js 开发环境搭建最简单攻略
2017/06/12 Javascript
用原生JS实现简单的多选框功能
2017/06/12 Javascript
微信小程序实现简易table表格
2020/06/19 Javascript
使用原生js编写一个简单的框选功能方法
2019/05/13 Javascript
微信小程序登录态和检验注册过没的app.js写法
2019/05/22 Javascript
微信公众号获取用户地理位置并列出附近的门店的示例代码
2019/07/25 Javascript
弱类型语言javascript开发中的一些坑实例小结【变量、函数、数组、对象、作用域等】
2019/08/07 Javascript
layui--js控制switch的切换方法
2019/09/03 Javascript
vue-cli 3如何使用vue-bootstrap-datetimepicker日期插件
2021/02/20 Vue.js
Python的subprocess模块总结
2014/11/07 Python
用Python编写脚本使IE实现代理上网的教程
2015/04/23 Python
Python模拟三级菜单效果
2017/09/11 Python
基于python分析你的上网行为 看看你平时上网都在干嘛
2019/08/13 Python
python实现机器人卡牌
2019/10/06 Python
英国设计的甲板鞋和船鞋:Chatham
2018/12/06 全球购物
加州风格的游泳和沙滩装品牌:Cupshe
2019/06/10 全球购物
铭万公司.net面试题笔试题
2014/07/20 面试题
中英双版中文教师求职信
2013/10/27 职场文书
2015元旦联欢晚会结束语
2014/12/14 职场文书
刑事附带民事起诉状
2015/05/19 职场文书
2015年审计人员工作总结
2015/05/26 职场文书
如何用JavaScript学习算法复杂度
2021/04/30 Javascript
Redis keys命令的具体使用
2022/06/05 Redis