
Write any javascript code with just these characters: ()[]{}+ - alcuadrado
http://patriciopalladino.com/blog/2012/08/09/non-alphanumeric-javascript.html
======
dherman
Arg, scooped! I was working on this _exact_ same thing! :D

Since you've beat me to it, let me offer up a couple additional tricks you
might want to use. If you want to make this completely independent of browser
API's, you can eliminate the dependence on window.location (or atob/btoa as
the sla.ckers.org poster did).

Trick #1 is to get the letter "S".

You can extract this from the source code of the String constructor, but you
want to be careful to make this as portable as possible. The ES spec doesn't
mandate much about the results of Function.prototype.toString, although it
"suggests" that it should be in the form of a FunctionDeclaration. In practice
you can count on it starting with [whitespace] "function" [whitespace]
[function name]. So how to eliminate the whitespace?

For this, we can make use of JS's broken isNaN global function, which coerces
its argument to a number before doing its test. It just so happens that
whitespace coerces to NaN, whereas alphabetical characters coerce to 0. So
isNaN is just the predicate we need to strip out the whitespace characters. So
we can reliably get the string "S" from:

[].slice.call(String+"").filter(isNaN)[8]

Of course, to get isNaN you need the Function("return isNaN")() trick, and you
know how the rest of the encoding works.

Trick #2 then lets you get any lowercase letter, in particular "p".

For this, we can make use of the fact that toString on a number allows you to
pick a radix other than 2, 8, 10, or 16. Again, the ES spec doesn't _mandate_
this, but in practice it's widely implemented, and the spec does say that if
you implement it its behavior needs to be the proper generalization of the
other radices. So we can get things like:

(25).toString(26) // "p"

(17).toString(18) // "h"

(22).toString(23) // "m"

and other hard-to-achieve letters.

But once you've got "p", you're home free with escape and unescape, as you
said in your post.

Dave

~~~
mathias
Now that you mention it — V8 has an interesting bug with excessive
Number#toString() decimal digits
(<http://code.google.com/p/v8/issues/detail?id=1627>).

For example:

    
    
        (1.1536999999997645e-10).toString(33).match(/[a-z]+/g)[81]; // 'oops'
    

More here: <https://gist.github.com/1153826>

~~~
dherman
Funky! Luckily that bug doesn't interfere with this trick, since it's only
relying on pretty-printing integers.

Dave

------
CurtHagenlocher
This is like a bizarro-world lambda calculus, complete with its own Church
numerals.

------
dag11
I made a little script to extract the original javascript from a script
obfuscated with OP's tool (<http://patriciopalladino.com/files/hieroglyphy/>).

And because I felt it was appropriate, I created this extraction script _in_
an obfuscated form!

Use this to extract obfuscated scripts:
<http://pastebin.com/raw.php?i=Q9TB4wEF>

Just save your obfuscated script in a variable called "original" and then run
my code. It'll return with the extracted script.

Oh, and it won't work on itself. That's because I didn't use the obfuscation
tool to create it. I made it mostly by hand: <http://pastebin.com/9LBWCSJs>

------
quarterto
There are no words to describe how dirty this makes me feel.

------
apendleton
This post title omits "!" which is also necessary.

~~~
alcuadrado
My fault, not intended

------
stcredzero
So, basically Javascript is just a superset of an esolang that contains
itself.

<http://esolangs.org/wiki/Main_Page>

(Especially true if you're developing with a Javascript interpreter hosted in
Javascript. Really, it's esolangs all the way down.)

------
maartenscholl
If you like reducing programs to basic expressions you should read into SKI
combinator calculus and the X combinator. Here is a paper that describes the
construction of an efficient X combinator[1]. Reading the paper gave me
insight in how simple yet powerful combinatory logic is.

[1]www.staff.science.uu.nl/~fokke101/article/combinat/combinat.ps

------
bgeron
I evalled all pieces of Javascript of <30 characters in Rhino, takes 1 minute
on my laptop. 4219 possible values, after stripping out some really
uninteresting stuff. Doesn't seem to contain anything interesting,
unfortunately.

<http://pastebin.com/CM5ac6Xi>

~~~
chx
I am not sure about those results. I entered (+[][{}]+{})[+[]] into Chrome
console and got N (from NaN[Object object]) while your code lists it as u. If
you replace the first +[] with a 0 you get an u (from undefined...).
Interesting.

------
jerfelix
Looks cool, but I couldn't make it work.

I went to <http://patriciopalladino.com/files/hieroglyphy/> and put in a
script "alert(1);". This provided me with a script of about 8300 characters.

I created a web page to execute the script:

    
    
        <body onload="
        [][(![]+[])[!+[] ...
        </body>
    

Firebug reports:

    
    
        ReferenceError:  Unescaee is not defined.
    

Looks like it's having trouble picking up a "p".

~~~
CUViper
Did you try to do this locally? The article explains that the "p" is picked up
from window.location, assuming it's http or https. If you're using
"file://...", that third character index is 'e' instead.

~~~
jerfelix
Good catch! You diagnosed my eroblem eerfectly.

------
spicyj
The article lists [][+[]] for undefined; you can get away with just [][[]].

------
infinity
Some of you may also enjoy aaencode by Yosuke Hasegawa:

<http://utf-8.jp/public/aaencode.html>

Encode any JavaScript program to Japanese style emoticons (^_^)

And of course jjencode:

<http://utf-8.jp/public/jjencode.html>

(hint: have a look at "palindrome")

~~~
skrebbel
Apparently, he also did the OP's trick: <http://utf-8.jp/public/jsfuck.html>
(but without, {} even)

~~~
dherman
Unfortunately, his tricks no longer work in current JS engines; it relies on
using

    
    
      [].sort.call()
    

which I believe used to return the global object but now throws an exception.

AFAICT, you need to add {} to make this work in current JS engines.

Dave

------
mistercow
Man, if you didn't care about performance or bandwidth, this would be a hell
an of obfuscation technique.

~~~
alcuadrado
This is pretty easy to reverse. Most JS parsers can print the source code of
functions, so you can do that for the generated lambdas.

~~~
mistercow
Yes of course. And even if they couldn't, it would be trivial to fork an
existing JS implementation and make eval spit out its input.

------
ctdonath
Cross this with John Horton Conway's notion of "Surreal Numbers" and you might
be onto something.

------
alter8
This guy did it with 6 characters by removing {}. But it lacks the detailed
description available in this post.

EDIT: I didn't check properly. You only use {} for a minor detail.

<http://utf-8.jp/public/jsfuck.html>

~~~
cseax
Is it just me, or does recursing his example break chrome?

------
skrebbel
Could someone please enlighten me as to how this helps doing an XSS attack?

~~~
TazeTSchnitzel
Some sites "filter" user input instead of escaping it.

------
jared314
I remember something like this a few years ago. They were using it for XSS.
<http://news.ycombinator.com/item?id=1153383>

------
rubyrescue
this is very cool...let me know if you want a job at inaka (we're in BA and
have other people in school working for us)

------
chris_wot
I wonder how well gzip would compress this?

~~~
michaelmior
Example: 47,734 bytes to 813. ~98%

~~~
chris_wot
Pretty damn well! I wonder what the decompression and parsing time is...

------
michokest
Minor typo:

> "[object Object]" with {}+[]

I believe it should be []+{}

------
bazookaBen
i pasted the entire json library into the field and it just hung. Any tips?

------
bradsmithinc
Witchcraft

------
Fando
really cool

------
mynameishere
Write any Windows application with just the following characters: 0 1

~~~
ethereal
... you'd need some preprocessing first. The ASCII characters `0' and `1'
aren't easy to use to write a program, though you could do it with nasm and
some '-' and '+'s I suppose.

If someone can prove me wrong, I'd be very happy though. Writing a program
using just '0' and '1' (the ASCII characters) would be awesome. (in an
established programming language, and no homomorphisms. :) )

