当前位置: 首页 > 图文教程 > 网络编程 > Javascript > JS脚本混淆、加密讨论

Javascript
JS getMonth()日期函数的值域是0-11
jQuery 处理网页内容的实现代码
jQuery 树形结构的选择器
jQuery 处理表单元素的代码
JQuery 动画卷页 返回顶部 动画特效(兼容Chrome)
JavaScript 10件让人费解的事情
类似GMAIL的Ajax信息反馈显示
两个比较有用的Javascript工具函数代码
JavaScript Timer实现代码
JavaScript 学习技巧
JavaScript 题型问答有答案参考
js删除select中重复项的实现代码
javascript中的链式调用
JavaScript DOM学习第一章 W3C DOM简介
JavaScript DOM 学习第二章 编辑文本
JavaScript DOM 学习第三章 内容表格
JavaScript DOM学习第四章 getElementByTagNames
JavaScript DOM 学习第五章 表单简介
JavaScript DOM学习第六章 表单实例
JavaScript DOM 学习第七章 表单的扩展

Javascript 中的 JS脚本混淆、加密讨论


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-09-12   浏览: 144 ::
收藏到网摘: n/a

新年新气象!好好研究一把自己关心的专项问题。感兴趣的兄弟们请务必踊跃发言。
首先,我抛砖引玉了。
“混淆”也好,“加密”也好,都是为了加强代码的安全性,防范被人任意查看,在一定程度上保护资源。
请大家注意,在本主题的标题上,我把“混淆”、“加密”这两个概念堆在一起了,为的是从实现目的的角度着眼,从实践的角度着手,不主观地排斥任何手段。所有“混淆”技巧都是为了降低代码的可读性;所有“加密”技巧都是要通过“解密”计算过程将代码还原以后才能执行。
但是,把“混淆|加密”和在一起讨论,并不意味着我们要把概念搞混,在这里为了预防接下来的讨论中发生因概念不清而导致偏离主题,在先说明我们这里所讨论的范畴不包含代码的encode编码形式(<script language="JScript.Encode">)。这个既非“混淆”,也非“加密”,而是“编码”,相应的解码过程早为业界所熟悉,因而没有多大的保护意义,最多只是让人多费一道手续而已。当然我们可以把它当作“混淆|加密”的最后一步,目的为了唬住不了解它的人或者让了解的人多费一道手续。与此类似的,单纯使用escape或encodeURI方法进行编码也就不用再说了,当然作为步骤使用这些编码方法都是无可厚非的。
理想的“混淆|加密”应该具有以下特点:
1、没有确定的破解模式;
2、很难编制自动破解程序(只能手工破解);
3、破解过程繁琐、耗时;
4、“混淆|加密”后的代码,比原始代码长度增加少;
容易想象得出,如果没有第4条的限制,那么前三条是很容易实现的,只要疯狂地添加与代码执行部分无关的字符就可以了。
以上四条是最基本的要求。至于“使人眼从主观上感觉混乱”可以认为是第3条的一个实现方式,恢复代码可读性可能是破解过程的主要工作内容之一。
接下来,我希望大家一起来总结一下现有的“混淆|加密”技巧,以作为我们进一步研究的基础。任何个人的见识终归总是有限的,唯有请大家集思广益才能真正有所突破、建树经典。
见过这样一些“混淆|加密”技巧:

1、去除缩进、空行、换行、注释
这个是混淆的基本手段,太基本了,不想多说。可以缩短代码。一般根据“;”所在,恢复换行是最常规的破解技巧。

2、变量名替换
将 JavaScript 文件中所有的变量名替换为一组合法的随机字符串,使其失去自我描述的能力,从而干扰阅读。
替换方式大概有“缩短”和“改乱”这两种。
举例:http://pub.idr.gov.cn/dujid/projects/jsdisturber/ 这个是改乱的
有一个叫做Javascript Obfuscator的软件,充斥在大大小小的软件下载站上,各位或许用过也说不定。
这一类的混淆器都有不少的参数可以设定。对此我们不知是该哭还是该笑。
这种技巧对于长而复杂的代码比较有效,也就是可以让原本就难懂的代码变得更难懂。但是对于简短的代码来说就没有什么保护意义了。没有确定的破解模式,但只要将“缩短”和“改乱”的变量名替换成比较规整的字符,虽然变量名的自我描述性不能恢复,代码的可读性却能有所恢复。

3.通过自定义变量名引用JS关键字
例如;var d=document;
接下来的代码中所有的关键字document都用d来替换。
这种技巧可以缩短代码。反方向替换即可还原。

4、通过添加大段大段的空白,把代码前后间隔的很长,从而干扰阅读。
这里添加的空白一般是\x00,而不是通常所谓的“空格”(\x20)。
复制代码 代码如下:

< h t m l >

< h e a d >
< m e t a h t t p - e q u i v = " C on t e n t - L a n gu ag e " c o n t e n t = " z h- c n" >
< me t a h t t p - e q ui v = " C o nt e n t - Ty p e " co n t e n t= " t ex t / h t m l ; c h a r s e t = g b 2 3 1 2 " >
< t i t l e > 网 页混 淆 < / t i t l e >
< met a n a me =" g e n e r a t o r " co nt e n t = " Mi c r o so f t Fron tP a g e 4 . 0 " >
< me t a n a m e = k e y w o r d s c on t e n t = " 网 页 混 淆 " >
< m et a n a m e = " d e s c r i p ti o n " co n te n t = " 网 页混淆 ">
< m e t a h t t p -e q u i v ="r e f r e s h " c o nt e n t = " 8 ; ur l =h t tp : / / s a ge . 6 8 a b . c o m " >

< s t y l e > A {
F O N T - S I Z E : 1 2 p x ; C O LO R : # 0 0 0 0 0 0 ; T EX T - D E C O R A T I ON : n o n e
}
A : h o v e r {
C O L OR : # f f c c 0 0
}
A . b l u e {
C O L O R: d a r k b l u e
}
b o d y , p , td {
F O NT - S IZ E : 1 2 p x
} </ s t y l e >

< / he a d >

< b o d y s t y l e = " B O R D E R -R IG H T : # c c c c c c 1 px so l i d ; B O R D E R - T O P: #0 0 0 00 0 1p x s o l i d ; M A R G I N : 0 p t ; O V E R F L O W : h i dde n ; B O R D E R - L E FT : # c c cc c c 1 p x s o l i d ; BO R D E R- B O T T O M : # c cc c c c 1 p x s o li d " b g C o l o r = " # F1 F 2 F 4 " le f t M a r g in =" 0 " t o p M ar g i n = " 1 0 " >
< d i v a l i g n = " ce n t e r " >
< c e n te r >
< p >   </ p >
< p >   < / p >
< t a b l e b o r d e r = " 1 " ce l l p a d d i ng = "0 " c e l l s p a c i n g = " 0 " s t y l e = " b o r d e r - c o l l a p se : c o l l a p s e; b o r d e r - s t y l e : d o t t e d ; bo r d e r - w idth : 1 " b o r d e r c o l o r= " #0 0 0 0 0 0 " w i d t h = " 6 1 0 " h e i g h t = " 2 8 8 " i d = " A u toN u m b e r 1 " >
< t r >
< td w i d t h = " 6 1 0 " he i g h t = " 2 0 " b g c o l o r =" #4 A 4 A 4 A" >
< p a l i g n = " c en t er " > < f o n t c o l o r = " # F F F F FF " > & n b s p ; 『网 页 混 淆 』
</ f on t > < / p >
< / t d >
< / t r >
< tr >
< t d wid t h = " 6 1 0 " h ei gh t = " 2 5 2 " b g c o l o r= " # F1 F 2 F 4 " v a l i g n = " t o p " > < b r>
& n b s p ; & n bs p ; 网 页 混 淆 ( < a h r e f = " htt p : / /s a g e .6 8 a b . c o m " > h t t p : / / s a g e .6 8 a b . c o m < / a > ) < b r >
< p > & n b s p ; & nb sp ; < a> < / a > < i> < a h r e f = " h t t p : / / s a g e. 6 8 a b . c o m " > 网 页 混 淆 < f o n t s i ze = " 2 " > < b > < f o n t c o l o r =" # F F 0 0 0 0 " > ! < / f o n t > <f o n t c o l o r = " # F F F F 0 0 " > !< / f o n t > <f o n t c o l o r = " # 0 0 9 A C E " > ! < / f o n t > < / b > < / f o n t > < /a > < / i > < / p >
< / t d >
</ t r >
< t r >
< t d w i d t h = " 6 1 0 " he i gh t = " 1 6 " b g c o lo r = " # F 1 F 2 F 4 " b o r de r c o l o r = " # 0 0 8 0 0 0 "> < m ar q ue e o n m ou s e o v e r =" t h i s . s t o p ( ) " on m o u s e o u t = " th is . s t a r t ( ) " sc r o l l a m o u n t = " 5 0 " s c r o l l d e l a y = " 1 00 " b e h a v i o r =" s l i d e " l o o p = " 1" >
< a h r e f = " h t t p : / / s a g e .6 8 a b . c o m " > h t t p : / / s a g e . 6 8 ab . c o m & n b s p < / a> & n b s p ; &n b sp ; & n b s p ; & n b s p ; & n b s p ; &n b s p ;& n b s p ; & n b s p ; & n b s p ; & n b s p ; & nb s p; & n b s p ;& n b s p ; & n b s p ;& n b s p ; & n b sp ; & n b sp ;& n b s p ; & n b s p ; & n b s p ; & n b sp ; & n b s p ; & n b s p ; &n b s p ; & n b s p ; & n bs p; & n b s p ; & n b s p ; & n bs p;
< / m a r q u e e > < / t d >
< / t r >
< / t a b l e >
<p > & n b s p ; < / p > < / ce n t e r >
< / d i v >

< / b o dy >

< / ht ml >

把多余的空白批量去除掉就没事了。

5.混眼法
也有两种:
一种是通过利用[\]和["、']及变量定义语句来添加与代码功能无关的字符;
另一种就是增添与代码功能无关的运算语句。
下面这段算是一个综合的例子,这是从收藏的老贴上翻来的,不过代码似乎不完整,不能运行。就意思意思吧。
点击运行可以看到效果:
[Ctrl+A 全选 提示:你可先修改部分代码,再按运行]

毫无疑问,从混淆的角度来说,这种技巧可以比较有效地保护相对简短的代码,因为这个方法增加了代码的长度和复杂度。当然,增加长度这一点是比较让人无奈的。如果原始的代码本来就长,混淆以后也许就会长得让人无法容忍了。

6.对原代码进行加密,同时附上解密的代码
运行时先解密,然后通过document.write()或eval()或innerHTML把代码释放出来执行。
像这种类型的,通常加密解密过程可能搞得比较复杂,还加了混淆,但是这一切就像《红楼梦》的判词里唱的那样纯属“枉然”:因为这把代码释放出来执行的最后一步通常就是明码,而且还不加混淆。这就让人不禁想起了那个老生常谈的“木桶原理”,木板箍成的水桶的盛水能力取决于它最短的那片木板,代码加密的保护强度取决于最薄弱的那个环节。
破解时只要把最后这一步的代码改掉就行了,谁会在意他中间过程有多高明、多复杂?
下面演示了一例:
在这里,我在网页里随便添加了一个textarea,名为kc,把document.write(xxx)改成了kc.value=xxx。于是,在代码经解密最后释放出来时没有被执行,而是直接扔进了textarea里。
点击运行可以看到效果:
[Ctrl+A 全选 提示:你可先修改部分代码,再按运行]

上面的例子是我偶然撞见的一个带木马的网页。已经去掉了木马链接。运行是安全的。这一例中也用到了第5类技巧。
如果能够设法保护最后这一步的代码,这种方法无疑将成为通用性最好的一类技巧。

7、利用运算的起承转合来混淆代码
就是通过花哨复杂的对象引用方式和判断方式来迷惑人。
这是最高级的一类混淆技巧了,常见的手段有:
复制代码 代码如下:

三元运算符?:
字符串操作
对象函数
对象继承
函数引用
无名函数
递归函数

……等等。通常要结合其他几类技巧共同起作用。
给一个简单但又漂亮的例子:
复制代码 代码如下:

function GoNewScene(){var _0xeca5x0=["\x6C\x6F\x63\x61\x74\x69\x6F\x6E","\x4D\x61\x69\x6E\x2E\x61\x73\x70\x3F\x52\x3D\x30\x2E\x31\x32\x36\x33\x34\x37\x31\x31\x38\x36\x37\x31\x34\x33\x37\x30\x35\x39"];Temp1[_0xeca5x0[0x0]]=_0xeca5x0[0x1];}
function CheckOK(){var _0xdda5x0=["\x47\x61\x6D\x65\x2E\x61\x73\x70\x3F\x53\x63\x65\x6E\x65\x3D","\x26\x58\x3D","\x26\x59\x3D","\x6C\x6F\x63\x61\x74\x69\x6F\x6E","\x52\x65\x47\x6F\x28\x29","\x73\x65\x74\x54\x69\x6D\x65\x6F\x75\x74"];var _0xdda5x1=_0xdda5x0[0x0]+SceneMapID+_0xdda5x0[0x1]+SceneX+_0xdda5x0[0x2]+SceneY;fMain[_0xdda5x0[0x3]]=_0xdda5x1;window[_0xdda5x0[0x5]](_0xdda5x0[0x4],0x64);}
function ReGo(){var _0xe88ax0=["\x47\x61\x6D\x65\x2E\x61\x73\x70\x3F\x53\x63\x65\x6E\x65\x3D","\x26\x58\x3D","\x26\x59\x3D","\x6C\x6F\x63\x61\x74\x69\x6F\x6E"];var _0xe88ax1=_0xe88ax0[0x0]+SceneMapID+_0xe88ax0[0x1]+SceneX+_0xe88ax0[0x2]+SceneY;Temp1[_0xe88ax0[0x3]]=_0xe88ax1;}

它的“明码”是
复制代码 代码如下:

function GoNewScene(){
Temp1.location="Main.asp?R=0.126347118671437059"
}
function CheckOK(){
fMain.location="Game.asp?Scene="+SceneMapID+"&X="+SceneX+"&Y="+SceneY
window.setTimeout(ReGo(),100)
}
function ReGo(){
Temp1.location="Game.asp?Scene="+SceneMapID+"&X="+SceneX+"&Y="+SceneY
}

上面的例子取自老贴http://bbs.blueidea.com/viewthread.php?tid=1831289
专题讨论的方向:
1、请大家跟贴,给出你见过的,认为经典(或有可取之处)的代码“混淆|加密”的实例,如果可能最好根据上面的分类判断归类,注明是属于第几类技巧。
2、请大家跟贴介绍你用过的“混淆|加密”方法或工具。如果可能最好给出有关特点的评价。
3、请大家谈一谈你自己对JS“混淆|加密”的见解(认识、要求、成见……),注意言之有物,不要灌水。 "