JSfuck原理解析一

原创 2018年04月15日 01:09:07

  本系列博客是对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里面的一些字母与语句的由来,敬请期待


CTF中那些脑洞大开的编码和加密

0x00 前言 正文开始之前先闲扯几句吧,玩CTF的小伙伴也许会遇到类似这样的问题:表哥,你知道这是什么加密吗?其实CTF中脑洞密码题(非现代加密方式)一般都是各种古典密码的变形,一般出题者...
  • fox_wayen
  • fox_wayen
  • 2017-10-14 16:41:44
  • 1599

解释jsfuck的一篇blog

终于找到了jsfuck的解释了,链接地址如下: http://lz12366.iteye.com/blog/961062
  • u012684933
  • u012684933
  • 2014-06-05 14:38:46
  • 2288

jsfuck编码---idf实验室“一种编码而已”笔记

[][(![]+[])[!![]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!![]+!![]+!![]+!...
  • Mr0Yang
  • Mr0Yang
  • 2016-06-08 16:03:51
  • 921

maven内部运行原理解析(二)

default-jar package jar ...
  • u013400939
  • u013400939
  • 2017-05-27 10:26:59
  • 247

FUCK电信

大概是前两天吧,电信又在加密,我在寝室拨了半天的号都没连上,还以为是路由器坏了。直到所有同学都在骂电信的时候,我TMD才反应过来。对于电信真心无语,垄断你做的好才行,这么垃圾还搞这些小动作赚钱,真TN...
  • lj1043041006
  • lj1043041006
  • 2013-04-13 09:45:52
  • 511

各种解码网站

xssee:http://web2hack.org/xssee xssee:http://evilcos.me/lab/xssee 程默的博客(DES,3DES,AES,RC,Blowfi...
  • xiaoi123
  • xiaoi123
  • 2018-01-16 17:22:54
  • 120

week2_day1_JS

JavaScript基本语法1.数据类型 JavaScript中有五种简单数据类型,也称为基本数据类型,分别是undefined(不明确的)、null(空)、boolean(布尔)、number(整...
  • Fuck_the_Oracle
  • Fuck_the_Oracle
  • 2016-11-14 22:04:52
  • 202

关于一些fuck

JS Fuck:[]()!+ 是指用6 个字符 []()!+ 来编写 的JavaScript 程序 在线转换js程序为js fuck:http://www.jsfuck.com/ 在线转换js fu...
  • galaxy96
  • galaxy96
  • 2016-12-19 23:25:39
  • 468

idf实验室 天罗地网 一种编码而已 学习笔记

[][(![]+[])[!![]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!![]+!![]+!![]+!...
  • xiaohajunsky
  • xiaohajunsky
  • 2016-04-07 22:46:10
  • 465

2016华山杯 writeup

web 1、签到 微信回复得到flag2、打不过~ http://huashan.xdsec.cn/ctf_hs_00b.php发现submit被禁止了,更改为允许,添加action,type=...
  • qq_28295425
  • qq_28295425
  • 2016-09-10 18:40:05
  • 960
收藏助手
不良信息举报
您举报文章:JSfuck原理解析一
举报原因:
原因补充:

(最多只允许输入30个字)