现在就来仔细说说那段代码的含义(原文在此),首先给出完整代码:
(_=[_=[]][(_+!![])[$=(!!_/!!_)]+(!!$+_)[-~-~$]+'v'+(!(_/_)+[])[-~-~$]+(!([]/($))+[])[$]+([]+!_)[-~-~$]+(!!{}+[])[-~-~$]])()[(!({}+_)+_)[$]+(!({}+[])+[])[-~$]+((''+!![]+''))[-~-~$]+(!![]+'')[$]+((!!_+[]))[$-$]]($/$);
这段代码可划分为两部分:
(_=[_=[]][(_+!![])[$=(!!_/!!_)]+(!!$+_)[-~-~$]+'v'+(!(_/_)+[])[-~-~$]+(!([]/($))+[])[$]+([]+!_)[-~-~$]+(!!{}+[])[-~-~$]])()
[(!({}+_)+_)[$]+(!({}+[])+[])[-~$]+((''+!![]+''))[-~-~$]+(!![]+'')[$]+((!!_+[]))[$-$]]($/$)
基本结构是:()()[]()。第一个括号中有一个函数,接下来的括号要执行它,执行后返回一个对象,再调用对象的某个方法,这个方法是通过后面的中括号定义的,最后的括号就是执行这个方法。
先来看第一部分,把第一个括号中的内容提取出来:
_=[_=[]][(_+!![])[$=(!!_/!!_)]+(!!$+_)[-~-~$]+'v'+(!(_/_)+[])[-~-~$]+(!([]/($))+[])[$]+([]+!_)[-~-~$]+(!!{}+[])[-~-~$]]
这里,我们先定义变量 _ 为一个空数组 [],因此上面代码等价于:
_=[_=[]][([]+!![])[$=(!![]/!![])]+(!!$+[])[-~-~$]+'v'+(!([]/[])+[])[-~-~$]+(!([]/($))+[])[$]+([]+![])[-~-~$]+(!!{}+[])[-~-~$]]
其中 !![]/!![] 的结果是1,那么变量 $ 也就是 1。~$ 等于 -2,-~$ 就是 2,同理 -~-~$ 就是 3,上面代码等价于:
_=[_=[]][([]+!![])[1]+(!!1+[])[3]+'v'+(!([]/[])+[])[3]+(!([]/1)+[])[1]+([]+![])[2]+(!!{}+[])[2]]
[] + !![] 返回字符串 'true',!!1 + []返回字符串 'true',按照类似方式上面代码推出:
_=[_=[]][('true')[1]+('true')[3]+'v'+('true')[3]+('true')[1]+('false')[3]+('true')[3]]
也就是:
_=[[]]['r' + 'e' + 'v' + 'e' + 'r' + 's' + 'e']
,即:
_ = [[]].reverse
,即定义变量 _ 为一个数组的reverse方法。
接下来,我们执行了方法 _,它返回了window对象,因此整个代码就是:
window[(!({}+_)+_)[$]+(!({}+[])+[])[-~$]+((''+!![]+''))[-~-~$]+(!![]+'')[$]+((!!_+[]))[$-$]]($/$);
等价于:
window[('false')[1]+('false')[2]+('true')[3]+('true')[1]+('true')[0]](1);
等价于:
window['a' + 'l' + 'e' + 'r' + 't'](1)
,即:
window.alert(1)
,亦即:
alert(1)
。
留言