Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript eval - obfuscation?

I came across some eval code:

eval('[+!+[]+!+[]+!+[]+!+[]+!+[]]');

This code equals the integer 5.

What is this type of thing called? I've tried searching the web but I can't seem to figure out what this is referred to. I find this very interesting and would like to know where/how one learns how to print different things instead of just the integer 5. Letters, symbols and etc. Since I can't pin point a pattern in that code I've had 0 success taking from and adding to it to make different results.

Is this some type of obfuscation?

like image 334
odran037 Avatar asked Jan 10 '15 16:01

odran037


4 Answers

This type of obfuscation, eval() aside, is known as Non-alphanumeric obfuscation. To be completely Non-alphanumeric, the eval would have to be performed by Array constructor prototypes functions and subscript notation:

[]["sort"]["constructor"]("string to be evaled");

These strings are then converted to non-alphanumeric form.

AFAIK, it was first proposed by Yosuke Hosogawa around 2009. If you want to see it in action see this tool: http://www.jsfuck.com/

It is not considered a good type of obfuscation because it is easy to reverse back to the original source code, without even having to run the code (statically). Plus, it increases the file size tremendously.

But its an interesting form of obfuscation that explores JavaScript type coercion. To learn more about it I recommend this presentation, slide 33: http://www.slideshare.net/auditmark/owasp-eu-tour-2013-lisbon-pedro-fortuna-protecting-java-script-source-code-using-obfuscation

like image 177
Alex Avatar answered Nov 19 '22 08:11

Alex


That's called Non-alphanumeric JavaScript and it's possible because of JavaScript type coercion capabilities. There are actually some ways to call eval/Function without having to use alpha characters:

[]["filter"]["constructor"]('[+!+[]+!+[]+!+[]+!+[]+!+[]]')()

After you replace strings "filter" and "constructor" by non-alphanumeric representations you have your full non-alphanumeric JavaScript.

If you want to play around with this, there is a site where you can do it: http://www.jsfuck.com/.

Check this https://github.com/aemkei/jsfuck/blob/master/jsfuck.js for more examples like the following:

'a':   '(false+"")[1]',
'b':   '(Function("return{}")()+"")[2]',
'c':   '([]["filter"]+"")[3]',
...
like image 38
filipe Avatar answered Nov 19 '22 10:11

filipe


To get the value as 5, the expression should have been like this

+[!+[] + !+[] + !+[] + !+[] + !+[]]

Let us analyze the common elements first. !+[].

  1. An empty array literal in JavaScript is considered as Falsy.

  2. + operator applied to an array literal, will try convert it to a number and since it is empty, JavaScript will evaluate it to 0.

  3. ! operator converts 0 to true.

So,

console.log(!+[]);

would print true. Now, the expression can be reduced like this

+[true + true + true + true + true]

Since true is treated as 1 in arithmetic expressions, the actual expression becomes

+[ 5 ]

The + operator tries to convert the array ([ 5 ]) to a number and which results in 5. That is why you are getting 5.

like image 2
thefourtheye Avatar answered Nov 19 '22 08:11

thefourtheye


I don't know of any term used to describe this type of code, aside from "abusing eval()".

I find this very interesting and would like to know where/how one learns how to print different things instead of just the integer 5. Letters, symbols and etc. Since I can't pin point a pattern in that code I've had 0 success taking from and adding to it to make different results.

This part I can at least partially answer. The eval() you pasted relies heavily on Javascript's strange type coercion rules. There are a lot of pages on the web describing various strange consequences of the coercion rules, which you can easily search for. But I can't find any reference on type coercion with the specific goal of getting "surprising" output from things like eval(), unless you count this video by Destroy All Software (the Javascript part starts at 1:20). Most of them understandably focus on how to avoid strange bugs in your code. For your purpose, I believe the most useful things I know of are:

  • The ! operator will convert anything to a boolean.
  • The unary + operator will convert anything to a number.
  • The binary + operator will coerce its arguments to either numbers or strings before adding or concatenating them. Normally it will only go with strings if one or the other argument is already a string, but there are exceptions.
  • The bitwise operators output integers, regardless of input.
  • Converting to numbers is complicated. Booleans will go to 0 or 1. Strings will attempt to use parseInt(), or produce NaN if that fails. I forget the rest.
  • Converting an object to a string or number will invoke its "toString" or "toValue" method respectively, if one exists.

You get the idea. thefourtheye's answer walks through exactly how these rules apply to the example you gave. I'm not even going to try summarizing what happens when Dates, Functions, and Regexps are involved.

Is this some type of obfuscation?

Normally you'd simply get obfuscation for free as part of minification, so I have no idea why someone would write that in real production code (assuming that's where you found it).

like image 1
Ixrec Avatar answered Nov 19 '22 10:11

Ixrec