How to deobfuscate JavaScript code
What is obfuscation?
Obfuscation is source code modification as a result it becomes difficult to read and understand, but so that its functionality does not change. Obfuscation is used for source code in interpreted (rather than compiled) programming languages. That is, it is JavaScript, PHP, obfuscation can be used for HTML (although it is a markup language, not a programming language), CSS and others, programs on which do not compile, but run in plain text.
Obfuscation is especially relevant for JavaScript, because, unlike, for example, PHP that runs on the web server, JavaScript is loaded into the browser and each user can have access to scripts.
Obfuscation uses different tricks. One of them is the removal of spaces. This is called code minify and is used not only to obfuscate, but to speed up script downloads. As a side effect, this code is really hard to figure out.
Often during obfuscation, the code turns into a meaningless set of functions and lines that cannot be understood, but which ultimately do exactly the same thing as the source code. But there are really amazing examples of obfuscation, for example, JSFuck can display any JavaScript code with just the following six characters []()!+
For example, the following code is workable JavaScript code:
[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[ ]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[] ])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+ (!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+ !+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![ ]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![] +[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[ +!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!! []+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![ ]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[ ]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![ ]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+(! []+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[]) [+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+[+!+[]]+( !![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[ ])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]])()
Obfuscation is used by both legitimate users who want to protect their ideas and their code from theft, and hackers to make it difficult to analyze their methods and programs.
What is deobfuscation
Deobfuscation is the reverse process of obfuscation, that is, the translation of code from a hard-to-read form into an understandable one.
Since there are many obfuscation methods, deobfuscation methods and tools are also many and they have different capabilities and varying degrees of effectiveness.
Deobfuscation is needed both in the analysis of malicious code and in the study of the target site to understand the logic of its operation and search for vulnerabilities.
An example of the use of deobfuscation will be shown in the next article during the site “hacking”.
1. Readable JavaScript in browser
Modern web browsers can beautify compressed to save traffic code to its original state.
In Google Chrome (or Chromium) go to Webmaster Tools (F12 button), select the Sources tab and the file of interest:
Click on the curly brackets icon { } and the code will be transformed into an easy-to-read form:
In Firefox, this button is available on the Debugger tab:
Result:
2. JStillery
JStillery performs advanced JavaScript deobfuscation via partial evaluation.
JStillery can be used without installation – the program is available as an online service from the author: https://mindedsecurity.github.io/jstillery/.
Ho to install JStillery
Installation on Kali Linux
git clone https://github.com/mindedsecurity/JStillery cd JStillery sudo npm install
To compile the server (if you need not only a tool with a command line interface, but you also want to use the web interface):
npm run build_server
To start the server:
npm run start_server
After that, the web interface will be available at http://localhost:3001
Installation in BlackArch
sudo pacman -S jstillery
The use is very simple, just specify the path to the file for deobfuscation:
jstillery /path/to/file
3. Universal deobfuscator of JavaScript code de4js
de4js is a JavaScript source code deobfuscator and unpacker.
It supports (de-obfuscates) the result of the following tools, services, methods:
- Eval, used for example in Packer, WiseLoop
- Array, used for example in Javascript Obfuscator, Free JS Obfuscator
- _Number
- Packer
- Javascript Obfuscator
- Free JS Obfuscator
- Obfuscator.IO (but does not always work, as this service is frequently updated, which requires updating the deobfuscator)
- My Obfuscate
- Кодирование URL, used for example in bookmarklet
- JSFuck
- JJencode
- AAencode
- WiseLoop
Information about installation and launch can be found on the program page: https://en.kali.tools/?p=1372
de4js runs as a small server to which you can connect with a web browser. That is, the program has a web interface.
Go to the folder with the program:
cd bin/de4js
Start the server:
npm start
In a web browser open the address http://127.0.0.1:4000/de4js/
In the web interface, select one of the following methods for entering obfuscated source code:
- String – insert code into the web interface window
- Local File – select a local file on the computer
- Remote File – specify the URL address of a remote file
Below you can specify the way the JavaScript code was obfuscated:
- None
- Eval
- Array
- Obfuscator IO
- _Number
- JSFuck
- JJencode
- AAencode
- URLencode
- Packer
- JS Obfuscator
- My Obfuscate
- Wise Eval
- Wise Function
- Clean Source
- Unreadable
Alternatively, you can click the “Auto Decode” button for de4js to automatically detect the obfuscation method. The deobfuscated code will be shown in the window below.
Additional options that you can turn on or off:
- Line numbers – show line numbers
- Format Code – code formatting and syntax highlighting
- Unescape strings – convert strings from escaped sequences to normal form
- Recover object-path – restore object-path
- Execute expression – perform arithmetic and other operations on expressions
- Merge strings - concatenate strings
- Remove grouping
de4js online: https://lelinhtinh.github.io/de4js/
4. JavaScript online deobfuscator deobfuscatejavascript.com
Service Address: http://deobfuscatejavascript.com/
The source code of this service is not hosted on GitHub, but this product is also open source, since all operations are performed in the browser, and the deobfuscation functions are located in the file http://deobfuscatejavascript.com/deobfuscate.js.
The code analyzed by this tool will be executed in your browser. This tool is designed only to intercept calls made by the eval() and write() functions, which are commonly used as the final function in malicious JavaScript scripts. Some malicious scripts may not use these features and therefore may infect your browser.
This tool is designed to help analysts deobfuscate malicious JavasSripts. It does not interpret HTML, so any HTML must be removed to properly deobfuscate the code. The script also should not contain syntax errors to get the correct results.
Black holes, landing pages, and exploit kits use obfuscation to hide code intent while reducing the chance of detection. When the scripts are packaged, the source code becomes data, and the visible code becomes a deobfuscation procedure. At run time, the data is unpacked by the subroutine, and the result is a string that must be processed as code to execute. This tool during the deobfuscation procedure returns this line of code, but does not start its execution. The resulting code is shown with syntax highlighting.
5. Deobfuscation Obfuscator.IO
The author of the Obfuscator.IO website is looking for programs that are able to deobfuscate the code created on this service and constantly changes, fixes obfuscation, as a result of which the deobfuscation tools stop working. Therefore, automatic deobfuscation tools (including de4js) usually lag behind the most recent version, that is, they can deobfuscate the code created earlier on Obfuscator.IO, but cannot deobfuscate the latest version of the code. But this does not mean that this is a reliable tool to secure your source code – projects regularly appear that bypass all deobfuscation methods. In addition, custom-made specialists can deobfuscate any code.
6. JS Beautifier
JS Beautifier improves the appearance of JavaScript code by reformatting and indenting. In addition it knows how to unpack scripts packaged by the popular packer from Dean Edward. It can partially deobfuscate scripts processed by the npm javascript-obfuscator package. It is used to improve readability of JavaScript code.
The program is available as an online service from the authors: https://beautifier.io/
How to install JS Beautifier
Installation on Kali Linux
sudo apt install npm sudo npm -g install js-beautify js-beautify -h
Installation in BlackArch
There are two installation options – from repositories and as an NPM package. The Python version is available in BlackArch repositories, its features are that html-beautify is completely absent, and css-beautify cannot be installed due to an error. There are also some other differences.
If you want to install from standard repositories then run the following command:
sudo pacman -S python-jsbeautifier
If you want to install Node.js JavaScript version, then run the following commands:
sudo pacman -R python-jsbeautifier sudo pacman -S npm sudo npm -g install js-beautify js-beautify -h
Windows installation
Start by installing Python in the article “How to install Python and PIP on Windows 10”.
After installing Python and PIP, run the commands:
sudo pip3 install jsbeautifier sudo pip3 install cssbeautifier
How to install JS Beautifier on Debian, Linux Mint, Ubuntu you can find on this page: https://en.kali.tools/?p=1359
Usage:
jsbeautifier.py [OPTIONS] <INPUT FILE>
For instance:
jsbeautifier.py [ОПЦИИ] <INPUT FILE>
All js-beautify options:
CLI Options: -f, --file Input file(s) (Pass '-' for stdin) -r, --replace Write output in-place, replacing input -o, --outfile Write output to file (default stdout) --config Path to config file --type [js|css|html] ["js"] -q, --quiet Suppress logging to stdout -h, --help Show this help -v, --version Show the version Beautifier Options: -s, --indent-size Indentation size [4] -c, --indent-char Indentation character [" "] -t, --indent-with-tabs Indent with tabs, overrides -s and -c -e, --eol Character(s) to use as line terminators. [first newline in file, otherwise "\n] -n, --end-with-newline End output with newline --indent-empty-lines Keep indentation on empty lines --templating List of templating languages (auto,none,django,erb,handlebars,php) ["auto"] auto = none in JavaScript, all in html --editorconfig Use EditorConfig to set up the options -l, --indent-level Initial indentation level [0] -p, --preserve-newlines Preserve line-breaks (--no-preserve-newlines disables) -m, --max-preserve-newlines Number of line-breaks to be preserved in one chunk [10] -P, --space-in-paren Add padding spaces within paren, ie. f( a, b ) -E, --space-in-empty-paren Add a single space inside empty paren, ie. f( ) -j, --jslint-happy Enable jslint-stricter mode -a, --space-after-anon-function Add a space before an anonymous function's parens, ie. function () --space_after_named_function Add a space before a named function's parens, ie. function example () -b, --brace-style [collapse|expand|end-expand|none][,preserve-inline] [collapse,preserve-inline] -u, --unindent-chained-methods Don't indent chained method calls -B, --break-chained-methods Break chained method calls across subsequent lines -k, --keep-array-indentation Preserve array indentation -x, --unescape-strings Decode printable characters encoded in xNN notation -w, --wrap-line-length Wrap lines that exceed N characters [0] -X, --e4x Pass E4X xml literals through untouched --good-stuff Warm the cockles of Crockford's heart -C, --comma-first Put commas at the beginning of new line instead of end -O, --operator-position Set operator position (before-newline|after-newline|preserve-newline) [before-newline]
7. UglifyJS
The UglifyJS toolkit performs various actions with code written in JavaScript without changing its functionality. The program can parse, compress, obfuscate or, conversely, make JavaScript scripts more readable.
In terms of deobfuscation, UglifyJS can make compressed JavaScript code readable.
Installation on Kali Linux
sudo apt install uglifyjs
Installation in BlackArch
sudo pacman -S uglify-js
How to install UglifyJS on Debian, Linux Mint, Ubuntu you can find on this page: https://en.kali.tools/?p=1365
Launch example: to improve the appearance of JavaScript code in the file, use the -b option; a file (or several files) must be specified before the options:
uglifyjs medium.js -b
The program can also process files piped in standard input:
cat medium.js | uglifyjs -b
All UglifyJS options:
-h, --help Print usage information. `--help options` for details on available options. -V, --version Print version number. -p, --parse <options> Specify parser options: `acorn` Use Acorn for parsing. `bare_returns` Allow return outside of functions. Useful when minifying CommonJS modules and Userscripts that may be anonymous function wrapped (IIFE) by the .user.js engine `caller`. `expression` Parse a single expression, rather than a program (for parsing JSON). `spidermonkey` Assume input files are SpiderMonkey AST format (as JSON). -c, --compress [options] Enable compressor/specify compressor options: `pure_funcs` List of functions that can be safely removed when their return values are not used. -m, --mangle [options] Mangle names/specify mangler options: `reserved` List of names that should not be mangled. --mangle-props [options] Mangle properties/specify mangler options: `builtins` Mangle property names that overlaps with standard JavaScript globals. `debug` Add debug prefix and suffix. `domprops` Mangle property names that overlaps with DOM properties. `keep_quoted` Only mangle unquoted properties. `regex` Only mangle matched property names. `reserved` List of names that should not be mangled. -b, --beautify [options] Beautify output/specify output options: `beautify` Enabled with `--beautify` by default. `preamble` Preamble to prepend to the output. You can use this to insert a comment, for example for licensing information. This will not be parsed, but the source map will adjust for its presence. `quote_style` Quote style: 0 - auto 1 - single 2 - double 3 - original `wrap_iife` Wrap IIFEs in parenthesis. Note: you may want to disable `negate_iife` under compressor options. -O, --output-opts [options] Specify output options (`beautify` disabled by default). -o, --output <file> Output file path (default STDOUT). Specify `ast` or `spidermonkey` to write UglifyJS or SpiderMonkey AST as JSON to STDOUT respectively. --comments [filter] Preserve copyright comments in the output. By default this works like Google Closure, keeping JSDoc-style comments that contain "@license" or "@preserve". You can optionally pass one of the following arguments to this flag: - "all" to keep all comments - a valid JS RegExp like `/foo/` or `/^!/` to keep only matching comments. Note that currently not *all* comments can be kept when compression is on, because of dead code removal or cascading statements into sequences. --config-file <file> Read `minify()` options from JSON file. -d, --define <expr>[=value] Global definitions. -e, --enclose [arg[:value]] Embed everything in a big function, with configurable argument(s) & value(s). --ie8 Support non-standard Internet Explorer 8. Equivalent to setting `ie8: true` in `minify()` for `compress`, `mangle` and `output` options. By default UglifyJS will not try to be IE-proof. --keep-fnames Do not mangle/drop function names. Useful for code relying on Function.prototype.name. --name-cache <file> File to hold mangled name mappings. --self Build UglifyJS as a library (implies --wrap UglifyJS) --source-map [options] Enable source map/specify source map options: `base` Path to compute relative paths from input files. `content` Input source map, useful if you're compressing JS that was generated from some other original code. Specify "inline" if the source map is included within the sources. `filename` Filename and/or location of the output source (sets `file` attribute in source map). `includeSources` Pass this flag if you want to include the content of source files in the source map as sourcesContent property. `names` Include symbol names in the source map. `root` Path to the original source to be included in the source map. `url` If specified, path to the source map to append in `//# sourceMappingURL`. --timings Display operations run time on STDERR. --toplevel Compress and/or mangle variables in top level scope. --verbose Print diagnostic messages. --warn Print warning messages. --wrap <name> Embed everything in a big function, making the “exports” and “global” variables available. You need to pass an argument to this option to specify the name that your module will take when included in, say, a browser.
Conclusion
If I missed some tool to deobfuscate JavaScript code, then write in the comments!
In the next article, we will try to circumvent the protection of the site, which is written in JavaScript – we will use different approaches, in the most difficult cases, tools for deobfuscation will be useful to us. See the sequel to “JavaScript Attacks”.
Related articles:
- How to see JavaScript code written using unprintable characters (87.9%)
- Bless manual (hex editor) (50%)
- Reverse engineering of network traffic (50%)
- How to find out the type of a file without an extension (in Windows and Linux) (50%)
- How to analyze and split compound files (firmware, multi partition disk images) (50%)
- How to find out hostnames for many IP addresses (RANDOM - 0.5%)
Superb article and very helpfull too.