JSFuck

JSFuck（或为了避讳脏话Fuck写作 JSF*ck ）是一种深奥的 JavaScript 编程风格。以这种风格写成的代码中仅使用 [、]、(、)、! 和 + 六种字符。此编程风格的名字衍生自仅使用较少符号写代码的Brainfuck语言。与其他深奥的编程语言不同，以JSFuck风格写出的代码不需要另外的编译器或解释器来执行，无论浏览器或JavaScript引擎中的原生 JavaScript 解释器皆可直接运行。鉴于 JavaScript 是弱类型语言，编写者可以用数量有限的字符重写 JavaScript 中的所有功能，且可以用这种方式执行任何类型的表达式。

 缘起 
长谷川阳介（Yosuke Hasegawa）于2009年7月创建了一个名为“jjencode”的网络应用程序，可将一切的JavaScript代码混淆为[]()!+,\"$.:;_{}~=这十八个字符的排列组合。

2010年1月，在一个Web应用程序安全站点上的“混淆”版块内，举行了一场非正式的竞赛。这场竞赛的目标是让JavaScript编程将所需的最少字符降至八个以下（[]()!+,/），而该帖文的回复者们设法消除了对,和/字符的需求。截至2010年3月，网上有一个名为“JS-NoAlnum”的在线编码器，它只使用六个字符来混淆JavaScript。

2010年底，长谷川阳介制作了一个名为JSF*ck的新编码器，它只使用了六个字符来混淆JavaScript。2012年，马丁·克莱普在GitHub上创建了一个编码器项目“jsfuck”，并创建了JSFuck.com网站，放置了一个使用该编码器实现的Web应用程序。

 用途与安全性 
JSFuck可用于代码混淆，一个优化版JSFuck编码器已经被用于混淆jQuery代码，使这一流行的JavaScript函数库可以仅使用六个字符来实现原本的所有功能。

此外，JSFuck可用于绕过恶意代码检测，且可以被用于跨站脚本攻击。因为缺乏原生JavaScript应有的特征，类似JSFuck的JavaScript混淆技术可帮助恶意代码绕过入侵防御系统或内容过滤器。现实中，因为JSFuck中缺少字母数字字符，且eBay中的内容过滤器曾存在缺陷，使得卖家曾经可以在他们的eBay拍卖页面中嵌入任意JSFuck脚本。

 编码方式
JSFuck代码非常冗长。在JavaScript中，alert("Hello World");这一代码将导致弹窗并显示“Hello World”字符串，这一代码的长度为21个字符。在使用JSFuck.com提供的JSFuck混淆程序后，转换出对应的相同效果代码长度为24691个字符。本节概述此转换方式的工作原理。

 数字 
数字0使用+[]来构造，其中[]代表空数组，而+是一元加运算符。
数字1则以+!![]或+!+[]来构造，其中!![]或!+[]代表布尔值为真（true），而前置的一元加运算符将真值转换为数字1。
数字2至9则以将“真”加和多次后转换为数值的类似方式来构造。例如，由true + true这一表达式在JavaScript中输出结果为2，又true可写作!![]或!+[]，故2可转写作!![]+!![]或!+[]+!+[]。
多位的整数则可将各数位分别表示，并使用串接运算符+进行字符串串接。例如字符串"10"可表达为两个数组串接的形式（[1] + [0]），将各数位替换为对应的JSFuck表达式后，即可将这一字符串表达为[+!+[]]+[+[]]；若要将字符串转化为数字，可将前述的表达式括在括号或方括号中，并加上一个+运算符，因此，数字值10可在JSFuck中表达为+([+!+[]]+[+[]])。

 字母 
通过使用索引器（即方括号中的数字）的方式，可以访问简单布尔值或数值对应字符串表示形式（如false、true、NaN、undefined）中的单个字符，而JSFuck可以借此转换一部分字母。此外，转换另一部分字母需要其他技巧，例如将字符串1e1000转换为数字，这样就会产生无穷大值（Infinity），而Infinity中的字符可以用于获取字母y。

 值  经JSFuck转化后 false  ![] true  !![]或!+[] NaN  +[![]]或+[] undefined  [] Infinity  +(+!+[]+(!+[]+[])[!+[]+!+[]+!+[]]+[+!+[]]+[+[]]+[+[]]+[+[]])

 其他构造方法 
在JavaScript中，Function函数这种构造器可被用于触发执行包含在字符串中的JavaScript代码，正如像执行原生JavaScript代码那样。例如，语句alert(1)等价于Function("alert(1)")()。而Function构造器在JavaScript中是任何常用函数的constructor属性，此处所言的常见函数指的是像[]["filter"]（即Array.prototype.filter）之类的函数。于是，这个构造器便可以通过访问一个空数组的filter属性下的constructor属性来构造。例如，alert(1)可被等价转换为[]["filter"]["constructor"]("alert(1)")()，并使用JSFuck进一步转换。

 备注 

对于“编码方式”章节中的内容：

 参考来源 

 外部链接 
 JSFuck - Write any JavaScript with 6 Characters: []()!+ – 将原生JavaScript转换为JSFuck的Web应用程序
 Yosuke Hasegawa创作的JSF*ck在线应用
 JSfuck.com所用的转换脚本 

Category:深奥的编程语言
Category:JavaScript