注册
web

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

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

好家伙,原来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'

核心技巧

  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 个评论

要回复文章请先登录注册