New PhantomLoader Malware Distributes SSLoad: Technical Analysis
Editor’s note: The current article is authored by Mohamed Talaat, a cybersecurity researcher and malware analyst. You can find Mohamed on X and LinkedIn.
In this malware analysis report, we take an in-depth look at how an undocumented loader called PhantomLoader has been used by attackers to distribute a rust-based malware known as SSLoad.
Overview
The PhantomLoader usually masquerades as a legitimate 32-bit DLL written in C/C++ for an antivirus software called 360 Security Total.
However, in this case, it was found disguising itself as “PatchUp.exe,” which is still a legitimate module of 360 Total Security. This loader has been used in recent attacks to deliver a new rust-based malware called SSLoad.
What makes PhantomLoader unique is that it was added to be part of a legitimate DLL or executable of a well-known software by binary patching the DLL or executable and adding a self-modifying technique. The latter decrypts an embedded code stub, which then decrypts and loads “SSLoad” into memory.
PatchUp.exe and legitimate module of 360 Total Security
Technical analysis
After analyzing the SSLoad sample in ANY.RUN’s sandbox, we observed that one distribution method for this malware involves phishing emails containing malicious Office documents. These documents initiate the infection chain.
The analysis session shows how the drop and execution of PhantomLoader occurs, after which it decrypts and runs SSLoad.
Execution of Malicious Word document
After executing the malicious Word document, it became clear that a new process, “app.com,” was launched by “WINWORD.exe,” indicating that an embedded malicious macro had been executed. This resulted in the creation of the suspicious process.
To better understand the infection chain, the macro was extracted and analyzed further.
Execution of Decoded XML String
In the ANY.RUN Script Tracer, it was observed that the malware loads an encoded XML string, which appears to be obfuscated using JScript. This encoding is used to disguise the malicious intent, making it more difficult to detect.
Once loaded, the XML string is executed, triggering the next stage in the malware’s infection process.
Upon further investigation of the document’s macros, an Autoclose macro was found that reads an XML string from an XML file named “UserForm1.”
After analyzing the referenced form file, it became clear that the loaded XML string is encoded in JavaScript. This encoding serves as a protection measure designed by Microsoft to prevent unauthorized copying or alteration of VBScript or JavaScript code.
Using CyberChef, the JavaScript was decoded, revealing the underlying code used by the malware to continue the infection process. This provides clear insights into the next steps of the attack.
The JavaScript code decodes the next stage, PhantomLoader, using base64. It then places the decoded file in the user’s %TEMP% directory with the name “app.com” and starts it.
First Loader: PhantomLoader
PhantomLoader disguises itself as a legitimate DLL module for the antivirus software 360 Total Security. This tactic allows it to remain undetected by both the system and users.
This is one of the rare cases where the malicious code runs before the main function is reached. This strongly suggests that the legitimate DLL module has been modified. A malicious routine is inserted before the main function, along with an encrypted stub.
The malicious routine embedded within the DLL module first calculates the address of the encrypted code stub, which is hidden within the file. It then decrypts this stub using a XOR operation with a hardcoded key.
The encrypted code is located in the .text section of the DLL. It was disassembled by IDA, but the disassembled output appeared nonsensical, indicating that the code is indeed encrypted.
To further analyze the encrypted code in IDA, an IDAPython script was created to decrypt and patch the code in place.
The decrypted code stub begins by fetching the base address of “kernel32”, a core Windows system DLL that provides essential system functions. It then uses this base address to resolve the following function addresses by hash:
VirtualAlloc – Responsible for memory allocation.
LoadLibraryA – Loads libraries (DLLs) into memory.
GetProcAddress – Retrieves the address of functions or variables from the loaded DLLs.
The resolved functions are then used to load the decrypted next-stage loader, SSLoad, directly into memory.
Using the same key as before, it XOR decrypts the encrypted SSLoad, which is stored in the “.rsrc” section of the DLL. This method keeps the actual payload concealed within the DLL until it’s ready to be executed.
Interestingly, it doesn’t use the common API sequence FindResourceA and LockResource to locate and extract the encrypted resource. Instead, an offset to the encrypted resource is passed to the function that points to the decrypted stub.
Second Loader: SSLoad
The final payload decrypted by PhantomLoader is SSLoad, a rust-based loader known for its evasive and stealthy nature.
It employs various anti-analysis techniques, including anti-debugging and anti-emulation methods. SSLoad also uses multiple layers of string decryption to conceal its Command-and-Control (C2) URLs and IP addresses, making detection and analysis more challenging.
When executed, SSLoad begins by creating a mutex object with a hardcoded name. This object ensures that only one instance of SSLoad can run on the host at any given time. This is a common technique used to avoid resource conflicts or redundant infections on a single host.
It uses a common anti-debugging technique by inspecting the Process Environment Block (PEB), specifically looking for the “BeingDebugged” flag. This flag is set to indicate whether the process is currently being debugged.
It is interesting to note that it uses an anti-emulation technique that was observed for the first time being used by Raspberry Robin. The technique involves attempting to retrieve the address of a function exported by kernel32 called “MpVmp32Entry”.
However, when inspecting the exports of kernel32 for this function name, it cannot be found. This is because only modified versions of kernel32.dll used by emulators export that function.
The developers of SSLoad may have either intentionally or accidentally failed to properly decrypt the library name Kernel32.dll. This would result in the DLL base address not being retrieved to check for the target export. As a result, the implemented trick might fail even on an emulated system.
One of the system artifacts to check for is the presence of a directory with a randomly generated name under %APPDATA%/Microsoft. This directory name is generated at runtime using the function SystemFunction036 from the Advapi32.dll library, which is often used for cryptographic functions.
After completing its checks and decrypting the C2 URLs and IP addresses, SSLoad moves forward with fingerprinting the host it’s running on. This process involves collecting various details about the system.
This data is then stored in a JSON object, which will be sent later via POST request to the Command-and-Control (C2) server for further communication.
The fingerprinted data collected by SSLoad includes crucial system information like the OS version, username, hostname, architecture (arch), public IP address, and other system-specific details.
The data will be sent to the server in preparation of C2 communication process.
If the connection was successful, the C2 server will return back response with a JSON object containing a “key” and an “ID”.
The returned key is a base64 encoded RC4 key that will be used to secure further communication between the host and C2 server.
In its turn, the ID is a unique identifier generated on the C2 side that will be used by the infected host to authenticate and identify itself to the C2 server.
In the later HTTP POST requests, no data is sent to the C2 server. Instead, the infected host sends empty HTTP POST requests that contain only the server-side generated “ID”.
Once SSLoad establishes a connection with the C2 server, it enters a beaconing loop, regularly checking in with the server for further instructions or tasks to execute.
It seems that for the current sample the server hasn’t returned any tasks to the infected host. However, in another SSLoad analysis sample, the server did return a response containing an “ID” and a “Job”.
The “ID” returned by the server identifies a task for the infected host.
The encoded structure contains two fields: “command” and “arguments.” Fishbein explained that when the “command” field is set to “exe” and the “arguments” field contains a URL, it indicates that the server is instructing the infected host to download and execute the next-stage malware payload from the given URL.
Indicators of Compromise (IOC)
File Paths and Names
Incident_Harassment.doc
%TEMP%/app.com
File Hashes (MD5)
EC7E26A81B6002C53854A1769AD427A6
bd3231011448b2d6a335032d11c12cad
E01DDD72BC81781FE86A68D3AD045548
Related Domains, URLs, and IP addresses
http://85[.]239[.]53[.]219
YARA Rule
rule crime_phantom_loader_dll
{
meta:
description = “Detects PhantomLoader C/C++ DLL”
author = “Mohamed Talaat”
date = “2024-17-8”
type = “crimeware”
hash1 = “BD3231011448B2D6A335032D11C12CAD”
hash2 = “CA303668B5420C022EF9C78CE1F2BFB7”
hash3 = “1D8D71B4A0870C0DFA3468470FB28A28”
hash4 = “B28A478EB5B99EFCDC7CAF428BFFB89A”
strings:
$pdb_str = “C:\vmagent_new\bin\joblist” ascii
$iobit_str = “IUForceDelete123” ascii wide
$mov_5F5E100 = { ( BF | 68 | C7 45 ?? ) 00 E1 F5 05 }
$payload_size = { ( D0 | 6C ) 07 00 00 }
$call_payload = { FF 55 ?? 68 [4] FF [-] 33 C0 ?? 8B E5 5D C3 }
condition:
(uint16(0) == 0x5A4D) and
all of ($mov_5F5E100, $payload_size, $call_payload) and
any of ($pdb_str, $iobit_str)
}
The post New PhantomLoader Malware Distributes SSLoad: Technical Analysis appeared first on ANY.RUN’s Cybersecurity Blog.
ANY.RUN’s Cybersecurity Blog – Read More