六个字符替换你的JavaScript代码
原文地址 http://jazcash.com/a-javascript-journey-with-only-six-characters
JavaScript可以让我们天马行空的coding却仍然奏效,他让我们如愿以偿的转化数据成我们想要的类型。
如果我们给字符转加上点什么东西,js会觉得我们想要的就是文本形式,所以他依旧会呈现给我们一个字符串。
如果我们加上的是 + 或者 - 前缀,js会认为我们需要他以数值的形式表示,如果可以得话,js就会将其转化为数值。
如果我们加上的是 ! 符号,js会将其转化为布尔值。
我们可以利用js提供的这些特征,仅仅用以下六个字符去做一些神奇的事情:
[, ], (, ) ,+和 !。
如果你现在使用pc端浏览器浏览这篇文章的话,你可以使用控制台验证文章后面出现的代码。
不以规矩,不成方圆 ,让我们记住一些基本规则:
1、前缀加 ! 转化为布尔值(Boolean);
2、前缀加 + 转化为数值(Number);
3、加 [ ] 转化为字符串(String)。
举个栗子:
![] === false
+[] === 0
[]+[] === ""
另一个我们需要知道的准则就是,字符转检索字母的时候可以使用中括号 :
"hello"[0] === "h"
我们也可以通过多个字符串连加,再通过转化为数值类型的方式,来组合多位数,看起来就像:
+("1" + "1") === 11
OK,那让我尝试获取到一个字符 a :
![] === false
![]+[] === "false"
+!![] === 1
------------------------
(![]+[])[+!![]] === "a" // 就像是‘ false ’[1]
完美!!!
到目前为止,我们可以通过以上组合获取到true和false两个单词,也就可以获得 a,e,f,l,r,s,t,u 这些字母,那我们如何获取其他字母呢?
我们知道,常用基本类型有一个undefined,我们可以这样拿到这个值:
[][[]] + [] === "undefined"
这样我们可以或得到额外的几个字母 d,i,n。
用我们现在所获得到的字母,我们可以拼写出fill,filter和find。之所以要提到这几个单词是因为他们都是原生数组的一些方法,我们可以用数组实例直接调用他们,就像:
[2,1].sort()
好,另一个需要我们知道的就是获取js对象的属性,我们可以使用中括号,也可以使用点运算符。数组也是对象,所以我们可以使用中括号或者点运算符来调用数组的方法。
所以[2,1]["sort"]()和 [2,1].sort()效果是一样的。
现在让我们看看当我们用以上我们可以使用的字母去拿到一个方法,但却不调用它时是什么样子的:
[]["fill"] --> function fill() { [native code] }
我们可以使用我们之前的基本规则将其转化为字符串:
[]["fill"]+[] === "function fill() { [native code] }"
so 现在我们的字母家族又多了几位新成员:c,o,v,(,),{,},[,], 。(注意:最后是有一个空格字符的呦)
使用我们刚刚拿到的 c 和 o 我们可以组成一个新的单词 constructor, constructor是一个每个js对象都有的方法,这个方法可以返回构造函数。
让我们看一看目前我们能拿到的对象的构造函数的字符串表示是什么样子的:
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到底有什么用?
简单地说,就是多进制转换,我们可以为toString方法传递相应的参数,来进行数值的进制转换。
(12)["toString"](10) === "12" // 10进制
(12)["toString"](2) === "1100" // 2进制
(12)["toString"](8) === "14" // 8进制
(12)["toString"](16) === "c" //16进制
为什么参数就到16?实际上传递参数的最大值是36!可以拿到字母,0-9和a-z。
(10)["toString"](36) === "a"
(35)["toString"](36) === "z"
Awesome! 但是我们如何拿到一些其他字符呢,比如 标点符号、大写字母什么 的?
当我们在执行js的时候,我们有可能访问特定的预定义对象和数据,在浏览器中,我们有机会访问一些旧的HTML包装方法。
例如,bold就是一个可以给一个字符串加上<b>标签的方法:
"test"["bold"]() === "<b>test</b>"
这样,我们拿到了<,>和 /。
我们还知道转义方法(escape function),他可以将字符转转移成一个URI友好格式,这样浏览器可以解析这个被转义的字符串。这个功能是我们需求的一个重要部分,我们需要执行它,我们现在也能拼出这个方法,但是我们怎样才能调用它呢?它不属于目前能拿到的任何类型的方法,它是一个全局函数啊。
任意一个函数的构造函数是什么?
答案是 function Function() { [native code] },是这个函数本身。
[]["fill"]["constructor"] === Function
利用这个,我们可以自己组合出一个可以执行的函数。
Function("alert('test')");
得出:
Function anonymous() { alert('test') }
我们只需要在代码末尾加上(),构造出一个立即执行的匿名函数,这样代码就可以顺利执行了,整体看起来像是下面这个样子:
[]["fill"]["constructor"]("return escape(' ')")() === "%20"
我们可以转义 < 来获得%3C,这个大写字母C对于我们要获得目前缺少的字符是非常重要的。
[]["fill"]["constructor"]("return escape('<')")()[2] === "C"
通过这个C,我们现在可以拼写出fromCharCode方法,这个方法会从一个给定的十进制数返回一个 Unicode 字符,它属于字符串对象,我们可以像之前一样调用它:
""["constructor"]["fromCharCode"](65) === "A"
""["constructor"]["fromCharCode"](46) === "."
我们可以很轻松查找到任何字符的十进制数值。
嚯,查不到该结束了。
我们现在可以得到任意的字符,我们只需要串联他们成代码,并且执行他们,也就是说我们可以将我们的js代码仅仅用[,],(,),+,!六个字符编写出来。
你可以在控制台粘贴复制如下代码尝试查看结果:
[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]])()
这回在页面弹出 1 ,相当于alert(1)。
这个是已经封装好的方法,你可以在如下链接的页面中输入你要转换的代码,他会自动生成你要的六个字符的代码:http://www.jsfuck.com/
这个是方法的源码,感兴趣的小伙伴可以看看:https://raw.githubusercontent.com/aemkei/jsfuck/master/jsfuck.js
那这有什么用?
并没什么用,耽误大家的时间了。
sorry

浙公网安备 33010602011771号