|
首先,我抛砖引玉了。
“混淆”也好,“加密”也好,都是为了加强代码的安全性,防范被人任意查看,在一定程度上保护资源。
请大家注意,在本主题的标题上,我把“混淆”、“加密”这两个概念堆在一起了,为的是从实现目的的角度着眼,从实践的角度着手,不主观地排斥任何手段。所有“混淆”技巧都是为了降低代码的可读性;所有“加密”技巧都是要通过“解密”计算过程将代码还原以后才能执行。
但是,把“混淆|加密”和在一起讨论,并不意味着我们要把概念搞混,在这里为了预防接下来的讨论中发生因概念不清而导致偏离主题,在先说明我们这里所讨论的范畴不包含代码的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 全选 注:如需引入外部Js需刷新才能执行]
毫无疑问,从混淆的角度来说,这种技巧可以比较有效地保护相对简短的代码,因为这个方法增加了代码的长度和复杂度。当然,增加长度这一点是比较让人无奈的。如果原始的代码本来就长,混淆以后也许就会长得让人无法容忍了。
6.对原代码进行加密,同时附上解密的代码
运行时先解密,然后通过document.write()或eval()或innerHTML把代码释放出来执行。
像这种类型的,通常加密解密过程可能搞得比较复杂,还加了混淆,但是这一切就像《红楼梦》的判词里唱的那样纯属“枉然”:因为这把代码释放出来执行的最后一步通常就是明码,而且还不加混淆。这就让人不禁想起了那个老生常谈的“木桶原理”,木板箍成的水桶的盛水能力取决于它最短的那片木板,代码加密的保护强度取决于最薄弱的那个环节。
破解时只要把最后这一步的代码改掉就行了,谁会在意他中间过程有多高明、多复杂?
下面演示了一例:
在这里,我在网页里随便添加了一个textarea,名为kc,把document.write(xxx)改成了kc.value=xxx。于是,在代码经解密最后释放出来时没有被执行,而是直接扔进了textarea里。