6个字符搞定一切

原文: A Javascript journey with only six characters

在这篇文章中,我们会用[,],(,),!+来做一些有趣的事情,首先需要记住以下几点:

  • !开头会转换成 Boolean 布尔值
  • +开头会转换成 Number 数值类型
  • 添加[]会转换成 String 字符串

 ![] === false +[] === 0 []+[] === "" 

另外可以通过[]获取字符串中特定的字符

 "hello"[0] === "h" 

也可以把数字串起来后再转换回数值:

 +("1" + "1") === 11 

好了, 来看看用这六个字符怎么可以得到一个字母a:

![] === false
![] + [] === "false"
// ---------------
!![] === true
+!![] === 1
// ---------------
(![] + [])[+!![]] === 'a'

用这个技巧我们可以轻易把truefalse中所有字母都取出来:a,e,f,l,r,s,t,u

还有什么其他可用的吗? undefined !

undefined 我们可以通过 [][[]] 得出来。

 [][[]] + [] === "undefined" 

这样我们可以额外得到d,in

([][[]] + [])[+!![]] === 'n'
([][[]] + [])[+!![]+!![]] === 'd'

利用目前我们得到的这些字母,我们可以拼出fill,filterfind. 当然还可以拼出其他单词,但这三个单词都是数组的方法!

还有一件事我们需要知道的是,对象的属性我们都可以通过[]获取到。[2,1]["fill"]()[2,1].fill()是一样的!

[]["fill"]

返回function fill() { [native code] }, 利用添加[]会转换成String的规则我们得到:

[]["fill"]+[] === "function fill() { [native code] }"

这样一来我们又获得了: c,o,v,(,),{,[,],},

进而我们可以得到constructor.

利用 constructor 函数可以返回对象的构造方法:

true["constructor"] + [] === "function Boolean() { [native code] }"
0["constructor"] + []    === "function Number() { [native code] }"
""["constructor"] + []   === "function String() { [native code] }"
[]["constructor"] + []   === "function Array() { [native code] }"

B,N,S,A,m,g,y 又收入囊中.

现在我们可以得到 toString 了:

(10)["toString"] () === "10"

嗯,虽然我们现在可以把任何东西都转换成字符串了,但是有个什么鸟用呢?

你有所不知的是,toString 有一个神秘的raidx 参数,可以指定用于数字到字符串的转换的基数。

(12)["toString"](10) === "12" // base 10 - normal to us
(12)["toString"](2) === "1100" // base 2, or binary, for 12
(12)["toString"](8) === "14" // base 8 (octonary) for 12
(12)["toString"](16) === "c" // hex for 12

利用这个方法,我们可以得到所有字符了. 0-9, a-z:

(10)["toString"](36) === "a"
(35)["toString"](36) === "z"

利用一些过期的现在已不推荐使用的(HTML wrapper methods)[https://developer.mozilla.org/en-US/docs/tag/HTML%20wrapper%20methods]我们可以得到另外一些标点符号:

"test""bold" === "<b>test</b>"

上面得到了<,>/.

现在我们还差大写字母.

或许你听说过escape函数。escape() 函数可对字符串进行编码,这样就可以在所有的计算机上读取该字符串。escape函数是我们成败的至关重要的一环!

现在我们可以拼写出escape但是我们怎么样可以执行呢, escape可是属于全局对象的!

问题来了,任何函数的构造函数是什么呢?

答案是:function Function() { [native code] }, Function 对象本身。

[]["fill"]["constructor"] === Function

利用Function对象,我们可以把字符串作为参数然后去创建一个函数:

Function("alert('test')")

我们只需要在最后添加()就可以执行 alert 了,所以我们可以这样使用escape函数:

[]["fill"]["constructor"]("return escape(' ')")() === "%20"

如果我们把<穿入escape会返回%3C. C对于我们得到剩下的字母灰常重要:

[]["fill"]["constructor"]("return escape('<')")()[2] === "C"

用了C, 我们就可以用 fromCharCode 函数了!fromCharCode() 可接受一个指定的 Unicode 值,然后返回一个字符串。fromCharCodeString 对象的方法,因此可以这样调用:

""["constructor"]["fromCharCode"](65) === "A"
""["constructor"]["fromCharCode"](46) === "."

至此为止,利用(Unicode对照表)[http://unicodelookup.com]我们可以得到任何字符了!

终于搞定!

我们现在可以得到任何一个字符,把它们连接起来并且执行了!

嗯,搞这么多,其实然并卵。

最后这里有个自动转换器: JSFuck

« 返回