标签 Function 下的文章

好多小伙伴都看到过这样一段全是由各种括号,以及有限的几个操作符组成的代码,完整代码贴在下面。为了好看,我给它格式化了一下:

[]
[
    (![] + [])[+[]] + 
    ([![]] + [][[]])[+!+[] + [+[]]] +
    (![] + [])[!+[] + !+[]] +
    (!![] + [])[+[]] +
    (!![] + [])[!+[] + !+[] + !+[]] +
    (!![] + [])[+!+[]]
]
[
    (
        [][
        (![] + [])[+[]] +
        ([![]] + [][[]])[+!+[] + [+[]]] +
        (![] + [])[!+[] + !+[]] +
        (!![] + [])[+[]] +
        (!![] + [])[!+[] + !+[] + !+[]] +
        (!![] + [])[+!+[]]] + []
    )[!+[] + !+[] + !+[]] +
    (
        !![] +
        [][(![] + [])[+[]] +
        ([![]] + [][[]])[+!+[] + [+[]]] +
        (![] + [])[!+[] + !+[]] +
        (!![] + [])[+[]] +
        (!![] + [])[!+[] + !+[] + !+[]] +
        (!![] + [])[+!+[]]]
    )[+!+[] + [+[]]] +
    ([][[]] + [])[+!+[]] +
    (![] + [])[!+[] + !+[] + !+[]] +
    (!![] + [])[+[]] +
    (!![] + [])[+!+[]] +
    ([][[]] + [])[+[]] +
    (
        [][(![] + [])[+[]] +
        ([![]] + [][[]])[+!+[] + [+[]]] +
        (![] + [])[!+[] + !+[]] +
        (!![] + [])[+[]] +
        (!![] + [])[!+[] + !+[] + !+[]] +
        (!![] + [])[+!+[]]] + []
    )[!+[] + !+[] + !+[]] +
    (!![] + [])[+[]] +
    (
        !![] +
        [][(![] + [])[+[]] +
        ([![]] + [][[]])[+!+[] +
        [+[]]] +
        (![] + [])[!+[] + !+[]] +
        (!![] + [])[+[]] + (!![] + [])[!+[] + !+[] + !+[]] +
        (!![] + [])[+!+[]]]
    )[+!+[] + [+[]]] +
    (!![] + [])[+!+[]]
]
(
    (![] + [])[+!+[]] +
    (![] + [])[!+[] + !+[]] +
    (!![] + [])[!+[] + !+[] + !+[]] +
    (!![] + [])[+!+[]] +
    (!![] + [])[+[]] +
    (
        ![] +
        [][
        (![] + [])[+[]] +
        ([![]] + [][[]])[+!+[] + [+[]]] +
        (![] + [])[!+[] + !+[]] +
        (!![] + [])[+[]] +
        (!![] + [])[!+[] + !+[] + !+[]] +
        (!![] + [])[+!+[]]
        ]
    )[!+[] + !+[] + [+[]]] +
    [+!+[]] +
    (
        !![] +
        [][(![] + [])[+[]] +
        ([![]] + [][[]])[+!+[] + [+[]]] +
        (![] + [])[!+[] + !+[]] +
        (!![] + [])[+[]] +
        (!![] + [])[!+[] + !+[] + !+[]] +
        (!![] + [])[+!+[]]]
    )[!+[] + !+[] + [+[]]]
)
();

这是一坨什么玩意儿?看得人脑瓜子嗡嗡的。
今天上班第一天,不想干活,只想摸鱼。趁着这个时间娱乐一下,看看这段代码到底是什么东西。

从上面的代码中可以看出来,我已经把它的主要结构展示地非常清晰:

//① ②    ③    ④   ⑤
 [][...][...](...)();

非常明显,第一个[]肯定是提供了一个存在于它的原型链上的 方法 或者 属性 供第二个[]使用。既然是用方括号调用方法或者属性,那么第二个[]里面必定是一个字符串,就像这样:

[]['map'];
//等价于
Array.prototype.map;

当然,第二个[]内的字符串不一定是map,我只是用map举个栗子,具体内容还要进一步分析。

以此类推,第三个[]类似第二个[],举例来说就是这样:

[]['map']['name'] //'map'

上面那行示例代码获取到了函数Array.prototype.mapname属性,但本文讨论的代码究竟获取到了什么东西,还是留待进一步分析。

咱们继续往下看。第四部分是一个小括号()。小括号除了分块外,最大的作用是调用函数。综合上文的分析,第三部分应该是返回一个方法,而第四部分的这个小括号就是调用第三部分返回的方法,小括号里面的内容呢,那肯定就是参数了。

至于第五部分也就是最后一个小括号,很明显是调用方法。既然这样,那么前四部分整体返回的就是一个方法,也就是说,第四部分执行了一个返回方法的方法。

什么方法会返回一个方法呢?继续深入分析。

第一部分[]是一个空的数组实例,除了继承了Array的一些属性和方法,其他没什么可分析的。

第二部分是由5个+操作符连接的语句。下面以第二部分的第一行为例进行分析。
第一行是(![] + [])[+[]],又可以分解成(![] + [])[+[]],其中涉及到的知识就是隐式转换。其中:

![]
//等价于
!''

结果是false,于是

(![] + [])
//等价于
(false + [])
//等价于
(false + '')
//等价于
('false' + '')
//等于
'false'

隐式转换的具体规则网上已经有很多文章了,这里就不重复了。

[+[]]
//等价于
[+'']
//等价于
[0]

所以,第一行最后的结果是

'false'[0]
//等于
'f'

搞了半天,原来是为了获取'f'这个字符。

实际上,分析完上面这行代码,其他的就不言自明了,套路都是一样的,第二部分和第三部分的目的,是为了拼凑'filter''constructor'这两个字符串。

经过分析,整个代码相当于:

[]['filter']['constructor']('alert(1)')();

等于

[].filter.constructor('alert(1)')()

那么为啥拼凑'filter'这个字符串,而不是拼凑'map''sort'……呢?这里必须要好好说道说道,这是因为,'filter'这个字符串,它容易得到……

[].filter.constructor指向的是构造函数Function,利用它,可以使用字符串构造函数,类似于eval(),所以[].filter.constructor('alert(1)')相当于

Function('alert(1)')

执行Function('alert(1)'),就会弹出 1 了:

Function('alert(1)')()

好了,本文到此结束了。


End