JSfuck原理解析一

  本系列博客是对jsfuck代码的一些分析,暂定为四篇。第一篇为jsfuck基础原理,第二篇为字母解析,第三篇为源码解析,第四篇为手撸jsfuck翻译(好吧,这个确实恶心)

  不出意外的话就是这四篇,如果我比较懒得话,源码解析会放掉,毕竟源码也不长-。-

  如果你也有对知识的渴望,可以直接访问原作者的GitHub:https://github.com/aemkei/jsfuck 原作者其实已经解释很清楚了。不过学习嘛,自己分析才有乐趣,就跟上学那会儿答案摆在桌子上也不看一眼的学霸一样(笑)。

  (文章纯手打,转载说明出处,谢谢)

  那下面开始正文:

  什么是jsfuck

  想象一下自己第一次见到代码的样子,满屏的奇怪字符?WTF?而当我看到jsfuck的时候,再次体会到了这种感觉。请看下面的代码:

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

WTF???(黑人问号脸)

  没错!这确实是一串js代码,你可以直接放到控制台去执行,最后执行的结果是alert(1)JS就是这么一门神奇的语言。本着对知识的渴求与对未知事物的探索精神(雾),下面我们就一起来研究下jsfuck的原理。

   在讲jsfuck之前,先要说起一个js的经典面试题:[]==![]

  这道题是考验js基础的,利用的是js的一些基本原理——类型转换。类型转换大家都了解,比如简单的 ‘a’+1结果就是’a1’,在这个计算过程中1被隐式转换成string类型,这道面试题也是这个原理。Js语法中’==’两边如果不是同一类型则会进行类型转换。

  但是相信很多接触过前端的同事见到这个题目时候的第一反应,是这个表达式的结果是false,然而拿到控制台执行之后却发现是true,这让很多人十分不解。特别是当我们在控制台打印代码的时候,会出现一些令人费解的事情。如:

Boolean([])   //true

Boolean(![])  //false

  其实上述代码,我们进行了强制转换,在js中在把对象做布尔值转换的时候,会把所有对象都转换为true(包括创建的new Boolean(false)对象转换之后也是true,具体可参考犀牛书3.8.3)。而相等运算符却不是这么计算的,在相等运算符中,如果运算符两边的值有一个是布尔类型,则会把true转换成1false则转换为0。而在这道题目中![]的结果肯定是布尔值false,则会转换为0

[]==0

  这时候解释起来就简单了很多,相等运算符如果有一边是数字,而另一边是对象,则会把对象转换成数字。而空的数组对象转换成数字是0(犀牛书3.8)那么结果便是:

0==0  //true

  讲了这么多,终于可以进入正题了。之所以开篇讲这么一个题目,是为了更好理解jsfuck的原理。在官网上(直接百度jsfuck就行),我们能看到官方给出的jsfuckBasics,下面我们来逐条分析。(水平有限,如果有发现错误可以指出,大家一起研究)


false => ![]  

//非运算符会把[]的布尔值取反



true => !![]  

//再取反则是true



undefined => [][[]] 

//这一个就比较复杂,在js中数组的索引可以为负数和非整数,而在这种情况下会将索引转换成字符串,作为对象的属性访问,我们知道[]转换为字符串为空字符串,则上面等价于:[][‘’]。然而数组对象并没有名为’’的属性,在js中访问一个对象并不存在的属性时,会给出undefined 


NaN => +[![]]  

//这里利用了+运算符的特性,这里+不是加号运算符(姑且这么叫)而是一元运算符的一种,一元加法,用于把操作数转换为数字或者NaN并返回这个数字。上式等价于+[false],而根据类型转换的规则我们知道,这样得到的结果为NaN


0 => +[]  

//根据类型转换规则,[]转换为数字为0


1 => +!+[]  

//本式为上面的变式,根据运算符的优先级,先执行+[]0,再转换成布尔取反为truetrue转换为数字为1


2 => !+[]+!+[] 

 //中间一个+为加法运算符优先级比较低,等价于true+true,值为2


10 => [+!+[]]+[+[]]   

//可拆分成[+!+[]][+[]],左边为[1],右边为[0]+作为连接字符串运算符,而根据数组转换成字符串我们可以知道上面等价于‘1+0’,得到的是字符串‘10


Array => []  

//[]就是数组对象的事例,用于获取字符串’Array’(暂时没有弄清楚作者的意思,这个Array对象的获取相当复杂,利用了js对象的原型链,其代码非常之繁琐,我会在最后一篇人肉翻译jsfuck代码中详细讲述。如果有大神了解原作者在此只放一个‘[]’的原因,请告诉我,我会对博客进行更改,并附上大神的名字提名感谢)


Number => +[]  

//与上式相同,后面会详细讲解


String => []+[]  

//与上式相同,后面会详细讲解


Boolean => ![] 

 //与上式相同,后面会详细讲解


Function => []["filter"] 

 //与上式相同,后面会详细讲解


eval => []["filter"]["constructor"]( CODE )()  

//这里比较复杂,我们先来看前半部分[]["filter"]["constructor"],这一部分可以看到拿的是一个数组对象的‘filter’属性下面的‘constructor’属性,‘filter’属性是数组的一个方法,但在这里并没有用到该方法,你把它替换成别的方法也可以照常运行(例如‘map’),关键是下面这一步,filterconstructor属性,我们知道在js中任何方法都可以看做是Function对象的一个实例,而Function就作为所有函数的构造函数。这里拿到的就是函数的Function()构造函数。而Function()构造函数的最后一个参数会作为函数体执行。因此这段语句会执行‘CODE里的内容’。


window => []["filter"]["constructor"]("return this")() 

 //与上式相同,拿到的是函数的构造函数,第一个括号内便是函数体。并且Fuction()构造函数所创建的函数并不使用词法作用域(划重点!),他是直接执行在顶层函数中的,也就是全局作用域,因此this返回window


说了这么多,却还是无法解释开篇那外星语言一般的代码,但是有了这篇博客的基础,接下来就方便了很多下一篇会详细分析jf里面的一些字母与语句的由来,敬请期待


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章