一开始我也有疑问,为何 ++[[]][+[]]+[+[]]='10' ?javascript
不得不信,因而咱们要慢慢的分析:java
[]有两个做用:git
1. 数组github
2. 访问属性和方法web
例子:ajax
[1,2,3,4] // 数组 "abc"[0] // 属性 [1,2]["length"] // 方法
1. 建立数字
2. 将两个值相加
3. 链接字符串
4. 建立字符串后端
operand + operand = result数组
1. 若是操做符数中有一个对象,它将转换为原始值(string
、number
或boolean
)浏览器
2. 若是操做符数中有一个字符串,第二个操做数将转换成字符串,而且链接在一块儿转换成一个字符串安全
3. 在其它状况之下,两个操做数转换为数字而且将执行加法运算
其中,对象转换的规则:
1. 若是对象类型是一个Date
,可使用toString()
方法
2. 在其它状况下使用valueOf()
方法,它将返回一个原始值
3. 若是valueOf()
方法不能将它返回一个原始值,可使用toString()
方法。而这种状况大部分状况下都会发生
例子:
// 数字和字符串 var result = 1 + "5"; // "15" // 数字和数组 var result = [1,3,5] + 1; // "1,3,51" // 数字和布尔值 var result = 10 + true; // 11 // 数字和对象 var result = 15 + {}; // "15[object Object]" // 数字和null var result = 8 + null; // 8 // 字符串和null var result = "queen" + null; // "queennull" // 数字和undefined var result = 12 + undefined; // NaN
下面这张图是两个变量相加的类型结果:
一元正号运算符(unary plus operator)位于其操做数前面,计算其操做数的数值,若是操做数不是一个数值,会尝试将其转换成一个数值。它能够将字符串转换成整数和浮点数形式,也能够转换非字符串值 true
,false
和
null
。小数和十六进制格式字符串也能够转换成数值。负数形式字符串也能够转换成数值(对于十六进制不适用)。若是它不能解析一个值,则计算结果为 NaN。
例子:
+3 // 3 +"3" // 3 +true // 1 +false // 0 +null // 0 +[] // 0
递增运算符(increment operator)为其操做数增长1,返回一个数值。
首先把这个表达式拆分开来,如:
++[[]][+[]] + [+[]]
由上面的基础分析可知, +[] === 0 是彻底正确的,故咱们能够简化以下:
++[[]][0] + [0]
[[]][0] 返回内部数组 ([])。可是因为语言规范, [[]][0] === [] 是不正确的,所以咱们暂时用A来代替里面的数组。
++[[]][0] == A + 1, 由于 ++ 的意思是”+1”。
++[[]][0] === +(A + 1);这是一个数值,由于递增(++)返回的永远都是一个数值
所以,表达式能够简化以下:
+([] + 1) + [0]
由上面的基础符号分析能够简化表达式以下:
1 // 参考+在操做数前面 + "0" // 参考两个变量相加的对象转换规则
故最终结果为'10'。
上面只是一个简单的例子,其实用这些字符串是能够写出真正有用的代码的,例如:
(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]] // alert(1)
能够在今生成想要的代码:http://www.jsfuck.com/
看着一些字符串能够执行,想必你们都有疑虑,用在哪些地方呢?
因为这样的代码属于混淆代码,不容易被识别,咱们能够用在帐户的安全校验上,好比,能够在Web端帐户登录以前从后端拿到一段这样的可执行代码,将执行结果写入cookie、token或者ajax请求里,这样能够防止一部分黑产用工具刷接口来获取数据。
因为黑产如今采用的工具都是易语言写的。基于winhttp.dll和winInet.dll的,不具有js引擎,因此若是web端在提交登录以前获取并执行后端的一段这样的代码,一来能够以混淆的代码使得黑产不容易看懂,二来若是黑产想破解的话,就须要一个js引擎或者无头浏览器,其成本是很高的。
用于安全上只是其中的一个例子,聪明的你可能还有更好的使用场景,不妨分享出来。
Addition (+):https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators
jsFuck: https://github.com/aemkei/jsfuck
JavaScript addition operator in details: https://rainsoft.io/javascriptss-addition-operator-demystified/
Why does ++[[]][+[]]+[+[]] return the string “10”?:https://stackoverflow.com/questions/7202157/why-does-return-the-string-10