博文記錄
教程分享 2019-10-24 11:31:39 95 0

此前发布过关于aaencode的混淆编码,此篇文章继续说同作者的jjencode混淆编码的具体过程。

介绍

首先是jjencode的作者提供的编码测试页:http://utf-8.jp/public/jjencode.html

可以将任何合法的JavaScript代码进行编码,首先我们可以简单测试将以下代码进行编码。

编码前:

alert("Hello, JavaScript" )

编码后:

$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+$.$_$_+(![]+"")[$._$_]+$.$$$_+"\\"+$.__$+$.$$_+$._$_+$.__+"(\\\"\\"+$.__$+$.__$+$.___+$.$$$_+(![]+"")[$._$_]+(![]+"")[$._$_]+$._$+",\\"+$.$__+$.___+"\\"+$.__$+$.__$+$._$_+$.$_$_+"\\"+$.__$+$.$$_+$.$$_+$.$_$_+"\\"+$.__$+$._$_+$._$$+$.$$__+"\\"+$.__$+$.$$_+$._$_+"\\"+$.__$+$.$_$+$.__$+"\\"+$.__$+$.$$_+$.___+$.__+"\\\"\\"+$.$__+$.___+")"+"\"")())();

可见,编码后的JS也是很有意思,仅由符号组成的JS代码。

 

混淆过程

通过源代码,我们可以看到具体将JS进行编码的函数过程,如下所示:

function jjencode( gv, text )
{
    var r="";
    var n;
    var t;
    var b=[ "___", "__$", "_$_", "_$$", "$__", "$_$", "$$_", "$$$", "$___", "$__$", "$_$_", "$_$$", "$$__", "$$_$", "$$$_", "$$$$", ];
    var s = "";
    for( var i = 0; i < text.length; i++ ){
        n = text.charCodeAt( i );
        if( n == 0x22 || n == 0x5c ){
            s += "\\\\\\" + text.charAt( i ).toString(16);
        }else if( (0x21 <= n && n <= 0x2f) || (0x3A <= n && n <= 0x40) || ( 0x5b <= n && n <= 0x60 ) || ( 0x7b <= n && n <= 0x7f ) ){
        //}else if( (0x20 <= n && n <= 0x2f) || (0x3A <= n == 0x40) || ( 0x5b <= n && n <= 0x60 ) || ( 0x7b <= n && n <= 0x7f ) ){
            s += text.charAt( i );
        }else if( (0x30 <= n && n <= 0x39 ) || (0x61 <= n && n <= 0x66 ) ){
            if( s ) r += "\"" + s +"\"+";
            r += gv + "." + b[ n < 0x40 ? n - 0x30 : n - 0x57 ] + "+";
            s="";
        }else if( n == 0x6c ){ // 'l'
            if( s ) r += "\"" + s + "\"+";
            r += "(![]+\"\")[" + gv + "._$_]+";
            s = "";
        }else if( n == 0x6f ){ // 'o'
            if( s ) r += "\"" + s + "\"+";
            r += gv + "._$+";
            s = "";
        }else if( n == 0x74 ){ // 'u'
            if( s ) r += "\"" + s + "\"+";
            r += gv + ".__+";
            s = "";
        }else if( n == 0x75 ){ // 'u'
            if( s ) r += "\"" + s + "\"+";
            r += gv + "._+";
            s = "";
        }else if( n < 128 ){
            if( s ) r += "\"" + s;
            else r += "\"";
            r += "\\\\\"+" + n.toString( 8 ).replace( /[0-7]/g, function(c){ return gv + "."+b[ c ]+"+" } );
            s = "";
        }else{
            if( s ) r += "\"" + s;
            else r += "\"";
            r += "\\\\\"+" + gv + "._+" + n.toString(16).replace( /[0-9a-f]/gi, function(c){ return gv + "."+b[parseInt(c,16)]+"+"} );
            s = "";
        }
    }
    if( s ) r += "\"" + s + "\"+";

    r = 
    gv + "=~[];" + 
    gv + "={___:++" + gv +",$$$$:(![]+\"\")["+gv+"],__$:++"+gv+",$_$_:(![]+\"\")["+gv+"],_$_:++"+
    gv+",$_$$:({}+\"\")["+gv+"],$$_$:("+gv+"["+gv+"]+\"\")["+gv+"],_$$:++"+gv+",$$$_:(!\"\"+\"\")["+
    gv+"],$__:++"+gv+",$_$:++"+gv+",$$__:({}+\"\")["+gv+"],$$_:++"+gv+",$$$:++"+gv+",$___:++"+gv+",$__$:++"+gv+"};"+
    gv+".$_="+
    "("+gv+".$_="+gv+"+\"\")["+gv+".$_$]+"+
    "("+gv+"._$="+gv+".$_["+gv+".__$])+"+
    "("+gv+".$$=("+gv+".$+\"\")["+gv+".__$])+"+
    "((!"+gv+")+\"\")["+gv+"._$$]+"+
    "("+gv+".__="+gv+".$_["+gv+".$$_])+"+
    "("+gv+".$=(!\"\"+\"\")["+gv+".__$])+"+
    "("+gv+"._=(!\"\"+\"\")["+gv+"._$_])+"+
    gv+".$_["+gv+".$_$]+"+
    gv+".__+"+
    gv+"._$+"+
    gv+".$;"+
    gv+".$$="+
    gv+".$+"+
    "(!\"\"+\"\")["+gv+"._$$]+"+
    gv+".__+"+
    gv+"._+"+
    gv+".$+"+
    gv+".$$;"+
    gv+".$=("+gv+".___)["+gv+".$_]["+gv+".$_];"+
    gv+".$("+gv+".$("+gv+".$$+\"\\\"\"+" + r + "\"\\\"\")())();";

    return r;
}

 

使用方式即是:

jjencode( '$', 'alert("Hello, JavaScript" )' )

参数1,就类似于混淆代码中的一个全局变量,参数2就是具体要进行混淆的原JS代码。

 

代码解析

接下来我们将这段JS函数进行解析,将混淆后的代码进行阅读,以便更好的理解其编码的思路。

 

对比混淆

首先编码一个“空文本代码”混淆后的代码,以及一个JS仅有字符“a”混淆后的代码,并将其格式化对比查看。

左边是由空字符构成的混淆后代码,右边是由字符a构成的混淆后代码。

由此我们基本可以看出其中多出来的部分就是具体我们原本的JS代码。

 

为了测试,我们此次混淆一段代码并将其执行,如下:

其实际就是:

console.log("tokyo")

 

逐步分析

我们将混淆后的代码进行逐行执行,了解其到底做了哪些事情。

根据下图,可以看到其的运行过程。

首先,初始化赋值将 ~[] 赋值到 $ 上,而这个 $ 就是我们之前说的哪个全局变量,也可以可定义的。

~[] 实际执行的是,初始化一个空数组,再将其按位取反即实际是 按位取反的0,即:$ = ~0 = -1(当然他这边也可以直接写作  ~0 ,但就不能很好的达到混淆的效果,毕竟混淆后是仅由符号组成的代码)

第二句,也可以很明显看到这个数组对象中存储的值是由0-10 a-f 之间的字符,也就正好完整的表示了十六进制的所有字符。

第三句,实际上是按照第二句赋值后的混淆数组,构成一个 constructor 字符串。

第四句,构造一个 return 字符串

第五句,构造一个匿名函数体

第六句,将我们原本的代码混淆后,作为参数传递给前面的匿名参数里,并执行。

 

constructor

在这里需要说明下,其中的构造函数执行原理。并非通过eval,而是通过constructor(构造方法)。

因JS万物皆对象,所以其中的Number也是对象,0也是对象、1也是对象、“123”是String对象,……都是对象。

所以,这行代码是这样实现一个空函数体的。
 

($.___) == 0
[$.$_]  其中的 $.$_ 接上面代码,也就是constructor字符串
那么拼接到一起就是 0["constructor"]["constructor"]   也等同于下面这一行内容
$.$ = ($.___)[$.$_][$.$_];

也等同于 eval

 

最终执行

那么,到了最后一行,也就是执行了。将已经编好的代码扔到匿名函数里进行执行。(注意:最后有一个()进行自执行)

# f(  "return" + '"' + "你的代码" + '"')   这一步构造了一个函数体
# $.$($.$($.$$ + "\"" + "\"")()) 		这一步构造一个新的函数体,参数是上一步的函数体,也就是 匿名函数。
# $.$($.$($.$$ + "\"" + "\"")())();    最后再通过()调用自执行。

# 最终如下
$.$($.$($.$$ + "\"" + "\"")())();

此时,我们的代码算是执行完毕了。不过此时,原本构造的$ 键值对数组,已经改变了,在构造constructor过程及之后,又附加了几个值。

 

引用结构

下图简单批注,可对比看到,也就为了后面的运行引用做准备。

 

源码分析

运行原理大致我们看明白了,接下来来分析下源代码,看他是如何将代码编码混淆的。

下图是我简单批注后的源代码,也是第一次分析时留下的注释,比较散乱。

 

逐步分析

简单看过,之后我们逐步分下下执行过程。

首先可以看到,有一个固定的声明数组:b (简称:b数组)

b数组中,是固定的一些由符号组成的值,也就对应后面的0-9 a-f的区间,数一下,正好是16位。

for循环是将text(我们的原代码),逐个字符开始进行编码。

模拟走一遍流程,如最初时我们将 a 进行编码,text.charCodeAt( i ) 即获得 a 的Unicode 编码,也就是97。

现在:n = 97 = a

接下来进入判断流程,如果n等于0x22 或者等于0x5c,就需要将其添加反斜杠进行转义保存,其值也需要转换值十六进制。

如果是a,则会将其存储为 "\\\61"

> "\\\\\\" + "a".charCodeAt(0).toString(16);
< "\\\61"

很显然这里我们的a不符合判断条件,判断条件中的0x22和0x5c分别对应的ASCII码是 "(双引号)\ (反斜杠)。也是为了拼接时的代码冲突,才将其转义。

此时我们通过查看对照ASCII码,更好的理解分析其中的判断逻辑。

第二个判断是也在图中标注了,如果是特殊字符,则原样记录。

第三个判断,将0-F之间的数据用b数组很好的进行引用代替。

第四、五、六、七个判断分别对这个几个字符(l o t u )特殊对待进行转码。
第八个判断,如果是字符是在合法的ASCII(128字符)以内,则将其转换为8进制存储,并将其的每一位替换成b数组中的字符引用。

举例:我们刚才的a字符,十进制97,八进制就是141,那么存储起来就是

> "\\\141"
< "\a"

混淆后就是这般:

> "\\\\\"+" + "a".charCodeAt(0).toString( 8 ).replace( /[0-7]/g, function(c){ return "$" + "."+b[ c ]+"+" } );
< "\\"+$.__$+$.$__+$.__$+"

最后一个else中的就是替换其他双字节字符,如汉字:

> "\\\\\"+" + "$" + "._+" + "中国".charCodeAt(0).toString(16).replace( /[0-9a-f]/gi, function(c){ return "$" + "."+b[parseInt(c,16)]+"+"} );
< "\\"+$._+$.$__+$.$$$_+$._$_+$.$$_$+"

 

经过一轮混淆判断之后,将混淆的内容存储到 r 中,s 则类似于一个缓冲区。

 

声明函数体

后面则是我们最开始分析的编码后的代码。

这里主要工作是构造一个函数体结构为后面执行做准备。

可以看到声明函数体后,将我们编码后的  r 作为参数传给函数体并自执行。也等同于最后面的匿名函数。

这个函数的声明过程到这里就执行完毕了!

 

混淆变体

如果此时你想,将代码稍微改改,变换一下混淆的引用元素或者混淆方法,那也是可以的。

我们将最开始的b数组中对应的0-F区间引用名,逐个替换。

如下:

当然还有后面动态添加的 o、t、u、constructor、return、f函数等一一用新的字符替换。

即最开始的b数组 我们这样定义:

var b=[ "富强", "民主", "文明", "和谐", "自由", "平等", "公正", "法治", "爱国", "敬业", "诚信", "友善", "富强民主", "文明和谐", "自由平等", "公正法治", ];

函数体部分:

图中的部分代码没有替换干净,如:![]+"",是因为截图时是之前的了,这里都是可以替换的。

参考下表:

(!(富强+富强)+"") =   (![] + "") = "false"
(!(富强-富强)+"") = (!"" + "") = "true"
({富强:富强}+"")  = ({}+ "") = "[object Object]"

这里用"富强"的位置可以换做其他任意字符,之所以选择"富强"原因而不用其他字符的原因,是为了选择出现率最高让代码更混乱。

替换后的代码并编码如下:

富强 = ~"富强";
富强 = {
	富强: ++富强,
	公正法治: (!!(富强 - 富强)+"")[富强],
	民主: ++富强,
	诚信: (!!(富强 - 富强)+"")[富强],
	文明: ++富强,
	友善: ({富强:富强}+"")[富强],
	文明和谐: (富强[富强] + "")[富强],
	和谐: ++富强,
	自由平等: (!(富强-富强)+"")[富强],
	自由: ++富强,
	平等: ++富强,
	富强民主: ({富强:富强}+"")[富强],
	公正: ++富强,
	法治: ++富强,
	爱国: ++富强,
	敬业: ++富强
};
富强.民主和谐 = (富强.民主和谐 = 富强 + "")[富强.平等] + (富强.爱国敬业 = 富强.民主和谐[富强.民主]) + (富强.文明自由 = (富强.和谐平等 + "")[富强.民主]) + ((!富强) + "")[富强.和谐] + (富强.诚信友善 = 富强.民主和谐[富强.公正]) + (富强.和谐平等 = (!(富强-富强)+"")[富强.民主]) + (富强.富强文明 = (!(富强-富强)+"")[富强.文明]) + 富强.民主和谐[富强.平等] + 富强.诚信友善 + 富强.爱国敬业 + 富强.和谐平等;
富强.文明自由 = 富强.和谐平等 + (!(富强-富强)+"")[富强.和谐] + 富强.诚信友善 + 富强.富强文明 + 富强.和谐平等 + 富强.文明自由;
富强.和谐平等 = (富强.富强)[富强.民主和谐][富强.民主和谐];
富强.和谐平等(富强.和谐平等(富强.文明自由 + "\"" + 富强.富强民主 + 富强.爱国敬业 + "\\" + 富强.民主 + 富强.平等 + 富强.公正 + "\\" + 富强.民主 + 富强.公正 + 富强.和谐 + 富强.爱国敬业 + (!(富强+富强)+"")[富强.文明] + 富强.自由平等 + "." + (!(富强+富强)+"")[富强.文明] + 富强.爱国敬业 + "\\" + 富强.民主 + 富强.自由 + 富强.法治 + "(" + 富强.民主 + 富强.民主 + 富强.民主 + 富强.民主 + ")" + "\"")())();

压缩后如下:

富强=~"富强";富强={富强:++富强,公正法治:(!!(富强-富强)+"")[富强],民主:++富强,诚信:(!!(富强-富强)+"")[富强],文明:++富强,友善:({富强:富强}+"")[富强],文明和谐:(富强[富强]+"")[富强],和谐:++富强,自由平等:(!(富强-富强)+"")[富强],自由:++富强,平等:++富强,富强民主:({富强:富强}+"")[富强],公正:++富强,法治:++富强,爱国:++富强,敬业:++富强};富强.民主和谐=(富强.民主和谐=富强+"")[富强.平等]+(富强.爱国敬业=富强.民主和谐[富强.民主])+(富强.文明自由=(富强.和谐平等+"")[富强.民主])+((!富强)+"")[富强.和谐]+(富强.诚信友善=富强.民主和谐[富强.公正])+(富强.和谐平等=(!(富强-富强)+"")[富强.民主])+(富强.富强文明=(!(富强-富强)+"")[富强.文明])+富强.民主和谐[富强.平等]+富强.诚信友善+富强.爱国敬业+富强.和谐平等;富强.文明自由=富强.和谐平等+(!(富强-富强)+"")[富强.和谐]+富强.诚信友善+富强.富强文明+富强.和谐平等+富强.文明自由;富强.和谐平等=(富强.富强)[富强.民主和谐][富强.民主和谐];富强.和谐平等(富强.和谐平等(富强.文明自由+"\""+富强.富强民主+富强.爱国敬业+"\\"+富强.民主+富强.平等+富强.公正+"\\"+富强.民主+富强.公正+富强.和谐+富强.爱国敬业+(!(富强+富强)+"")[富强.文明]+富强.自由平等+"."+(!(富强+富强)+"")[富强.文明]+富强.爱国敬业+"\\"+富强.民主+富强.自由+富强.法治+"("+富强.民主+富强.民主+富强.民主+富强.民主+")"+"\"")())();

运行效果:

 

这种方式用来混淆JS代码,并不能防止破解,只能骗过不了解JS的新手,比较适用于的场景就是防止无脑爬虫抓取页面信息。以及配合其他混淆规则效果会更好。

最后粘贴一份我更改过后的JS混淆过程代码,因用了中文,后面的双字节支持会有问题,也没来得及修正。所以双字节会报错。

// 富强、民主、文明、和谐、自由、平等、公正、法治、爱国、敬业、诚信、友善
// _$ = o = 爱国敬业
// __ = t = 诚信友善
// _ = u = 富强文明
// $_ = constructor  = 民主和谐
// $$ = return = 文明自由
// $ = f函数 = 和谐平等

function jjencode( gv, text )
{
    var r="";
    var n;
    var t;
    var b=[ "___", "__$", "_$_", "_$$", "$__", "$_$", "$$_", "$$$", "$___", "$__$", "$_$_", "$_$$", "$$__", "$$_$", "$$$_", "$$$$", ];
    var b=[ "富强", "民主", "文明", "和谐", "自由", "平等", "公正", "法治", "爱国", "敬业", "诚信", "友善", "富强民主", "文明和谐", "自由平等", "公正法治", ];
    var s = "";
    for( var i = 0; i < text.length; i++ ){
        n = text.charCodeAt( i ); // 获取字符Unicode码
        if( n == 0x22 || n == 0x5c ){ // " || \ 
            s += "\\\\\\" + text.charAt( i ).toString(16);
        }else if( (0x21 <= n && n <= 0x2f) || (0x3A <= n && n <= 0x40) || ( 0x5b <= n && n <= 0x60 ) || ( 0x7b <= n && n <= 0x7f ) ){
			// 	(! <= n && n<= /) || ( : <= n && n <= @) || ( [ <= n && n <= `) || ( { <= n && n <= "")
        //}else if( (0x20 <= n && n <= 0x2f) || (0x3A <= n == 0x40) || ( 0x5b <= n && n <= 0x60 ) || ( 0x7b <= n && n <= 0x7f ) ){
            s += text.charAt( i );//特殊字符原本输出
        }else if( (0x30 <= n && n <= 0x39 ) || (0x61 <= n && n <= 0x66 ) ){
			// 0-9 数字 || a-f
            if( s ) r += "\"" + s +"\"+";
			// " " +
			// " "+$.__$+
			// "console.log(1)"+
			console.log(n);
			// 如果是数字,用变量b中对应的值代替(0-9) 
			// 如果是a-f,则减57得A-F区间,对应b中数组a-f
			console.log(n < 0x40 ? n - 0x30 : n - 0x57);
            r += gv + "." + b[ n < 0x40 ? n - 0x30 : n - 0x57 ] + "+";
            s="";
			// 清空s
        }else if( n == 0x6c ){ // 'l'
			// 和上面一样,s有内容则将s包裹起来,再拼接到r中
            if( s ) r += "\"" + s + "\"+";
			
			// 从([!]+"")数组中取第第三个成员,也就是索引2的值用来混淆代表l 字符
			// ([!]+"") 也就是 "false" 字符串,第三个就是l
            r += "(![]+\"\")[" + gv + ".文明]+";
            s = "";
			// 清空s
        }else if( n == 0x6f ){ // 'o'
			// 和上面一样,混淆o 字符
            if( s ) r += "\"" + s + "\"+";
            r += gv + ".爱国敬业+"; // # 没看懂这部分
            s = "";
			// 清空s
        }else if( n == 0x74 ){ // 't'
			// 和上面一样,混淆t字符
            if( s ) r += "\"" + s + "\"+";
            r += gv + ".诚信友善+";
            s = "";
        }else if( n == 0x75 ){ // 'u'
			// 和上面一样,混淆u字符
            if( s ) r += "\"" + s + "\"+";
			// 没看懂这部分
            r += gv + ".富强文明+";
            s = "";
        }else if( n < 128 ){
			// 如果是正常的128个ASCII字符以内的字符
			// 如果s有数据,添加前引号包裹,再拼接到r
            if( s ) r += "\"" + s;
			// 否则直接给r拼接引号(可能结束引号,也可能是开始)
            else r += "\"";
			//  拼接转义符 和引号, 再将字符取8进制,且将8进制的数字用b数组中的0-7代替表示。
            r += "\\\\\"+" + n.toString( 8 ).replace( /[0-7]/g, function(c){ return gv + "."+b[ c ]+"+" } );
            s = "";// 清空s
        }else{
			// 其他大于128的字符,进行引号包裹
            if( s ) r += "\"" + s;
            else r += "\"";
			// 拼接转义符和引号,再拼接一个b数组中的_+( u ), 然后将字符码转换到16进制,再将0-f的数据用b数组代替表示。
            r += "\\\\\"+" + gv + "._+" + n.toString(16).replace( /[0-9a-f]/gi, function(c){ return gv + "."+b[parseInt(c,16)]+"+"} );
            s = "";
			// 清空s
        }
    }
	// 如果s有内容,则将s用引号包裹。附加到r上。
    if( s ) r += "\"" + s + "\"+";
	console.log(r);
	console.log(s);

	// 声明基础字符以及函数体
    r = 
    gv + "=~\"富强\";" +                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
    gv + "={富强:++" + gv +",公正法治:(![]+\"\")["+gv+"],民主:++"+gv+",诚信:(![]+\"\")["+gv+"],文明:++"+
    gv+",友善:({}+\"\")["+gv+"],文明和谐:("+gv+"["+gv+"]+\"\")["+gv+"],和谐:++"+gv+",自由平等:(!\"\"+\"\")["+
    gv+"],自由:++"+gv+",平等:++"+gv+",富强民主:({}+\"\")["+gv+"],公正:++"+gv+",法治:++"+gv+",爱国:++"+gv+",敬业:++"+gv+"};"+
    gv+".民主和谐="+
    "("+gv+".民主和谐="+gv+"+\"\")["+gv+".平等]+"+
    "("+gv+".爱国敬业="+gv+".民主和谐["+gv+".民主])+"+
    "("+gv+".文明自由=("+gv+".和谐平等+\"\")["+gv+".民主])+"+
    "((!"+gv+")+\"\")["+gv+".和谐]+"+
    "("+gv+".诚信友善="+gv+".民主和谐["+gv+".公正])+"+
    "("+gv+".和谐平等=(!\"\"+\"\")["+gv+".民主])+"+
    "("+gv+".富强文明=(!\"\"+\"\")["+gv+".文明])+"+
    gv+".民主和谐["+gv+".平等]+"+
    gv+".诚信友善+"+
    gv+".爱国敬业+"+
    gv+".和谐平等;"+
    gv+".文明自由="+
    gv+".和谐平等+"+
    "(!\"\"+\"\")["+gv+".和谐]+"+
    gv+".诚信友善+"+
    gv+".富强文明+"+
    gv+".和谐平等+"+
    gv+".文明自由;"+
    gv+".和谐平等=("+gv+".富强)["+gv+".民主和谐]["+gv+".民主和谐];"+
    gv+".和谐平等("+gv+".和谐平等("+gv+".文明自由+\"\\\"\"+" + r + "\"\\\"\")())();";

    return r;
}

还有一份原作者的ppt可以阅览一下:http://utf-8.jp/public/20090710/jjencode.pps

如果有更好的JS混淆编码方式也欢迎留言和我交流!

發表評論
StudioEIM - 冒险者讲习所
0:00