jjencode&&aaencode类似js编码原理探究

一.探究背景

以前在一次做ctf的时候,发现了类似如下的神奇编码。

゚ω゚ノ= /`m´)ノ ~┻━┻   //*´∇`*/ ['_']; o=(゚ー゚)  =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_');

当时没多想网上查了一下发现是aaencode编码后的就直接找网站解密做完了。最近在看JS混淆方面的东西,于是这种编码方式又进入了我的视线,于是稍稍研究这个东西的原理是什么。

二.编码分析过程

首先JS解释器只能识别JS代码,那么这些颜文字想要执行必定需要含有将颜文字解析成JS代码的片段。于是我找到aaencode的编码程序,如下:

function aaencode( text )
{
    var t;
    var b = [
		"(c^_^o)",
		"(゚Θ゚)",
		"((o^_^o) - (゚Θ゚))",
		"(o^_^o)",
		"(゚ー゚)",
		"((゚ー゚) + (゚Θ゚))",
		"((o^_^o) +(o^_^o))",
		"((゚ー゚) + (o^_^o))",
		"((゚ー゚) + (゚ー゚))",
		"((゚ー゚) + (゚ー゚) + (゚Θ゚))",
		"(゚Д゚) .゚ω゚ノ",
		"(゚Д゚) .゚Θ゚ノ",
		"(゚Д゚) ['c']",
		"(゚Д゚) .゚ー゚ノ",
		"(゚Д゚) .゚Д゚ノ",
		"(゚Д゚) [゚Θ゚]"
        ];
	var r = "゚ω゚ノ= /`m´)ノ ~┻━┻   //*´∇`*/ ['_']; o=(゚ー゚)  =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); "; 
	
	if( /ひだまりスケッチ×(365|356)\s*来週も見てくださいね[!!]/.test( text ) ){
		r += "X=_=3; ";
		r += "\r\n\r\n    X / _ / X < \"来週も見てくださいね!\";\r\n\r\n";
	}
    r += "(゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);"+
        "(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] "+
        ",゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] "+
        ",゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];"+
        "(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];"+
        "(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];"+
        "(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + "+
        "((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+"+
        "((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+"+
        "((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+"+
        "((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];"+
        "(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+"+
        "((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+"+
        "((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; "+
        "(゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\\\'; "+
        "(゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];"+ 
		"(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];"+//TODO
        "(゚Д゚) [゚o゚]='\\\"';"+ 
        "(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+";
    r += "(゚Д゚)[゚o゚]+ ";
    for( var i = 0; i < text.length; i++ ){
        n = text.charCodeAt( i );
        t = "(゚Д゚)[゚ε゚]+";
		if( n <= 127 ){
			t += n.toString( 8 ).replace( /[0-7]/g, function(c){ return b[ c ] + "+ "; } );
		}else{
			var m = /[0-9a-f]{4}$/.exec( "000" + n.toString(16 ) )[0];
			t += "(o゚ー゚o)+ " + m.replace( /[0-9a-f]/gi, function(c){ return b[ parseInt( c,16 ) ] + "+ "; } );
		}
        r += t;

    }
    r += "(゚Д゚)[゚o゚]) (゚Θ゚)) ('_');";
    return r;


}

事实上这个程序就是日本人写的(“゚ω゚ノ= /`m´)ノ ~┻━┻,好可爱)。先看for循环部分吧(其他地方都是颜文字),看上去像是将输入的原程序的每个字符(基本都是可见字符<127)转为8进制字符串然后用数组b里的颜文字进行替换。
那么看看b是什么,先把编码后的扔进console执行,然后这些颜文字就有各自的值,再看看b。
在这里插入图片描述
试了一些发现就是16进制。于是编码的过程就为如果为ascii字符就根据其8进制的每个位替换为b中对应的颜文字,如字符’a’,对应的8进制为141,那么就将其替换为(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)。然后每次t在替换之前都会有个初始值(゚Д゚)[゚ε゚]+ 这个在console中看了一下值为”",那么"(゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)“这个颜文字在执行的时候值就变为”\141",这个就是字符’a’。同理else语句中的替换是unicode字符集替换成颜文字(可能是为了兼容日文)。我们来验证一下,将编码函数输入console,在t那加入一个console.log(t),然后调用编码函数,aaencode(‘alert(“Hello, JavaScript”)’)。查看console的输出。
在这里插入图片描述
确实就如上面分析的那样进行编码的,在最后运行的时候这些颜文字的值就是alert(“Hello, JavaScript”)。
总结一下:编码过程就是将原JS代码中的字符都转化为8进制或者16进制,将其替换为b中的颜文字,b中的颜文字在解码执行的时候值是0-f,理论上0-f可以表示任意字符,在其前面加\或\u就可以表示相应字符。

三.解码执行过程

那么到这里我们还有几个问题需要解决:
1.上面编码函数中的b数组那些颜文字为什么在执行的时候值会变成0-f
2.编码后的颜文字丢到浏览器就能直接执行,原程序是如何被调用执行的。

要解决这些问题要从编码程序循环部分上面的颜文字中得知了,首先解决第一个问题。
我们以分号分割上面的颜文字。

゚ω゚ノ = /`m´)ノ ~┻━┻   / /*´∇`*/ ['_'];
o = (゚ー゚) = _ = 3;
c = (゚Θ゚) = (゚ー゚) - (゚ー゚);
(゚Д゚) = (゚Θ゚) = (o ^ _ ^ o) / (o ^ _ ^ o);
(゚Д゚) = {
    ゚Θ゚: '_',
    ゚ω゚ノ: ((゚ω゚ノ == 3) + '_')[゚Θ゚],
    ゚ー゚ノ: (゚ω゚ノ + '_')[o ^ _ ^ o - (゚Θ゚)],
    ゚Д゚ノ: ((゚ー゚ == 3) + '_')[゚ー゚]
};
(゚Д゚)[゚Θ゚] = ((゚ω゚ノ == 3) + '_')[c ^ _ ^ o];
(゚Д゚)['c'] = ((゚Д゚) + '_')[(゚ー゚) + (゚ー゚) - (゚Θ゚)];
(゚Д゚)['o'] = ((゚Д゚) + '_')[゚Θ゚];
(゚o゚) = (゚Д゚)['c'] + (゚Д゚)['o'] + (゚ω゚ノ + '_')[゚Θ゚] + ((゚ω゚ノ == 3) + '_')[゚ー゚] + ((゚Д゚) + '_')[(゚ー゚) + (゚ー゚)] + ((゚ー゚ == 3) + '_')[゚Θ゚] + ((゚ー゚ == 3) + '_')[(゚ー゚) - (゚Θ゚)] + (゚Д゚)['c'] + ((゚Д゚) + '_')[(゚ー゚) + (゚ー゚)] + (゚Д゚)['o'] + ((゚ー゚ == 3) + '_')[゚Θ゚];
(゚Д゚)['_'] = (o ^ _ ^ o)[゚o゚][゚o゚];
(゚ε゚) = ((゚ー゚ == 3) + '_')[゚Θ゚] + (゚Д゚).゚Д゚ノ + ((゚Д゚) + '_')[(゚ー゚) + (゚ー゚)] + ((゚ー゚ == 3) + '_')[o ^ _ ^ o - ゚Θ゚] + ((゚ー゚ == 3) + '_')[゚Θ゚] + (゚ω゚ノ + '_')[゚Θ゚];
(゚ー゚) += (゚Θ゚);
(゚Д゚)[゚ε゚] = '\\';
(゚Д゚).゚Θ゚ノ = (゚Д゚ + ゚ー゚)[o ^ _ ^ o - (゚Θ゚)];
(o゚ー゚o) = (゚ω゚ノ + '_')[c ^ _ ^ o];
(゚Д゚)[゚o゚] = '\"';
(゚Д゚)['_']((゚Д゚)['_'](゚ε゚ + (゚Д゚)[゚o゚] + (゚Д゚)[゚ε゚] + (゚Θ゚) + (゚ー゚) + (゚Θ゚) + (゚Д゚)[゚ε゚] + (゚Θ゚) + ((゚ー゚) + (゚Θ゚)) + (゚ー゚) + (゚Д゚)[゚ε゚] + (゚Θ゚) + (゚ー゚) + ((゚ー゚) + (゚Θ゚)) + (゚Д゚)[゚ε゚] + (゚Θ゚) + ((o ^ _ ^ o) + (o ^ _ ^ o)) + ((o ^ _ ^ o) - (゚Θ゚)) + (゚Д゚)[゚ε゚] + (゚Θ゚) + ((o ^ _ ^ o) + (o ^ _ ^ o)) + (゚ー゚) + (゚Д゚)[゚ε゚] + ((゚ー゚) + (゚Θ゚)) + (c ^ _ ^ o) + (゚Д゚)[゚ε゚] + (゚ー゚) + ((o ^ _ ^ o) - (゚Θ゚)) + (゚Д゚)[゚ε゚] + (゚Θ゚) + (゚Θ゚) + (c ^ _ ^ o) + (゚Д゚)[゚ε゚] + (゚Θ゚) + (゚ー゚) + ((゚ー゚) + (゚Θ゚)) + (゚Д゚)[゚ε゚] + (゚Θ゚) + ((゚ー゚) + (゚Θ゚)) + (゚ー゚) + (゚Д゚)[゚ε゚] + (゚Θ゚) + ((゚ー゚) + (゚Θ゚)) + (゚ー゚) + (゚Д゚)[゚ε゚] + (゚Θ゚) + ((゚ー゚) + (゚Θ゚)) + ((゚ー゚) + (o ^ _ ^ o)) + (゚Д゚)[゚ε゚] + ((゚ー゚) + (゚Θ゚)) + (゚ー゚) + (゚Д゚)[゚ε゚] + (゚ー゚) + (c ^ _ ^ o) + (゚Д゚)[゚ε゚] + (゚Θ゚) + (゚Θ゚) + ((o ^ _ ^ o) - (゚Θ゚)) + (゚Д゚)[゚ε゚] + (゚Θ゚) + (゚ー゚) + (゚Θ゚) + (゚Д゚)[゚ε゚] + (゚Θ゚) + ((o ^ _ ^ o) + (o ^ _ ^ o)) + ((o ^ _ ^ o) + (o ^ _ ^ o)) + (゚Д゚)[゚ε゚] + (゚Θ゚) + (゚ー゚) + (゚Θ゚) + (゚Д゚)[゚ε゚] + (゚Θ゚) + ((o ^ _ ^ o) - (゚Θ゚)) + (o ^ _ ^ o) + (゚Д゚)[゚ε゚] + (゚Θ゚) + (゚ー゚) + (o ^ _ ^ o) + (゚Д゚)[゚ε゚] + (゚Θ゚) + ((o ^ _ ^ o) + (o ^ _ ^ o)) + ((o ^ _ ^ o) - (゚Θ゚)) + (゚Д゚)[゚ε゚] + (゚Θ゚) + ((゚ー゚) + (゚Θ゚)) + (゚Θ゚) + (゚Д゚)[゚ε゚] + (゚Θ゚) + ((o ^ _ ^ o) + (o ^ _ ^ o)) + (c ^ _ ^ o) + (゚Д゚)[゚ε゚] + (゚Θ゚) + ((o ^ _ ^ o) + (o ^ _ ^ o)) + (゚ー゚) + (゚Д゚)[゚ε゚] + (゚ー゚) + ((o ^ _ ^ o) - (゚Θ゚)) + (゚Д゚)[゚ε゚] + ((゚ー゚) + (゚Θ゚)) + (゚Θ゚) + (゚Д゚)[゚o゚])(゚Θ゚))('_');

第一句゚ω゚ノ= /`m´)ノ ~┻━┻ //´∇`/ [’’]; #这个好像并没有什么用
第二句o=(゚ー゚) =
=3; #这里可以注意到以上两个颜文字被赋值为3
第三句c=(゚Θ゚) =(゚ー゚)-(゚ー゚);#这里减法操作,这个颜文字的值为0
第四句(゚Д゚) =(゚Θ゚)= (o_o)/ (o_o);#这里除法操作,这个颜文字的值为1
…(实际上这里通过加加减减数字都可以出来篇幅有限就不写了)
那么字符怎么出来呢。
第五句(゚Д゚)={゚Θ゚: ‘’ ,゚ω゚ノ : ((゚ω゚ノ==3) +’’) [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ ‘’)[o_o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +’’)[゚ー゚] }; #这个就厉害了。我们看看这个颜文字的值是什么。

在这里插入图片描述

这里神奇的出现字符了,实际上是利用了JS的一点特性,拿字母’a’举例。看看((゚ω゚ノ==3) +’_’) [゚Θ゚]这个值是什么。
在这里插入图片描述
首先通过表达式得出bool值false然后将其转化为字符串,再通过上面已经有的数字当索引来得到"false"中的所有字符!这里我觉得还是挺巧妙的。于是许多字符我们都可以得到了,比如“true”,“undefined”,"NaN"等。从而可以推出其他字符。

第一个问题解决了,那么第二个问题我们原程序是如何调用执行的。
看看最后一句很长的,看看值是什么。将其丢到console中之后就弹出弹窗了,说明我们的原程序已经执行了,我们看看格式xx(xx)(xx)。先看看中间一个括号是什么。
在这里插入图片描述
发现就是我们的原程序,再看看前面两个颜文字是什么。
在这里插入图片描述
竟然是函数调用,那么最后一个()就是传递的参数了,暂且不管,我们看看这个颜文字为什么是函数调用。往上看到这么一个赋值语句(゚Д゚)[’_’] = (o ^ _ ^ o)[゚o゚][゚o゚]; 那么就要看看(o ^ _ ^ o) ,[゚o゚], [゚o゚] 是什么了。
在这里插入图片描述
看到这里就基本知道是怎么回事了,JS中还有一个函数定义的方式[][“constructor”][“constructor”]
在这里插入图片描述
所以实际上最后一行颜文字就是3[“constructor”][“constructor”](alert(“Hello, JavaScript”))();通过这种方式完成了一个函数调用。那么第二个问题也解决了。

四.总结

编码程序将原JS代码中的字符都转化为8进制或者16进制,将其替换为b中的颜文字添加在解码片段之后,在解码执行的时候的值就是原程序字符串。
解码运行过程通过各种骚操作构造出[][“constructor”][“constructor”](code)()来执行原程序。
其他类似的编码方式如jjencode,jsfuck大致原理都是这样。
安全性方面仅仅是一个编码方式并没有实际的混淆作用,因为将最后的括号去掉,丢到console里执行直接能还原出原程序。
在这里插入图片描述

PS:最后再贴一个自己随便仿制的一个编码方式hhh

$$=1;$=[($+"_")[$$+!+[]+$$]+($+"_")[$$+!+[]+$$+$$+!+[]+$$]+($+"_")[$$+!+[]+$$+$$+!+[]+$$+$$]+(($$==$)+"_")[$$+!+[]+$$]+(($$==$$)+"_")[$$-!+[]]+(($$==$$)+"_")[$$]+(($$==$$)+"_")[$$+!+[]]+($+"_")[$$+!+[]+$$]+(($$==$$)+"_")[$$-!+[]]+($+"_")[$$+!+[]+$$+$$+!+[]+$$]+(($$==$$)+"_")[$$]];$$[$][$]((($$==$)+"_")[$$]+(($$==$)+"_")[$$+$$]+(($$==$$)+"_")[$$+!+[]+$$]+(($$==$$)+"_")[$$]+(($$==$$)+"_")[$$-!+[]]+"("+$$+")")("_")

猜你喜欢

转载自blog.csdn.net/github_36788573/article/details/102866435
今日推荐