本文最后更新于:2021年3月11日 下午
encode混淆
大体思路
这种让你看不懂代码的方式是通过编码实现的
编译器能都识别那些 由 16进制字符 或者 Unicode 字符
一般而言为了 让字符看起来非常难顶,代码作者会设计将字符转换成一些奇怪的字符
但为了不影响代码逻辑,这些奇怪字符的值依然与原本保持一致
代码会被保存为非常长的字符串格式
在多数情况下是类似于这样
()["constructor"]["constructor"](执行代码)()
- eval(执行代码)
当然,它不会明面的把函数写上,他会绕来绕去,让你看不出
AAencode
分析
既然是一个开源的,那就查看一下源码吧
Github: https://github.com/bprayudha/jquery.aaencode
源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| (function($) { var aaencode = function(text) { var t; var b = [ "(c^_^o)" , "(゚Θ゚)" , "((o^_^o) - (゚Θ゚))" , "(o^_^o)" , "(゚ー゚)" , "((゚ー゚) + (゚Θ゚))" , "((o^_^o) +(o^_^o))" , "((゚ー゚) + (o^_^o))" , "((゚ー゚) + (゚ー゚))" , "((゚ー゚) + (゚ー゚) + (゚Θ゚))" , "(゚Д゚) .゚ω゚ノ" , "(゚Д゚) .゚Θ゚ノ" , "(゚Д゚) ['c']" , "(゚Д゚) .゚ー゚ノ" , "(゚Д゚) .゚Д゚ノ" , "(゚Д゚) [゚Θ゚]" ]; var r = "゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); "; 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];" + "(゚Д゚) [゚o゚]='\\\"';" + "(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+" + "(゚Д゚)[゚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; }
$.fn.aaencode = function() { return aaencode(this.val()); } })(jQuery);
|
逐一调试观察逻辑并记录
(为了调试方便改写了一些格式,但内容没改)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
| 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=(゚Θ゚) =(゚ー゚)-(゚ー゚); "; 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];" + "(゚Д゚) [゚o゚]='\\\"';" + "(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_');";
for (var i = 0; i < text.length; i++) { n = text.charCodeAt(i); t = "(゚Д゚)[゚ε゚]+"; if (n <= 127) { n = n.toString(8); t += n.replace(/[0-7]/g, function (c) { return b[c] + "+ "; }); } else { n = "000" + n.toString(16); var m = /[0-9a-f]{4}$/.exec(n)[0]; m = m.replace(/[0-9a-f]/gi, function (c) { return b[parseInt(c, 16)] + "+ "; }); t += "(o゚ー゚o)+ " + m; } r += t;
}
r += "(゚Д゚)[゚o゚]) (゚Θ゚)) ('_');";
return r; }
|
在详细分析以后,过程是比较得明朗的
过程
定义一个 表情符号数组
为了增加迷惑性,设定一个表情符号数组,用作未来取代javascript
代码字符
定义外围函数包围原本的代码
最外面包裹着一层 执行解释函数
通过各种奇怪的符号构造出 ()["constructor"]["constructor"](执行代码)()
()["constructor"]["constructor"](执行代码)()
等价于Function (执行代码)()
,能执行代码
原本的js代码通过unicode编码
后映射到了一个数上,作者将这个数做了区分处理
- 这个数在0-127之间,说明是数字字母等javascript代码原本需要用到的字符 C0 控制与基本的 Latin(拉丁字母)
这种字符作者将数转为8进制后,将每一位的数转为表情字符
- 这个数超出127,说明这个字符并非常规的字母数字等,而是一些较少使用的字符,如中文之类的
这种字符作者将数转为16进制后,将每一位的数转为表情字符,最后在前面添加一个”(o゚ー゚o)”(实际上是字符 u)用作标识Unicode字符
- 为什么可以转为表情
实际上,在一开始的变量声明完毕以后,表情字符本身的值就等于序号(16进制,超出的会对应a-f)
这是作者设定好的,混淆是让你看不懂,并不会破坏逻辑本身
你可以尝试着去获取那些值
解法
删掉最后的('_');";
,若是不行,可以在后面加toString()
来把函数转为字符串输出
由于代码是()["constructor"]["constructor"](执行代码)()
这种形式的
如果你把最后的括号删掉,那么源代码函数就会暴露出来,直接得到源码了
进入虚拟空间VM即可看到源码
在执行混淆代码之前,打上断点,步进到混淆代码内部,分析堆栈,进入虚拟空间,就能看到源码了
如果内部代码执行报错,那么也可以通过报错的定位进入虚拟空间
Recluse
2020年8月13日14:53:10