DEV Community

WangLiwen
WangLiwen

Posted on • Updated on

JavaScript Magic Tricks: Undocumented Usage of Eval

JavaScript Magic Tricks: Undocumented Usage of Eval

In JavaScript programming, Eval is typically used to execute JavaScript code, perform computations, and output results. However, there is an undocumented usage of Eval that few people are probably familiar with.

Here is an example:

var a = eval(['g', 'o', 'l', '.', 'e', 'l', 'o', 's', 'n', 'o', 'c'].reverse().join(""));
var b = ['m', 'o', 'c', '.', 'n', 'a', 'm', 'a', 'h', 's', 'j'].reverse().join("");
a(b);
Enter fullscreen mode Exit fullscreen mode

Can you guess what the output of the function a(b) will be if you only look at the syntax of this JS code? The answer is surprisingly unexpected. Here it is:

Image description

The ability to produce such an output relies on an undocumented usage of Eval that allows converting strings into syntactic keywords. The simplified version of the Eval statement mentioned above would be:

eval("console.log");

Image description

Use reverse and join to hide the plaintext of console.log.

This method is used for encrypting JavaScript code and works quite well. When it comes to obfuscating and encrypting JS code, some signature words are difficult to hide, like console.log. Typically, console.log might be changed to console["log"] or console["\x6c\x6f\x67"], where the "log" characters can be transformed, but console as a syntax keyword cannot be changed, making it easy to be identified. However, this usage of eval can solve this issue and effectively hide many syntax keywords.

Or for example, for encrypting JSON data:

var abc ={a:'This is a', b:'This is b', c:'This is c'};
console.log(abc.a);
console.log(abc.b);
console.log(abc.c);
Enter fullscreen mode Exit fullscreen mode

JSON data, due to its unique format, is notoriously difficult to obfuscate and encrypt with JavaScript, as it is often difficult to hide key names. However, using the method described in this article, you can modify the code to:

eval("var abc ={a:'This is a', b:'This is b', c:'This is c'};");
console.log(abc.a);
console.log(abc.b);
console.log(abc.c);
Enter fullscreen mode Exit fullscreen mode

Encrypt the content inside the eval statement, and the encrypted code can become:
Note: This is done using JShaman JavaScript Obfuscator, the same applies below.

eval("\u0076\u0061\u0072\u0020\u0061\u0062\u0063\u0020\u003d\u007b\u0061\u003a\u0027\u0054\u0068\u0069\u0073\u0020\u0069\u0073\u0020\u0061\u0027\u002c\u0020\u0062\u003a\u0027\u0054\u0068\u0069\u0073\u0020\u0069\u0073\u0020\u0062\u0027\u002c\u0020\u0063\u003a\u0027\u0054\u0068\u0069\u0073\u0020\u0069\u0073\u0020\u0063\u0027\u007d\u003b");
console.log(abc.a);
console.log(abc.b);
console.log(abc.c);
Enter fullscreen mode Exit fullscreen mode

output:

Image description

Top comments (0)