How to see JavaScript code written using unprintable characters

In the article “How to obfuscate JavaScript code”, at the very end I gave “esoteric” examples from the author of JSFuck in which most of the code is simply invisible. I recommend looking at those concepts that the author has prepared – they are admirable and make you think about the capabilities of JavaScript. The programmer writes the lines as an escaped sequence and/or uses encoding tricks. Whatever it was, but when copying-pasting, the code looks like this:

<body onload=eval(eval('"'+escape("############################################################################################################################################################################################################################################################################################################################################################################################################################").replace(/..(.)..(.)/g,'\\x$1$2')+'"'))>

And when viewing the source code of a page, the JavaScript code looks like this:

The first thought is to save the page and look in the hex editor. Of course, we will see code bytes, but it will be difficult to restore them to executable code. Let's look at the ways in which you can see invisible JavaScript code and at the same time get acquainted with some more features of the Developer Tools in web browsers.

1. Stop execution before the last eval

Let's start with an example called “Invisible Code” - an invisible source code: http://aem1k.com/0/

We see that the code starts with “<body onload=eval(eval('"'+escape("”. The first eval call receives some code to execute, and the result is passed to the second eval call also to be executed as code. And the result of the second call of eval is displayed on the screen, that is, the source code of interest to us is transferred to the second eval. We remove this call and assign what should have been given to eval to execute, the variable a.

I’ll make changes to the code in the Developer Tools in a web browser, and to save them after the page is updated, I will use the method from the article “How to make changes in browser Developer Tools persist after page reload”.

We will slightly transform the code so that we can make our own changes to it and check its performance:

<body>

<script>
eval(eval('"'+escape("HIDDEN CODE").replace(/..(.)..(.)/g,'\\x$1$2')+'"'))
</script>

The code retained its functionality, so we continue to change:

<body>

<script>
a=eval('"'+escape("HIDDEN CODE").replace(/..(.)..(.)/g,'\\x$1$2')+'"')
document.write(a);
</script>

As you can see, the idea as a whole worked, that the output of the code is broken due to some reason:

Again, a little change in the approach to code output:

<script>
a=eval('"'+escape("HIDDEN CODE").replace(/..(.)..(.)/g,'\\x$1$2')+'"')
alert(a);
</script>

I got the code:

Apparently my focus with <pre> did not work for the reason that the code also uses the <pre> tag.

To test whether it is still functional, I save this code in a file with the .htm extension:

And I open it in the browser to make sure that the code is working:

So, I managed to get a code that was previously invisible and displayed as dots.

2. Pause JavaScript

The following example // VOID - invisible variables and code: https://aem1k.com/void/

Using the previous method here is difficult, because the code is written in several lines and generally, at the last stage, eval is not used. Moreover, most modifications of the source code (even extra spaces after </script>) make this code non-functional.

Let's see the structure of the DOM document:

There are a lot of interesting things, but this time it did not help.

Go back to the Sources tab and pause JavaScript:

Please note that a new file has opened – it contains JavaScript code that is executed when paused. Let's make this code more readable:

i = setInterval(I=>{
    document.body.style.backgroundColor = 0;
    document.body.style.color = "#0FF";
    document.body.innerHTML = "<pre>&lt;script>   " + document.head.textContent.replace(/ᅠ‌*/g, "").replace(/"'.*'"/, "\"''\"").replace(/./g, x=>`<b style="color:#${["F0F", "FF0"][i++ % 5] || "0FF"}">${x}</b>`) + "&lt;/script>"
}
, 100)

Again I save the code in the .htm file:

And open in a web browser to check:

Everything is working! Although now other characters shimmer. The bottom line is that the source code shimmers, whatever it may be (that is, yes, the source code that is currently running is displayed on the page, this is such an interesting script).

3. Invisible characters in JavaScript can still be copied!

Let's try to deobfuscate invisible code using JStillery.

Again, take the previous example (https://aem1k.com/void/), copy the source code in its original form and paste it into JStillery. Amazingly, this trick succeeded:

Received code after deobfuscation:

undefined;
ᅠ‌‌‌‌‌‌‌‌ = '"';
ᅠ‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌ = true;
ᅠ‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌ = false;
ᅠ‌‌‌‌‌‌‌‌‌‌‌‌ = 'true';
ᅠ‌‌‌‌‌‌‌ = 'false';
ᅠ‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌ = 0;
ᅠ‌ = 1;
ᅠ‌‌‌‌‌‌‌‌‌ = {};
ᅠ‌‌ = 2;
ᅠ‌‌‌ = 3;
ᅠ‌‌‌‌‌ = 5;
ᅠ‌‌‌‌‌‌‌‌‌ = '[object Object]';
ᅠ‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌ = 'undefined[object Object]';
ᅠ‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌ = 'n';
ᅠ‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌ = 't';
ᅠ‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌ = 'r';
ᅠ‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌ = 'c';
ᅠ‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌ = 'u';
ᅠ‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌ = 'o';
ᅠ‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌ = 's';
ᅠ‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌ = 'e';
ᅠ‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌ = 'a';
ᅠ‌‌‌‌‌‌‌‌‌‌‌‌‌ = '\\)(';
ᅠ‌‌‌‌‌‌‌‌‌‌‌ = '\\';
ᅠ‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌ = '(';
ᅠ‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌‌ = ')';
ᅠ‌‌‌‌‌‌ = 'return ';
ᅠ‌‌‌‌‌‌‌‌‌‌ = 'constructor';
ᅠ‌‌‌‌‌‌‌‌‌‌‌‌‌‌ = Function;
(function anonymous() {
    i = setInterval(I =>
        /* Called:undefined | Scope Closed:false| writes:false*/
        {
            document.body.style.backgroundColor = 0;
            document.body.style.color = '#0FF';
            document.body.innerHTML = '<pre>&lt;script>   ' + document.head.textContent.replace(/ᅠ‌*/g, '').replace(/"'.*'"/, '"\'\'"').replace(/./g, x => /* Called:undefined | Scope Closed:false| writes:false*/
            '<b style="color:#' + ([
                'F0F',
                'FF0'
            ][i++ % 5] || '0FF') + '">' + x + '</b>') + '&lt;/script>';
        }, 100);;
}());

As you can see, additional lines are displayed in it, but the second part coincides with the deobfuscated code obtained in the previous way.

The code is also working:

The code from the first example (http://aem1k.com/0/) failed to be deobfuscated in this way. I think the thing is most likely that the code spoils when copying and pasting (note: later I realized that the thing was that I had to remove HTML tags, copy-paste would also work, as in the example above). Therefore, we will try in another way – save the file with invisible JavaScript. But we will not save in the web browser – web browsers add a lot of unnecessary strings. Save using wget or cURL, for example:

wget http://aem1k.com/0/ -O 0.htm

From the saved page, we remove everything that does not apply to JavaScript, for example, in this case, I removed <body onload= and >.

Run deobfuscation on the command line using jstillery:

jstillery 0.htm

It works, and we again received the code fragment that we had already seen before.

4. Deobfuscation of JavaScript written on non-Latin writing systems

Take another example: aurebesh.js - translating JavaScript to other writing systems: https://aem1k.com/aurebesh.js/

For example, the following code works in a web browser:

<script>
        ก='',ว=!ก+ก,อ=!ว+ก,ซ=ก+{},ฝ=ว[ก++],ค=ว[ง=ก],ญ=++ง+ก,ฒ=ซ[ง+ญ],ว[ฒ+=ซ[ก]+(ว.อ+ซ)[ก]+อ[ญ]+ฝ+ค+ว[ง]+ฒ+ฝ+ซ[ก]+ค][ฒ](อ[ก]+อ[ง]+ว[ญ]+ค+ฝ+"(ก)")()
</script>

But how do you know what exactly is written in it?

If you remove the <script></script> tag from this code, you can deobfuscate it using JStillery:

jstillery thai.htm

We get the code:

ก = '';
ว = 'true';
อ = 'false';
ซ = '[object Object]';
ฝ = 't';
ค = 'true'[ง = 1];
ญ = 3;
ฒ = 'c';
'true'[ฒ = 'constructor'].constructor('alert(ก)')();

Deobfuscation was successful, but it should be noted that the resulting code did not fully retain the functionality: alert displays an empty string instead of “1”).

Let's try another option. Open the file with the code in a web browser and click the “Format” button. We will also pause script execution:

Since the script has already completed execution, reload the page and press F9 to step through the execution of JavaScript.

As a result, the executable code will be shown in its usual form, in how the JavaScript engine sees it:

(function anonymous(
) {
alert(ก)
})

Conclusion

I liked these examples as puzzles. The considered code fragments, despite their “anomaly”, once again confirm that it is very difficult and in most cases impossible to protect JavaScript and HTML code from analysis and modification.

Last Updated on

Recommended for you:

Leave a Reply

Your email address will not be published.