>>>今天,有个朋友给我发了一串神秘的字符( (!(~+[]) + {})[--[~+''][+[]] * [~+[]] + ~~!+[]] + ({} + [])[[~!+[]] * ~+[]] ),还要我在控制台打印一下试试
好家伙,原来JavaScrip还能这样玩,那这到底是什么原理呢?
字符串解析
这段代码是一个典型的 JavaScript 混淆代码,通过一系列运算和隐式类型转换来生成字符串。首先我们先解析一下这段字符串,不难发现,这个字符串可以划分为两个部分:
第一部分
>>>(!(~+[]) + {})[--[~+''][+[]] * [~+[]] + ~~!+[]]
拆解步骤:
~+[]
+[]
将空数组转换为数字0
,~0
按位取反得到-1
。
[~+''][+[]]
~+''
先将空字符串转为数字0
,再取反得到-1
,即[-1]
。[+[]]
等价于[0]
,因此[-1][0]
得到-1
。
--[~+''][+[]]
即--[-1][0]
,递减后得到-2
。
[~+[]]
和前面的一样,即[-1]
。~~!+[]
+[]
为0
,!0
为true
,~~true
两次取反得到1
。
--[~+''][+[]] * [~+[]] + ~~!+[]
计算:-2 * -1 + 1 = 3
。
!(~+[])
~+[]
为-1
,!(-1)
为false
。
!(~+[]) + {}
false
转为字符串"false"
,与空对象拼接得到"false[object Object]"
。
"false[object Object]"[3]
索引3
对应的字符是's'
。
第二部分
>>>({} + [])[[~!+[]] * ~+[]]
拆解步骤:
({} + [])
空对象转为字符串"[object Object]"
,与空数组相加仍为"[object Object]"
。
~!+[]
+[]
为0
,!0
为true
,~true
按位取反得到-2
。
[~!+[]]
即[-2]
。[~!+[]] * ~+[]
[-2]
转为数字-2
,~+[]
为-1
,计算:-2 * -1 = 2
。
"[object Object]"[2]
索引2
对应的字符是'b'
。
合并结果
将两部分结果拼接:'s' + 'b' = 'sb'
。
核心技巧
隐式类型转换 数组/对象通过 +
运算转为字符串。!
、~
、+
等运算符触发类型转换(如+[] → 0
,[]+{} → "[object Object]"
,+{}+[] → "NaN"
)。
按位运算
~
用于生成特定数值(如-1
、-2
)。数组索引
通过计算得到字符串索引(如3
、2
),提取目标字符。
实现一个代码混淆函数
通过对前面那串神秘字符的分析,我们也知道了它的核心思路就是通过JavaScript的隐式类型转换规则对字符进行转换,那么我们是不是可以将我们的代码也都转换成这些字符,来达到一个代码混淆的效果呢?
1、数字转换
0: +[]
将空数组转换为数字0
1: ![]
将空数组转为 false ,!![]
再次取反得到 true ,+!![]
+号让true隐式转换为1其他数字 都可以通过1和0进行加减乘除或拼接来得到
{
0: "+[]",
1: "+!![]",
2: "!![]+!![]",
3: "!![]+!![]+!![]",
4: "(!![]+!![]) * (!![]+!![])",
5: "(!![]+!![]) * (!![]+!![]) + !![]",
6: "(!![]+!![]) * (!![]+!![]+!![])",
7: "(!![]+!![]) * (!![]+!![]+!![]) + !![]",
8: "(!![]+!![]) ** (!![]+!![]+!![])",
9: "(!![]+!![]+!![]) ** (!![]+!![])",
}
2、字母转换
undefined
([][[]]+[]) 相当于 [][0]+'' ,可以得到字符串 undefined
false
(![]+[]) 相当于 !true+'' ,可以得到字符串 false
true
(!![]+[]) 相当于 !!true+'' ,可以得到字符串 true
[object Object]
({} + []) ,空对象转为字符串 "[object Object]"
,与空数组相加仍为 "[object Object]"
。
NaN
(+{}+[]) ,{}会被隐式转为数字类型,对象无法被解析成有效数字,所以会返回 NaN
constructor
通过前面转换的字符串,我们可以拼接成完整的 constructor 字符串。
我们可以通过构造器来获取到更多的字符,比如:
3、其他字符
通过前面的方法我们就可以将大部分的字母都获取到了,但是还有部分字母获取不到,那么剩下的字母就和其他字符一样都可以通过下面这个方式来获取:
比如字母 U:
>>>ASCII 码 U → 八进制转十进制 85 → 转义为 \125,那么我们可以直接这样获得字母 U
所以我们只需要想办法得到函数构造器即可,还是要用到前面提到过的 constructor ,我们知道数组有很多内置的函数,比如 at:
那么 at 方法的构造器就是一个函数,我们直接通过 constructor 就可以获取到一个函数构造器
这里用到的字母都可以通过简单的转换得到,把字母通过前面的方法转换替换掉就可以了
好了,到这里你就实现了一个简单的 JSFuck 了~
体验地址
http://jyeontu.xyz/JDemo/#/codeObfuscation
源码
组件源码已开源到gitee,有兴趣的也可以到这里看看:https://gitee.com/zheng_yongtao/jyeontu-vue-demo
推荐本站淘宝优惠价购买喜欢的宝贝:
本文链接:https://hqyman.cn/post/11238.html 非本站原创文章欢迎转载,原创文章需保留本站地址!
休息一下~~