大家好,我是 ConardLi。
上周有个朋友在群里发了一段代码,复制到浏览器发现居然是可以运行的:
[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[+!+[]+[!+[]+!+[]+!+[]]]+([]+[])[(![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]()[+!+[]+[!+[]+!+[]]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+!+[]]+([][[]]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([]+[])[(![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]()[+!+[]+[!+[]+!+[]]]+([+[]]+![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[!+[]+!+[]+[+[]]])()
研究了一下,挺有意思的,只用 []()!+
这六个字符就可以实现一段可执行的 JavaScipt
代码,这是咋实现的呢?
类型转换
JavaScript
是弱类型的编程语言,我们在写代码的时候充斥着大量的类型转换,在我之前的文章 【JS进阶】你真的掌握变量和类型了吗 中有过相关的介绍:
其实上面代码的核心就是用到了下面三个类型转换:
!
后面跟的字符会被转换成布尔值+
后面跟的字符会被转换成数值+[]
前面的字符会被转换成字符串
通过上面的方法,我们可以尝试做一些简单的转换:
1 | false => ![] |
数字
怎么用这几个符号来表示数字呢?最简单的 0 :
1 | +[] === 0 |
这个很好理解,根据上面表格中的总结我们知道,空数组转换成数字是 0,我们只需要在 []
前面加上 +
让它转换成数字就可以得到 0
。
那么 1 可以怎么得到呢?
1 | +!+[] === 1 |
因为 +[]
转换成了 0
,0
是一个假值,那么 !+[]
就是一个真值,把一个真值转换成数字就会得到 1
,所以我们只需要在 !+[]
前面加上 +
就可以得到 1。
那么 2
就简单了,让两个 1
相加就可以了:
1 | !+[]+!+[] === 2 |
以此类推,3456789
都可以这样表示。
如果是一个非常大的数呢?要一直相加代码就太复杂了,我们可以用另一种方法,先转换成字符串再转换成数字:
1 | [+!+[]] === [1] |
这样,任意一个大数都可以表示了 …
字母
字母怎么得到呢?
首先我们尝试得到一个 undefined
:
1 | [][0] === undefined //获取一个空数组的第0个元素 |
下面我们利用一下第三条法则: +[]前面的字符会被转换成字符串
1 | [][+[]] +[] === 'undefined' |
这样我们就得到了 'undefined'
这样一个字符串,也就是可以拿到 u n d e f i
这其中任意一个字符,比如我们要拿到字符 u
:
1 | "undefined" [ 0] === "u" |
怎么拿到字符 a
呢,同理,我们可以从 false
里面获取:
1 | "false"[1] === 'a' |
方法
首先,我们把字符拼接起来可以得到一个方法名:
1 | // 拿到想要的字母 |
然后我们通过 []
调用方法:
1 | []["f"+"i"+"n"+"d"] |
调用一个空数组的 find
方法有啥用呢?
没啥用 … 我们尝试把这个方法再转换成字符串:
1 | []["find"] +[] === "function find() { [native code] }" |
太妙了,我们又有很多新的字符(a c d e f i n o t u v
)可以用了 …
根据已有的字符,我们可以拼接成一个 constructor
字符串,也就是构造方法,当我们尝试对一些原始值读取它的 constructor
时,就可以拿到它的构造器了:
1 | 0 ["constructor"] // Number |
然后我们把构造器再转换成字符串:
1 | 0["constructor"]+[] // "function Number() { ... }" |
我们又有了更多的新字符:m b S g B A F
…
用这样的方法,我们可以先把一些关键字或表达式转换成字符串,再去获取其中的字母,就可以表示所有的字母了…
特殊字符
字符串的 fontcolor()
方法可以用于按照指定的颜色来显示字符串,实际上它就是包了一个 HTML Font
标签:
我们通过一个空字符串去访问 fontcolor
方法,就得到了下面的字符串:
1 | ""["fontcolor"]() // "<font color="undefined"></font>" |
这样,这些特殊字符 < > = " /
就可以用了 …
怎么执行任意代码?
通过前面的方法,我们基本可以表示任意字符串了,怎么怎么可以把任意字符串表示成任意可执行的代码呢?
答案是 Function
构造函数,我们可以通过 Function
构造函数来创建一个新的 Function
对象,也就是一个新的函数:
然后我们在后面加上 ()
就可以执行这个函数:
1 | Function("alert(1)")() |
那么怎么获取到 Function
构造函数呢?
在前面的章节我们提到,通过 []["find"]
可以拿到数组的 find
方法,那么 find
方法的构造函数其实就是 Function
了,所以:
1 | []["find"]["constructor"] === Function |
我们可以像这样执行一个字符串代码:
1 | const str = "alert(1)"; |
尝试一下
下面我们来尝试把上面的代码全部通过 []()!+
表示:
f:
(![]+[])[+[]]
find:
(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+([][[]]+[])[!+[]+!+[]]
constructor:
([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]
alert:
(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]
[]["find"]["constructor"]("alert(1)")()
:
[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]]+[])[+!+[]+[!+[]+!+[]+!+[]]]+[+!+[]]+([+[]]+![]+[][(![]+[])[+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[+!+[]]+(!![]+[])[+[]]])[!+[]+!+[]+[+[]]])()
通过这个网站可以在线转换任意代码:http://www.jsfuck.com/
好了,去装逼吧 …
如果你想加入高质量前端交流群,或者你有任何其他事情想和我交流也可以添加我的个人微信 ConardLi 。