# Emotet JavaScript downloader **[maxkersten.nl/binary-analysis-course/malware-analysis/emotet-javascript-downloader/](https://maxkersten.nl/binary-analysis-course/malware-analysis/emotet-javascript-downloader/)** _This article was published on the 8th of April 2020. This article was updated on the 8th of_ _December 2021._ The Emotet trojan is dropped in multiple stages. The first stage is an office file that contains a macro. This macro then loads the second stage, which is either a PowerShell script or a piece of JavaScript. A PowerShell based downloader script that was used to downloaded the [Emotet binary, is analysed in the Emotet droppers article. In this article, a JavaScript based](https://maxkersten.nl/binary-analysis-course/malware-analysis/emotet-droppers/) downloader is analysed in the usual step-by-step manner. At first, the obfuscation methods are explained, after which the deobfuscated sample is analysed. ## Table of contents Sample information The JavaScript based downloader is lauched by a macro in a Word document. The hashes of both samples are given below. Additionally a sample package (which contains both files) [can be downloaded from MalShare,](https://malshare.com/sample.php?action=detail&hash=fb8eacb936940d255e856bbe8dfba277) [Malware Bazaar, or](https://bazaar.abuse.ch/sample/ddfedf6178d86d3372922620116d8c973e0627b5ac1ef087cc7c15cfcc452480/) [VirusBay.](https://beta.virusbay.io/sample/browse/fb8eacb936940d255e856bbe8dfba277) ``` Word document MD-5: 12c0a3f94e87c9c4baa70e63cbb8f132 Word document SHA-1: 219588d23f281f1fafad61780c115e1f61c7cd52 Word document SHA-256: 8d3de338b1f13c55c73461a24fef506de8733e392cd145cc3a6a843bab28ee3d JavaScript MD-5: b23fd915ab76f0d3f79d90c7cbb87f54 JavaScript SHA-1: d8bd63db6475105200fbdcc09fcb1e1c4bbde190 JavaScript SHA-256: b47c3e2c8dd09054e1eec662db8ee433acb494467b6517a3a022cd7c399cef17 ``` Note that this article only covers the JavaScript based downloader. ## Analysis outline [The JavaScript file is obfuscated using Obfuscator.io‘s obfuscator. One can inspect the](https://obfuscator.io/) obfuscator’s source code to understand how it works. Its not often that the obfuscator’s source code is available, which is why its not used in this article. Understanding how to approach such a sample, and knowing how to recognise patterns in code, is a valuable skill to develop. ## Deobfuscating the code ----- This article will show six steps that are required to remove the obfuscation. Firstly, the original strings are retrieved. After that, multiple dead code variants are removed. Thirdly, the _dictionary mappings within functions are addressed. Fourthly, the control flow is unflattened._ Fifthly, the function overrides are explained. Lastly, function callbacks are addressed. After the deobfuscation is complete, the original payload will be reconstructed and analysed step-by-step. ### Retrieving strings Within the sample, the strings are stored in a single array, as can be seen when scrolling through the code. The strings are obtained from this array during run time. The code below provides the string array, together with a function that alters the array. ``` var a = ['base64-encoded-value', 'another-base64-encoded-value', ... ]; (function(c, d) { var e = function(f) { while (--f) { c['push'](c['shift']()); } }; e(++d); }(a, 0x13b)); ``` The anonymous function shuffles the array’s order 0x13b places, or 315 in decimal. Directly below that, a function is defined. The code is given below. ----- ``` var b function(c, d) { c = c - 0x0; var e = a[c]; if (b['glFLpC'] === undefined) { (function() { var f = function() { var g; try { g = Function('return\x20(function()\x20' + '{}.constructor(\x22return\x20this\x22)(\x20)' + ');')(); } catch (h) { g = window; } return g; }; var i = f(); var j = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; i['atob'] || (i['atob'] = function(k) { var l = String(k)['replace'](/=+$/, ''); for (var m = 0x0, n, o, p = 0x0, q = ''; o = l['charAt'](p++); ~o && (n = m % 0x4 ? n * 0x40 + o : o, m++ % 0x4) ? q += String['fromCharCode'](0xff & n >> (-0x2 * m & 0x6)) : 0x0) { o = j['indexOf'](o); } return q; }); }()); var r = function(s, d) { var u = [], v = 0x0, w, x = '', y = ''; s = atob(s); for (var z = 0x0, A = s['length']; z < A; z++) { y += '%' + ('00' + s['charCodeAt'](z)['toString'](0x10))['slice'] (-0x2); } s = decodeURIComponent(y); for (var B = 0x0; B < 0x100; B++) { u[B] = B; } for (B = 0x0; B < 0x100; B++) { v = (v + u[B] + d['charCodeAt'](B % d['length'])) % 0x100; w = u[B]; u[B] = u[v]; u[v] = w; } B = 0x0; v = 0x0; for (var C = 0x0; C < s['length']; C++) { B = (B + 0x1) % 0x100; v = (v + u[B]) % 0x100; w = u[B]; u[B] = u[v]; ``` ----- ``` u[v] w; x += String['fromCharCode'](s['charCodeAt'](C) ^ u[(u[B] + u[v]) % 0x100]); } return x; }; b['DeXxzd'] = r; b['qjpvAF'] = {}; b['glFLpC'] = !![]; } var D = b['qjpvAF'][c]; if (D === undefined) { if (b['dXYIcg'] === undefined) { b['dXYIcg'] = !![]; } e = b['DeXxzd'](e, d); b['qjpvAF'][c] = e; } else { e = D; } return e; }; ``` This function is called at places where a string is normally located in the script. An example of such a call is given below. ``` b('0x0', '(6q)') ``` The first parameter is the index of the value in the string array, as can be seen in the code excerpt below. ``` var b = function(c, d) { c = c - 0x0; var e = a[c]; ``` The second argument is used in the decryption of he given string. Searching for some of the _[magic values, will lead to the conclusion that the RC4 encryption algorithm is used, and is](https://en.wikipedia.org/wiki/RC4)_ decrypted using this function. Note that the string array contains base64 encoded strings, as not all encrypted output is printable. As such, the decryption function base64 decodes the strings first, using the [atob function. The refactored function template is given below.](https://www.w3schools.com/jsref/met_win_atob.asp) ``` decrypt(index, rc4_key) ``` Note that one can also find the usage of the RC4 encryption algorithm in the feature list of the obfuscator. As stated prior, this article does not rely on the feature list nor source code of the obfuscator, as this is not always available. To clean the script, replace all occurrences of the decryption function with the result it returns for the given array. One can copy the string array and shuffle function into the browser’s console to obtain the shuffled and decrypted values, or automate the process with a script. A ----- version of the script where all strings have been replaced is present in the file package that is provided in the beginning. ### Dead code removal Within the script, dead code is present in several ways. The two most occurring methods are the insertion of dead code in the form of variables and the creation of redundant ifstatements. To avoid automatic removal of unused variables, the variables link to other dead code, thereby referencing each other. An example from the script is given below. ``` var fS = 0x1522c; var fT = 0x15cdc; var fU = 0x8b7aec; WshShell = WScript[cb](ck); var fY = 0xc1b1; var fZ = 0x2f3869; var g0 = 0x2d7f69; fY = fZ + fZ; fY = fZ + fY; fY = fY + fZ; ``` Not all dead code references other dead code. An example of dead code without references is given below. Additionally, this excerpt contains a redundant if-statement. Only when the code is altered, statically or in-memory, the condition could be met. ``` if ("JCqNE" === "nUZVy") { that = window; } else { var eV = 0xf2bd6; var eW = 0x169e; var eX = new ce(c6); var eY = 0xb66; var eZ = 0x11c1d; var f0 = "KT!Wd0rRAcucX*QYYufz tnIg;ORkuP1?c[op38[z?8ROFKHKLpH?dOB