JS混淆-JJEncode、AAEncode、JSFuck
简介
JJEncode、AAEncode、JSFuck 都是由日本的同一个作者Yosuke HASEGAWA开发。
简介
JJEncode 最初是由日本作者 Yosuke HASEGAWA 于 2009 年开发的一个 web 程序,它可以将任意 JavaScript 编码转为仅使用 18 个符号的混淆形式 []()!+,\"$.:;_{}~=
,在线体验。
注意
JJEncode 易于解码,它不是实用的混淆,只是一个编码器,JJEncode 太有特点了,很容易被检测,而且还浏览器依赖,代码不能在某种浏览器上运行。它的缺点是压栈很严重,如果 JS 很大,去做加密可能内存溢出,所以只适合核心功能加密,事实上 JJEncode 商用的还是很少,不过认识一下并没有什么坏处。
示例
正常的一段 JS 代码
1 | alert("Hello, JavaScript") |
经过 JJEncode 混淆(自定义变量名为 $)之后的代码
1 | $=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+$.$_$_+(![]+"")[$._$_]+$.$$$_+"\\"+$.__$+$.$$_+$._$_+$.__+"(\\\"\\"+$.__$+$.__$+$.___+$.$$$_+(![]+"")[$._$_]+(![]+"")[$._$_]+$._$+",\\"+$.$__+$.___+"\\"+$.__$+$.__$+$._$_+$.$_$_+"\\"+$.__$+$.$$_+$.$$_+$.$_$_+"\\"+$.__$+$._$_+$._$$+$.$$__+"\\"+$.__$+$.$$_+$._$_+"\\"+$.__$+$.$_$+$.__$+"\\"+$.__$+$.$$_+$.___+$.__+"\\\")"+"\"")())(); |
解混淆
JJEncode 解混淆的方式很简单,以下介绍几种常见的方法:
- 使用在线工具直接解密
- JJEncode 的代码通常是一个自执行方法(IIFE),去掉代码最后面的
()
后,放到浏览器检查->控制台
里面去直接执行就可以看到源码 - 在线调试,在 JJEncode 代码第一行下断点,然后一步一步执行,最终也会在虚拟机(VM)里看到源码
案例
- 链接:https://spa10.scrape.center/
- 说明:NBA球星数据网站,数据纯前端渲染,Token经过加密处理,JavaScript 经过 JJEncode 混淆,适合 JavaScript 逆向分析。
简介
AAEncode 可以将任何 JavaScript 代码编码为日式表情符号,在线体验。
示例
正常的一段 JS 代码
1 | alert("Hello, JavaScript") |
经过 AAEncode 混淆之后的代码
1 | ゚ω゚ノ= /`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 代码第一行下断点,然后一步一步执行,最终也会在虚拟机(VM)里看到源码
案例
- 链接:https://spa11.scrape.center/
- 说明:NBA球星数据网站,数据纯前端渲染,Token经过加密处理,JavaScript 经过 AAEncode 混淆,适合 JavaScript 逆向分析。
简介
JSFuck 由日本的 Yosuke HASEGAWA 在 2010 创造,它可以将任意 JavaScript 编码转为仅使用 6 个符号的混淆形式 []()!+
,2012 年,Martin Kleppe 在 GitHub 上创建了一个 jsfuck 项目和一个 JSFuck.com 网站,其中包含使用该编码器实现的 Web 应用程序。JSFuck 可用于绕过对网站上提交的恶意代码的检测,例如跨站点脚本(XSS)攻击。JSFuck 的另一个潜在用途在于代码混淆,目前的 jQuery 就已经有经过 JSFuck 混淆后的功能齐全的版本。在线体验1 、 在线体验2。
示例
正常的一段 JS 代码
1 | alert(1) |
经过 JSFuck 混淆之后的代码
1 | [][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(+(!+[]+!+[]+!+[]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([]+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+((+[])[([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]])+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]])()((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[+!+[]+[!+[]+!+[]+!+[]]]+[+!+[]]+([+[]]+![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[!+[]+!+[]+[+[]]]) |
字符转换表
JSFuck 中常见的元素、数字、符号转换如下表,更多元素可参考 JSFuck 官方 GitHub 或 JSFuck 维基百科。
Character | JSFuck |
---|---|
false | ![] |
true | !![] or !+[] |
NaN | +[![]] |
undefined | [][[]] |
Infinity | +(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]]+[+[]]) |
Array | [] |
Number | +[] |
String | []+[] |
Boolean | ![] |
Function | []["filter"] |
eval | []["filter"]["constructor"]( CODE )() |
window | []["filter"]["constructor"]("return this")() |
+ |
(+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]])+[])[!+[]+!+[]] |
. |
(+(+!+[]+[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+[!+[]+!+[]]+[+[]])+[])[+!+[]] |
0 |
+[] |
1 |
+!![] or +!+[] |
2 |
!![]+!![] or !+[]+!+[] |
3 |
!![]+!![]+!![] or !+[]+!+[]+!+[] |
4 |
!![]+!![]+!![]+!![] or !+[]+!+[]+!+[]+!+[] |
5 |
!![]+!![]+!![]+!![]+!![] or !+[]+!+[]+!+[]+!+[]+!+[] |
6 |
!![]+!![]+!![]+!![]+!![]+!![] or !+[]+!+[]+!+[]+!+[]+!+[]+!+[] |
7 |
!![]+!![]+!![]+!![]+!![]+!![]+!![] or !+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[] |
8 |
!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![] or !+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[] |
9 |
!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![] or !+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[] |
a |
(![]+[])[+!+[]] |
d |
([][[]]+[])[!+[]+!+[]] |
e |
(!![]+[])[!+[]+!+[]+!+[]] |
f |
(![]+[])[+[]] |
i |
([![]]+[][[]])[+!+[]+[+[]]] |
I |
(+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+(+!+[])+(+[])+(+[])+(+[]))+[])[+[]] |
l |
(![]+[])[!+[]+!+[]] |
N |
(+[![]]+[])[+[]] |
n |
([][[]]+[])[+!+[]] |
r |
(!+[]+[])[+!+[]] |
s |
(![]+[])[!+[]+!+[]+!+[]] |
t |
(!+[]+[])[+[]] |
u |
([][[]]+[])[+[]] |
y |
(+[![]]+[+(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+(+!+[])+(+[])+(+[])+(+[]))])[+!+[]+[+[]]] |
混淆流程示例
我们以字母 a 为例,来演示一遍其混淆的流程
"false"[1]
:字母 a 取自字符串 false,在 false 中,a 的索引值是 1(false+[])[1]
:false 可以写成false+[]
,即布尔常量 false 加上一个空数组(![]+[])[1]
:false 又可以写成![]
,即否定应用于空数组(![]+[])[+true]
:1 是一个数字,我们可以把它写成+true
(![]+[])[+!![]]
:由于 false 是![]
,所以 true 就是!![]
,生成最终混淆代码
解混淆
JSFuck 在调用方法时通常都是通过 Function(xxx)()
和 eval(xxx)
的形式来执行,因此 JSFuck 常见解混淆的方式如下:
- 使用在线工具直接解密,在线工具1、在线工具2
- 针对 Function 的情况,复制代码最外层倒数第二个括号内的内容,放到浏览器里面去直接执行就可以看到源码
- 针对 eval 的情况,复制代码最外层最后一个括号内的内容,放到浏览器里面去直接执行就可以看到源码
- 使用 Hook 的方式,分别 Hook Function 和 eval,打印输出源码
- 使用 AST 进行解混淆,AST 的教程后续也会写,本文不详细介绍
如前面 alert(1)
的混淆代码,复制最外层最后一个括号内的内容到浏览器控制台,就可以看到源代码
案例
- 链接:https://spa12.scrape.center/
- 说明:NBA球星数据网站,数据纯前端渲染,Token 经过加密处理,JavaScript 经过 JSFuck 混淆,适合 JavaScript 逆向分析。