Write any JavaScript with 6 Characters: []()!+
demo : jsfuck.com
fork from : https://github.com/aemkei/jsfuck.git

Martin Kleppe 6c8e1beacd Merge pull request #57 from hazzik/patch-1 9 年之前
test d5d4057c71 Update lengths 11 年之前
.gitignore efc8b2339e Add tests 11 年之前
.npmignore efc8b2339e Add tests 11 年之前
Gruntfile.js efc8b2339e Add tests 11 年之前
LICENSE.txt 570ecd3b1b Add license file. 13 年之前
README.md 856cfd6b11 Make ">" alternative consistent 9 年之前
favicon.ico 611c29efa5 Add preview and favicon. 13 年之前
fuck.js 6069cfff72 add repl to executable 11 年之前
index.html b2dae714ba Allow running generated code in parent scope 10 年之前
jsfuck.js 26daabc3e0 merge master 9 年之前
output.txt 26daabc3e0 merge master 9 年之前
package.json 53388a2d80 Grunt related stuff 9 年之前
preview.png 611c29efa5 Add preview and favicon. 13 年之前

README.md

JSFuck []()!+

JSFuck is an esoteric and educational programming style based on the atomic parts of JavaScript. It uses only six different characters to write and execute code.

It does not depend on a browser, so you can even run it on Node.js.

Demo: jsfuck.com

By @aemkei and friends.

Example

The following source will do an alert(1):

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

Basics

false       =>  ![]
true        =>  !![]
undefined   =>  [][[]]
NaN         =>  +[![]]
0           =>  +[]
1           =>  +!+[]
2           =>  !+[]+!+[]
10          =>  [+!+[]]+[+[]]
Array       =>  []
Number      =>  +[]
String      =>  []+[]
Boolean     =>  ![]
Function    =>  []["filter"]
run         =>  []["filter"]["constructor"]( CODE )()
eval        =>  []["filter"]["constructor"]("return eval")()( CODE )
window      =>  []["filter"]["constructor"]("return this")()

See the full list here.

Links

JSFuck - How it Works

This wiki should document the different approaches to run any JavaScript with the smallest subset of characters.

Note: Feel free to join the discussion here: https://gitter.im/aemkei/jsfuck

[] – Brackets

Let's start with the opening and closing brackets and see what is possible here. They are super useful for this project and it are considered as a core element because they provide a way to 1. deal with arrays and 2. access properties and methods.

[] – Array Literals

Create new arrays:

[] // an empty array
[[]] // an array with one element (another array) 

[X][i] – Array / Object Access

[][[]]   // undefined, same as [][""]

Later we will be able to do this:

"abc"[0]     // get single letter
[]["length"] // get property
[]["fill"]   // get methods

[X][0] - Array wrapping trick

By wrapping an expression in an array then getting the element at index zero, you can apply several operators on one expression. This means brackets [] can replace parenthesis () to isolate expressions:

[X][0] === X
++[ ++[ ++[X][0] ][0] ][0] === X + 3

+ – Plus Sign

This symbol is useful two, because it allows us to create number, add two values, concatenating strings and (combined with '[]') create strings.

The current version of JSFuck uses it a lot but we not sure if they are fundamental.

Cast to Number

+[] // 0 - the number 0

Increment Numbers

using the Array wrapping trick

++[ 0  ][  0  ] // 1
++[ [] ][ +[] ] // 1

Getting undefined

Getting an element by index in an empty array will return undefined:

undefined === [][0]
undefined === [][ +[] ]
undefined === [][ [] ] // will look for property _empty string_ in the array

Getting NaN

Casting undefined to Number will result in not-a-number:

+[][[]]    // +undefined = NaN

Add Numbers

          1 +           1 // 2
++[[]][+[]] + ++[[]][+[]] // 2

A shorter way using ++:

++[          1][  0] // 2
++[++[[]][+[]]][+[]] // 2

Using this technique, we are able to access all digits:

0, 1, 2, 3, 4, 5, 6, 7, 8, 9

+[] – Casting to String

Combining the brackets and the plus sign, allows us to turn other values into strings.

Casts to String:

[]          +[] // "" - empty string
+[]         +[] // "0"
[][[]]      +[] // "undefined"
++[][[]]    +[] // "NaN
++[[]][+[]] +[] // "1"

"word"[i] – Get Single Characters

As we have strings, we can get single characters:

 "undefined"      [  0] // "u"
["undefined"][  0][  0] // "u"
[[][+[]]+[] ][+[]][+[]] // "u"
[[][+[]]+[]][+[]][           1 ] // n
[[][+[]]+[]][+[]][ ++[[]][+[]] ] // n

Since we have "NaN" and "undefined", we got the following characters:

N,a,d,e,f,i,n,u.

+ – Combine Characters

Now we can concat characters to new words.

// can be written using []+ only:
"undefined"[4] // "f"
"undefined"[5] // "i"
"undefined"[6] // "n"
"undefined"[3] // "d"

// combine using +
"f"+"i"+"n"+"d" // "find"

"e" – Numbers in exponential notation

As we have the character "e" from "undefined", we can use exponential notation to construct very big numbers and get a reference to Infinity:

+("1e309")         //  Infinity
+("1e309") +[]     // "Infinity"
+("11e100")        //  1.1+e101
+("11e100") +[]    // "1.1+e101"   (gives us `.`)
+("0.0000001")     //  1e-7
+("0.0000001") +[] // "1e-7"       (gives us `-`)

Resulting chars:

I,f,i,n,t,y,.,+,-.

[]["method"] – Access Methods

Newly combinded characters can form method names. These can be accessed using the square brackets notation:

[]["f"+"i"+"n"+"d"] // where "f" is the first char of "false" and so on
[]["find"]          // same as the dot syntax:
[] .find

Note: With the characters from "undefined", "NaN" and "Infinity", the only method we are able to find in the objects we have is Array.prototype.find.

method+[] – Get Method Definitions

We can cast a method to a String and get its definition as a String:

[]["find"] +[]

This will return the following String:

"function find() { [native code] }"

Note: String representations of native functions are not part of the ECMAScript standard and slightly differ between browsers. For example, Firefox will output a slightly different string with additional line breaks using \n.

Resulting characters:

  • a,c,d,e,f,i,n,o,t,u,v
  • , {, }, (, ), [,]

Resulting methods:

  • .concat
  • .find.

! – Logical NOT operator

This is the fourth character in the original JSFuck set and used to create booleans.

!X – Cast to Boolean

The logical "Not" operator can be used to create booelans false and true:

![]  // false
!![] // true

!X+[] – Get "true" and "false"

Booleans can be casted to string:

![]  +[] // "false"
!![] +[] // "true"

This will give us access to more characters:

a, e, f, l, r, s, t, u.

And together with the set above, we will have {}()[]+. INacdefilnorstuvy with access to these methods:

  • call
  • concat
  • constructor
  • entries
  • every
  • fill
  • filter
  • find
  • fontcolor
  • includes
  • italics
  • reduce
  • reverse
  • slice
  • sort

Important: We should better take one of the symbols =, > or < to create booleans, because they are more powerful (see section "Alternatives" below).

X["constructor"] – Primitive wrappers names

With .constructor we have a reference to the function that created the instance. For primitives values, it returns the corresponding built-in wrappers:

0       ["constructor"] // Number
""      ["constructor"] // String
[]      ["constructor"] // Array
false   ["constructor"] // Boolean
[].find ["constructor"] // Function

Use +[] to convert them to strings and retrieve their function name in order to get more chars:

0["constructor"]+[] === "function Number() { ..." // gives chars m and b

New chars available : m, b, S, g, B, A, F.

… and more methods and properties:

  • arguments
  • big
  • bind
  • bold
  • name
  • small
  • some
  • sub
  • substr
  • substring
  • toString
  • trim

() – Parenthesis

Calling Methods

Since we have access to methods, we can call them to get more power. To do this we need to introduce two more symbols ( and ) here.

Example without arguments:

""["fontcolor"]()   // "<font color="undefined"></font>"
[]["entries"]() +[] // "[object Array Iterator]"

New characters:

j, <, >, =, ", /

number.toString(x) – Getting any lowercase letter

Number's toString method has an optional argument specifying the base to use, between 2 and 36. With base 36, the output is displayed with every number and lowercase letter, so we can retrieve any lowercase letter from base 36:

"h" === 17["toString"](36)
"x" === 33["toString"](36)
...

Exposed characters: abcdefghijklmnopqrstuvwxyz

Function("code")() – Evaluate Code

Function constructor is the master key : it takes a String as argument and returns a new anonymous function with this string as the function body. So it basically lets you evaluate any code as a String. This is like eval, without the need for a reference to the global scope (a.k.a. window). We can get it with [].find ["constructor"].

This is the first major step and an essential part of a JS-to-JSFuck compiler. ...

Function("return this")() – window

When evaluating a fresh new function anonymous() { return this }, we get in return the invocation context which is a reference to the global scope here: window

Getting a reference to window is another huge step forward for JSFuck. With the brackets characters, we could only dig in the available objects: numbers, arrays, some functions... With a reference to the global scope, we now have access to any global variable and the inner properties of these globals.


Alternatives

Combine Characters

Use .concat to combine strings:

"f"["concat"]("i")["concat"]("l")["concat"]("l") // fill

Problem: We need to combibe "c", "o", "n", "c", "a" and "t" to get "concat".

Booleans

The ! might be replaced by with more "powerful" characters:

= – Boolean + Assign Values

X == X // true
X == Y // false
X = Y  // assign a new value

> – Boolean + Create Numbers

X > Y  // true
X > X  // false
X >> Y // number

A more complex example is to get character "f" with []>+ only:

[[ []>[] ] + [] ] [[]>>[]] [[]>>[]]
[[ false ] + [] ] [     0] [     0]
[ "false"       ] [     0] [     0]
  "false"                  [     0]

Numbers

Use booleans and bitshift operators to create numbers:

true >> false         // 1
true << true          // 2
true << true << true  // 4

Problem: Some number (like 5) are harder to get. But it is possible when using strings, eg "11" >> true.

Execute Function

Using Backticks

Instead of using opening and closing parentheses, we could use backticks ` to execute functions. In ES6 they can be used to interpolate strings and tagged template literals.

([]["entries"]``).constructor // Object

This would give us characters from "Object" and access to its methods.

Unfortunately, we can only pass a single string (from our basic alphabet eg. []!+) as the parameter. It is not possible to call methods with multiple arguments or precompiled string. To do that, we have to use expression interpolation using ${} which would introduce new characters.

The possibilities of backticks were discussed in detail in the Gitter chat room.

Mapping toString

Another approach executing functions without parentheses would be to map the .toString or .valueOf method and call implicitly.

A=[]
A["toString"]=A["pop"]
A+"" // will execute A.pop

Note: There is no way to pass arguments and it requires to = be present in our basic alphabet. And it only works for methods that return basic types.

So far the only use-case is to wire .toSource in Firefox to get special characters like the backslash \.

Further Readings

JSFuck was not the first approach! Many people around the world are trying to break the so-called "Wall".