Breaking down one of the coolest JavaScript obfuscators

Image for post
Image for post

Secure your JS code is one of the most important tasks when you have to expose your code to users. That is when JavaScript obfuscator like aaencode, comes to help. Today I’m going to analyze the obfuscated code to know more about how the obfuscated code is executed and in the same time, achieve more knowledge about JS data type.

What is aaencode

You may be unfamiliar with this name, so let me show you what you have missed. The obfuscator named "aaencode" is one of the coolest JS obfuscators created by Yosuke Hasegawa. Unlike other obfuscators, while other obfuscators obfuscated code give you the sense of a solveable code, aaencode make it so hard to read that when you look at it, you don't even think that is a working JS code.

Here's the proof, let's try to obfuscate a simple line of code.

alert("hi")

How it looks in aaencode

゚ω゚ノ= /`m´)ノ ~┻━┻   //*´∇`*/ ['_']; o=(゚ー゚)  =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_');

Believe or not, the code above works perfectly, you can try execute it in the browser’s console and get familiar with it as that piece of obfuscated code will about to be broke down.

Let beautify our cinderella

To increase readability, I used an extremely useful website called jsbeautifier to somewhat deobfuscate the code. After using jsbeautifier, there was only a mild improvement in readability as all of the variables are UTF8 character.

Image for post
Image for post
The result after using jsbeautifier

Crazy right? This feature of JS is immensely useful for making code more complicated. Basically, if you use UTF8 character to name your variables then this line of code bellow is consider as valid JS.

var ಠ_ಠ = "I'm done with JS"; 
alert(ಠ_ಠ);

So how do we solve this problem? There is only 1 way, is to replace all the UTF8 variable names with English alphabet letters. This process will take quite some time but with the replace all feature of sublime text I was able to finish the task in just a few minutes.

Image for post
Image for post

Deeper into the world of code

Let’s first look at the first 10 lines.

a = /`m´)ノ ~┻━┻   / /*´∇`*/ ['_'];
o = (b) = _ = 3;
c = (d) = (b) - (b);
(e) = (d) = (o ^ _ ^ o) / (o ^ _ ^ o);
(e) = {
d: '_',
a: ((a == 3) + '_')[d],
h: (a + '_')[o ^ _ ^ o - (d)],
i: ((b == 3) + '_')[b]
};

First of all, we can see that the code is assigning some dark magic characters to the variable “a”. However, despite its weird looking, its value is actually just because the value of consists 3 parts

/`m´)ノ ~┻━┻   / -> regular expression
/*´∇`*/ -> comment
['_'] -> object property selector

So the value of is the value of the property in the regex and because the property is not defined so it will return .

Next, the value of , and is set to 3. Afterward, the variables and are created and assigned the value of which is . The variable is then shares it value with which is a newly created variable and both of them contain a new value which is smile face divided smile face.

Haha, that actually not a smile face, it’s a combination bettween the and the variable using the xor operator and the divide operator. The actual value of a smile face is.

(o ^ _ ^ o) = (3 ^ 3 ^ 3) = 3

So we can calculate the value of and is now equals to .

Then changed its value to an object, that means only is now carry the value of . The value of e is now easy to resolve as it’s now just basic JavaScript.

(e) = {
d: '_',
a: ((a == 3) + '_')[d],
h: (a + '_')[o ^ _ ^ o - (d)],
i: ((b == 3) + '_')[b]
};

Let’s take a look at the property, its value is . Now we all know that is equals to so will definitely return , then is concatenated with the string which change the value to and after that the index of the string is taken which is the index of the string, that means the property is now equals to .

Same thing with ,property, we will have

(a + '_')[o ^ _ ^ o - (d)] = 'undefined_'[3 - 1] = 'd'

and property will possess the value of

((b == 3) + '_')[b] = (true + '_')[3] = 'true_'[3] = 'e'

Let rewrite our code with the new value that we have successfully calculated.

a = undefined;
o = (b) = _ = 3;
c = (d) = 0;
(e) = (d) = 1;
(e) = {
d: '_',
a: 'a',
h: 'd',
i: 'e'
};

Move on to the next 3 lines.

(e)[d] = ((a == 3) + '_')[c ^ _ ^ o];
(e)['c'] = ((e) + '_')[(b) + (b) - (d)];
(e)['o'] = ((e) + '_')[d];

The first line in those 3 lines is seem to be assigning a new property to the object variable. Because is equals to and there is no property named in so JavaScript will create a new property if you assign some value to a undefined property. That means is now own another property with value of .

Same thing will happen with the next 2 lines. But something different appeared in those 2 lines. They concatenating with ? How can an object combine with a character? Well, if you try to concatenate an object with a character or string, JavaScript will not return any error but instead it will call the method of both object and string then return the result string after add those 2 string achieved from the method together.

Image for post
Image for post

Here is the result of it.

Image for post
Image for post

Thus, the value of the last 2 lines will be

(e)['c'] = ((e) + '_')[(b) + (b) - (d)] = '[object Object]_'[5] = 'c'
(e)['o'] = ((e) + '_')[d] = '[object Object]_'[1] = 'o';

Again let rewrite the variable with the newly added property.

Image for post
Image for post

Take a break !

You should now take a break because we have just finished our work with the stage 1 and you won’t survive the stage 2 if you don’t take a break. Who said JavaScript is easier than calculus?

More complicated code

Now we will move on to the hardest part of our analyzing process. Here is a part of the rest of our obfuscated code and in this section we will analyze the part from the beginning of the code to the line 22.

Image for post
Image for post

Let’s start with the first line

(g) = (e)['c'] + (e)['o'] + (a + '_')[d] + ((a == 3) + '_')[b] + ((e) + '_')[(b) + (b)] + ((b == 3) + '_')[d] + ((b == 3) + '_')[(b) - (d)] + (e)['c'] + ((e) + '_')[(b) + (b)] + (e)['o'] + ((b == 3) + '_')[d];

As you can see that’s a very long line of code we can separate them like this

(g) = 
(e)['c'] +
(e)['o'] +
(a + '_')[d] +
((a == 3) + '_')[b] +
((e) + '_')[(b) + (b)] +
((b == 3) + '_')[d] +
((b == 3) + '_')[(b) - (d)] +
(e)['c'] + ((e) + '_')[(b) + (b)] +
(e)['o'] + ((b == 3) + '_')[d];

Look like this statement is trying to build a string because we can see that the first thing that they concatenate is which is a character . Thus, we can replace all the variable and obtain this result.

(g) = 
(e)['c'] + // 'c'
(e)['o'] + // 'o'
(a + '_')[d] + // 'n'
((a == 3) + '_')[b] + // 's'
((e) + '_')[(b) + (b)] + // 't'
((b == 3) + '_')[d] + // 'r'
((b == 3) + '_')[(b) - (d)] + // 'u'
(e)['c'] + // 'c'
((e) + '_')[(b) + (b)] + // 't'
(e)['o'] + // 'o'
((b == 3) + '_')[d]; // 'r'
// 'c' + 'o' + 'n' + 's' + 't' + 'r' + 'u' + 'c' + 't' + 'o' + 'r'
// 'constructor'

So this line of code just build the stirng and then assign it to a new variable called .

Move on to the next statement, we have a very short but interesting line of code.

(e)['_'] = (o ^ _ ^ o)[g][g];

So we know that the property is not exists in the object variable so we can conclude that this line of code is creating and assigning a new value to that property. But that’s a weird value because we have analyzed before that the smile face will return 3 and will equals to . Thus, our line true value is

(e)['_'] = 3['constructor']['constructor']

So what’s constructor? According to this link, will

Returns a reference to the constructor function that created the instance object. Note that the value of this property is a reference to the function itself, not a string containing the function's name. The value is only read-only for primitive values such as , and .

So basically, you can use to create a new instance of that object type.

Image for post
Image for post

Now an intriguing question to ask is “what is the constructor of an object constructor?”

Every constructor of a class in JavaScript is a function.

Thus, the constructor of the constructor of a object is a constructor of a function and every function in JavaScript is a object. See the first sentence in the description section in this site to know more.

A object is a global object and according to MDN web docs

The constructor creates a new object. Calling the constructor directly can create functions dynamically, but suffers from security and performance issues similar to .

With some furthur reading, you will discover that this is a bit like the function except it will create an anonymous function but not to invoke it.

Image for post
Image for post
The a function will only execute if we call it

Back to the main reason why we conduct all of these researchs — our short line of code.

(e)['_'] = (o ^ _ ^ o)[g][g];

That means the property of object variable is now contains a reference to the object constructor.

Our next line of code is a bit shorter than the first one but don’t worry this is just another string building code.

(f) = ((b == 3) + '_')[d] + (e).i + ((e) + '_')[(b) + (b)] + ((b == 3) + '_')[o ^ _ ^ o - d] + ((b == 3) + '_')[d] + (a + '_')[d];

The final result will be

(f) = 
((b == 3) + '_')[d] + // 'r'
(e).i + // 'e'
((e) + '_')[(b) + (b)] + // 't'
((b == 3) + '_')[o ^ _ ^ o - d] + // 'u'
((b == 3) + '_')[d] + // 'r'
(a + '_')[d]; // 'n'
// 'r' + 'e' + 't' + 'u' + 'r' + 'n'
// 'return'

So now we have created a new variable named with the string within it.

The last five lines of our stage 2 code.

(b) += (d);
(e)[f] = '\\';
(e).j = (e + b)[o ^ _ ^ o - (d)];
(obo) = (a + '_')[c ^ _ ^ o];
(e)[g] = '\"';

It’s clear that the first line will increase the variable by the value of which is 1. Now will hold the value of 4.

The next line will take the string that we obtained in the previous step which is to use as a property object and the value of it is a string or more precise, a character.

In this line the code continue to add another property to the object and its value is

(e).j = (e + b)[o ^ _ ^ o - (d)]; // -> (e).j = '[object Object]4'[2] = 'b'

Next it create a new variable named to store a character .

(obo) = (a + '_')[c ^ _ ^ o]; // -> (obo) = 'undefined_'[0] = 'u'

Then is continue to be added a new property in this line.

(e)[g] = '\"'; // -> (e)['constructor'] = '\"'

And that’s the end of our stage 2. We can now rewrite our code and here is how it look after rewriting.

Image for post
Image for post

Last line standing

Image for post
Image for post

We are now at the final stage of our analyzing process. Only 1 last line of code which is also the most crucial line of all.

(e)['_']((e)['_'](f + (e)[g] + (e)[f] + (d) + (b) + (d) + (e)[f] + (d) + ((b) + (d)) + (b) + (e)[f] + (d) + (b) + ((b) + (d)) + (e)[f] + (d) + ((o ^ _ ^ o) + (o ^ _ ^ o)) + ((o ^ _ ^ o) - (d)) + (e)[f] + (d) + ((o ^ _ ^ o) + (o ^ _ ^ o)) + (b) + (e)[f] + ((b) + (d)) + (c ^ _ ^ o) + (e)[f] + (b) + ((o ^ _ ^ o) - (d)) + (e)[f] + (d) + ((b) + (d)) + (c ^ _ ^ o) + (e)[f] + (d) + ((b) + (d)) + (d) + (e)[f] + (b) + ((o ^ _ ^ o) - (d)) + (e)[f] + ((b) + (d)) + (d) + (e)[g])(d))('_');

First, let’s separate them into parts.

(e)['_'](
(e)['_'](
f + (e)[g] + (e)[f] + (d) + (b) + (d) + (e)[f] + (d) + ((b) + (d)) + (b) + (e)[f] + (d) + (b) + ((b) + (d)) + (e)[f] + (d) + ((o ^ _ ^ o) + (o ^ _ ^ o)) + ((o ^ _ ^ o) - (d)) + (e)[f] + (d) + ((o ^ _ ^ o) + (o ^ _ ^ o)) + (b) + (e)[f] + ((b) + (d)) + (c ^ _ ^ o) + (e)[f] + (b) + ((o ^ _ ^ o) - (d)) + (e)[f] + (d) + ((b) + (d)) + (c ^ _ ^ o) + (e)[f] + (d) + ((b) + (d)) + (d) + (e)[f] + (b) + ((o ^ _ ^ o) - (d)) + (e)[f] + ((b) + (d)) + (d) + (e)[g] )(d))
('_');

As you can see, the is wrapping all the code inside it and is the object constructor so we know this line is trying to dynamically make a function and execute it. We also know that object constructor take a string to use it as the function body, so the code within it must be building a string. Using the browser console we can see that the inner code is building the string

return"\141\154\145\162\164\50\42\150\151\42\51"
Image for post
Image for post

What does means?

It actually is a octal escape string. By pasting it directly to the console we can obtain its true value, which is

alert("hi")
Image for post
Image for post

Let rebuild the code

(e)['_']( (e)['_']( "return \"alert(\"hi\")\" ) (d)) ('_');

We can rewrite the inner function to this

(function(){ return "alert(\"hi\")"; })(d)

So after the function is built it is then invoked with a parameter and string will be passed to the outter constructor which will make a function and use that string as the function body. After constructing the function it will invoke the function using the character and that’s how our code is executed.

Case closed

Image for post
Image for post

That’s how aaencode JS obfuscator works and it will take a significant amount of time to analyze it, however, nothing is impossible. Also, I want to thank Yosuke Hasegawa for create this amazing obfuscator and I hope after reading this, you guys will find some interesting things to do with JS and please drop a comment if you have any question or compliments :))

Goodbye and Merry Christmas.

The happy lone guy

The happy lone guy blog

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store