注册
web

也只有JavaScript可以写出这么离谱的代码了吧


今天,有个朋友给我发了一串神秘的字符( (!(~+[]) + {})[--[~+''][+[]] * [~+[]] + ~~!+[]] + ({} + [])[[~!+[]] * ~+[]] ),还要我在控制台打印一下试试




好家伙,原来JavaScrip还能这样玩,那这到底是什么原理呢?


字符串解析


这段代码是一个典型的 JavaScript 混淆代码,通过一系列运算和隐式类型转换来生成字符串。首先我们先解析一下这段字符串,不难发现,这个字符串可以划分为两个部分:



第一部分



(!(+[]) + {})[--[+''][+[]] * [~+[]] + ~~!+[]]



拆解步骤:



  • ~+[]

    +[] 将空数组转换为数字 0~0 按位取反得到 -1



  • [~+''][+[]]

    ~+'' 先将空字符串转为数字 0,再取反得到 -1,即 [-1]


    [+[]] 等价于 [0],因此 [-1][0] 得到 -1





  • --[~+''][+[]]

    --[-1][0],递减后得到 -2



  • [~+[]]

    和前面的一样,即 [-1]
  • ~~!+[]

    +[]0!0true~~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!0true~true 按位取反得到 -2



  • [~!+[]]

    [-2]
  • [~!+[]] * ~+[]

    [-2] 转为数字 -2~+[]-1,计算:-2 * -1 = 2



  • "[object Object]"[2]

    索引 2 对应的字符是 'b'

合并结果


将两部分结果拼接:'s' + 'b' = 'sb'



核心技巧



  1. 隐式类型转换

    • 数组/对象通过 + 运算转为字符串。
    • !~+ 等运算符触发类型转换(如 +[] → 0[]+{} → "[object Object]"+{}+[] → "NaN")。





  1. 按位运算

    ~ 用于生成特定数值(如 -1-2)。
  2. 数组索引

    通过计算得到字符串索引(如 32),提取目标字符。

实现一个代码混淆函数


通过对前面那串神秘字符的分析,我们也知道了它的核心思路就是通过JavaScript的隐式类型转换规则对字符进行转换,那么我们是不是可以将我们的代码也都转换成这些字符,来达到一个代码混淆的效果呢?


1、数字转换



  • 0+[] 将空数组转换为数字 0
  • 1![] 将空数组转为 false!![]再次取反得到 true+!![]+号让true隐式转换为1
  • 其他数字 都可以通过10进行加减乘除或拼接来得到

{
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 了~


体验地址


jyeontu.xyz/JDemo/#/cod…




源码


组件源码已开源到gitee,有兴趣的也可以到这里看看:gitee.com/zheng_yongt…



  • 🌟觉得有帮助的可以点个star~
  • 🖊有什么问题或错误可以指出,欢迎pr~
  • 📬有什么想要实现的组件或想法可以联系我~

公众号


关注公众号『 前端也能这么有趣 』,获取更多有趣内容。


发送 加群 还可以加入群聊,一起来学习(摸鱼)吧~


说在后面



🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『前端也能这么有趣』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。



作者:JYeontu
来源:juejin.cn/post/7503846429082468389

0 个评论

要回复文章请先登录注册