Zscaler Blog
Get the latest Zscaler blog updates in your inbox
SubscribeA Brief History of SmokeLoader, Part 1
Introduction
This is Part 1 in our series on the history of SmokeLoader. Go to Part 2.
In May 2024, Zscaler ThreatLabz technical analysis of SmokeLoader supported an international law enforcement action known as Operation Endgame, which remotely disinfected tens of thousands of infections. In the process of providing assistance to law enforcement for the operation, ThreatLabz has documented SmokeLoader for nearly all known versions.
In this two-part blog series, we explore the evolution of SmokeLoader. Initially used as a first-stage downloader to deploy other malware families, SmokeLoader has evolved to include its own framework and expand its capabilities with information stealing functionalities. Over the years, the malware has undergone significant development and improvements, with the latest known version appearing in 2022. This blog provides an overview of SmokeLoader’s origins and initial transformation into a modular operation.
Key Takeaways
- SmokeLoader is a modular malware family that was first advertised on criminal forums in 2011.
- Smoke’s primary function is to serve as a downloader and execute second stage malware.
- SmokeLoader possesses the capability to download a range of additional modules that enhance the malware's capabilities, enabling it to perform tasks such as stealing data, launching distributed denial of service attacks, and mining cryptocurrency.
- SmokeLoader detects analysis environments, generates fake network traffic, and obfuscates code to evade detection and hinder analysis.
- SmokeLoader has undergone extensive evolution over the years, with new features, alongside improved encryption, compression, and hash algorithms.
Timeline
The figure below is a comprehensive timeline of SmokeLoader’s evolution from 2011 to the present.
![Figure 1: A timeline of SmokeLoader’s evolution from 2011 to 2022.](/cdn-cgi/image/format=auto/sites/default/files/images/blogs/figure_1_smokeloader1.png)
Figure 1: A timeline of SmokeLoader’s evolution from 2011 to 2022.
2011-2013: Prehistoric
The first SmokeLoader samples we analyzed date back to 2011. These samples display notable differences and are more rudimentary compared to subsequent iterations. We refer to the earliest SmokeLoader samples as prehistoric because they do not contain a version number.
These early versions of SmokeLoader include an initial module that serves as the foundation for establishing initial communication with the command-and-control (C2) server. The malware achieves this through the utilization of two embedded shellcodes that are injected into two newly created instances of svchost.exe
. During this prehistoric period, the code was modified several times, with some samples performing process injection by creating shared sections (using ZwCreateSection
and ZwMapViewOfSection
) and resuming the main process thread (using ZwResumeThread
) to execute the injected code.
Another sample dating to 2012 uses an Asynchronous Procedure Calls (APC) queue technique to inject SmokeLoader into the hollowed svchost.exe
processes. The figure below shows SmokeLoader’s process of building the shellcode and injecting it into svchost.exe
using the APC queue injection technique.
![Figure 2: Early version of SmokeLoader building and injecting shellcode into svchost.exe.](/cdn-cgi/image/format=auto/sites/default/files/images/blogs/figure_2_smokeloader1.png)
Figure 2: Early version of SmokeLoader building and injecting shellcode into svchost.exe
.
One of the shellcodes sends the getload
(with the argument login
) command to the C2 server, while the other shellcode queries the C2 server with the getgrab
command.
The figure below shows the svchost.exe
shellcodes for the SmokeLoader sample under analysis.
![Figure 3: The svchost.exe shellcodes for a Smokeloader sample circa 2012.](/cdn-cgi/image/format=auto/sites/default/files/images/blogs/figure_3_smokeloader1_0.png)
Figure 3: The svchost.exe
shellcodes for a Smokeloader sample circa 2012.
Using the getload
command, the bot registers itself within the C2 server using HTTP GET requests. Example network traffic from this early Smoke version is shown below.
![Figure 4: Example C2 requests from the SmokeLoader version 2012.](/cdn-cgi/image/format=auto/sites/default/files/images/blogs/figure_4_smokeloader1_0.png)
Figure 4: Example C2 requests from the SmokeLoader version 2012.
SmokeLoader sends two parameters to the C2 server using the getload
command as shown in the table below:
Argument | Description |
---|---|
| This specifies the bot ID, which is calculated as a simple MD5 hash of the victim’s computer name. |
| This specifies the hardcoded seller ID (a.k.a., affiliate ID), which varies per sample (e.g., |
Table 1: SmokeLoader 2012 parameters for the getload
command.
In modern versions, SmokeLoader still continues to send a bot ID and seller ID to register itself with the C2 server. Once registered, the server responds to the getload
command with a payload that the malware writes to disk and executes.
In addition, the getgrab
command can download an additional SmokeLoader grabber module. In this case, the data returned by the C2 server is encrypted with a simple XOR algorithm. Once decrypted, the Portable Executable (PE) file is mapped directly in the current process context by the shellcode.
Information stealer plugins
The source code for the SmokeLoader 2012 panel was leaked. The code sample below shows how the panel manages the various commands it supports.
if ($command == "getgrab") {
getmodule("./mods/grab");
exit;
} elseif ($command == "getproxy") {
getmodule("./mods/socks");
exit;
} elseif ($command == "getspoof") {
getmodule("./mods/hosts");
exit;
} elseif ($command == "getcmdshell") {
getmodule("./mods/shell");
exit;
} elseif ($command == "getload" && isset($cmd["doubles"])) {
…
} elseif ($command == "getload" && isset($cmd["final"])) {
…
} elseif ($command == "getload" && isset($cmd["personal"])) {
…
The getgrab
command retrieves the content of the file ./mods/grab
on the C2 server. The first 4 bytes of this file correspond to the XOR key used for decrypting the remaining content. The grab
executable is a fully-featured information stealer module that is capable of stealing email, FTP, and email passwords.
Unlike the primary SmokeLoader communication channel which uses HTTP GET requests, the communication between the grabber and the C2 is conducted through HTTP POST queries.
Within the mods
folder of the leaked panel, there is also a ./mods/shell
file that implements a simple remote shell. The leaked panel's source code references other modules including those mentioned by the getproxy
and getspoof
commands.
First anti-analysis techniques
SmokeLoader is notorious for employing various anti-analysis techniques, which have been incrementally improved with each new version. This section examines the initial anti-analysis techniques observed in the 2012 version of SmokeLoader.
Instead of storing the names of exported functions, the malware utilizes a hash-based approach to locate the addresses of the required APIs. In this version, the algorithm used to hash the API names is relatively simple, as shown in the Python code sample below.
def calc_hash_smoke2012(apiname):
hash = 0
for byte in apiname:
hash = (hash << 8 | hash >> (32 - 8)) & 0xFFFFFFFF
hash = byte ^ hash
return hash
The strings used by the malware’s first stage are encrypted. Each encrypted string in the binary is structured as follows: the initial 4 bytes correspond to an XOR key, which is then followed by the encrypted data.
The Python implementation of the algorithm to decrypt the strings is shown in the code sample below.
def smoke2012_string_decrypt(data, key):
aligned = data
unaligned = b''
unaligned_dec = b''
if n_unaligned := len(data) % 4:
aligned = data[0:-n_unaligned]
unaligned = data[-n_unaligned:]
aligned_dec = xor(aligned, key)
unaligned_dec = xor(unaligned, key[0:1])
return aligned_dec + unaligned_dec
In this version, the Smoke C2 URLs are stored among the list of encrypted strings.
2014: Ancient Modularizations
The following section covers new features and modifications to SmokeLoader version 2014, which include a multi-stage loading process, an updated algorithm for generating the bot ID, a separate encrypted C2 list, and more.
During the analysis of a sample dating back to 2014, we discovered the introduction of the string s2k14
that is used as the name of a file mapping. We believe s2k14
is a reference to SmokeLoader version 2014. The figure below shows this string referenced in the code.
![Figure 5: SmokeLoader version 2014 string for a file mapping name called s2k14.](/cdn-cgi/image/format=auto/sites/default/files/images/blogs/figure_5_smokelaoder1.png)
Figure 5: SmokeLoader version 2014 string for a file mapping name called s2k14
.
One of the most interesting features in this version of SmokeLoader is the malware was split into several loading stages. The introduction of a stager component marked a significant change that became standard in all subsequent versions. Each version since 2014 consists of a stager, a main module, and plugins that implement additional features.
In SmokeLoader version 2014, the ./mods/
folder in the panel includes a ./mods/plugins
file that combines multiple plugins into a single file. The prior ./mods/grab
information stealing module from previous SmokeLoader versions was split into multiple stealing modules like an FTP/mail stealer module, browser stealer module, and keylogger module, and then packaged in this plugins
file. This modification to the plugins persists from this version onward until the most recent version of SmokeLoader.
aPLib stager
The stager introduced in SmokeLoader version 2014 is quite simple. The stager performs the following actions:
- Decrypts a section of data using a single byte XOR key.
- Decompresses the data using aPLib.
- Maps the main module in a buffer allocated in the same process context.
- Executes some simple anti-analysis measures by checking the Process Environment Block (PEB) such as the
BeingDebugged
andNtGlobalFlags
fields.
Then, the stager transfers execution to the main module, creates an instance of svchost.exe
, and injects SmokeLoader into this newly created svchost.exe
process using APC queue code injection.
The figure below shows how the 2014 version of the SmokeLoader aPLib stager works.
![Figure 6: SmokeLoader version 2014 code unpacking and injecting into svchost.exe.](/cdn-cgi/image/format=auto/sites/default/files/images/blogs/figure_6_smokeloader1.png)
Figure 6: SmokeLoader version 2014 code unpacking and injecting into svchost.exe
.
SmokeLoader’s stager underwent significant evolution in subsequent versions, incorporating advanced obfuscation techniques and additional anti-analysis measures. Nevertheless, even in this version, we can observe the presence of rudimentary obfuscation tricks.
For instance, SmokeLoader employs non-polymorphic decryption loops to unravel layers of XOR encryption for functions that are invoked, as shown in the figure below.
![Figure 7: SmokeLoader version 2014 stager function decryption.](/cdn-cgi/image/format=auto/sites/default/files/images/blogs/figure_7_smokeloader1_0.png)
Figure 7: SmokeLoader version 2014 stager function decryption.
Persistence
The SmokeLoader seller has provided threat actors with an option to build a sample with (or without) persistence. SmokeLoader’s approach to achieve persistence on the victim's system has undergone numerous changes over time. In earlier versions (2011-2017), SmokeLoader would leverage common Run registry keys and create a startup shortcut as a fallback option (if setting the registry values failed). In addition, SmokeLoader would establish two dedicated threads responsible for safeguarding the modified registry keys.
Bot ID
In the initial version of SmokeLoader, dating from approximately 2011 to 2012, we observed that the bot ID was generated by taking a simple MD5 hash of the victim machine's computer name. Over time, the algorithm to generate the bot ID has undergone slight modifications. Notably, in version 2014, SmokeLoader employed a CRC32 and XOR based algorithm.
Starting from 2014, all versions of SmokeLoader calculate the ID using both the computer name and the volume information, as shown in the figure below.
![Figure 8: SmokeLoader version 2014 bot ID generation.](/cdn-cgi/image/format=auto/sites/default/files/images/blogs/figure_8_smokeloader1.png)
Figure 8: SmokeLoader version 2014 bot ID generation.
Anti-analysis tricks and plain text strings
Interestingly, SmokeLoader version 2014’s main module stored the malware’s strings in plaintext as shown in the figure below. This is a departure from the initial version where the strings were encrypted.
Figure 9: SmokeLoader version 2014 plaintext strings.
This is the first version of the malware that searches for sbiedll
, dbghelp
, qemu
, virtual
, vmware
, and xen
strings to check for libraries and processes related to malware analysis environments. If an analysis environment is detected, SmokeLoader terminates itself to evade detection.
Encrypted C2s
The algorithm used to decrypt the list of encrypted C2s is one of the SmokeLoader components that has undergone the most changes across versions.
While the strings in the main module of SmokeLoader version 2014 are stored in plaintext, the list of C2 servers is encrypted. To decrypt the list, a custom XOR-based decryption algorithm is employed. The code contains a table of pointers, with each pointer referencing a string that is prepended by a byte that is used as an XOR key, which is followed by three unused bytes. The next byte is the size of the encrypted C2 URL and the remaining bytes are the encrypted C2 URL. The Python code below demonstrates the C2 decryption algorithm used in SmokeLoader version 2014.
def smoke2014_c2_xor_decrypt(enc_data):
key = enc_data[0]
size = enc_data[4]
enc = enc_data[5:]
dec = b''
for i in range(0, len(enc)-1, 2):
dec += (0xff&((enc[i] ^ key) -
(enc[i+1] ^ key))).to_bytes(1, 'little')
return dec
Anti-C2 patching mechanism
An interesting addition to SmokeLoader version 2014 is the implementation of what appears to be a simple copy-protection mechanism as shown in the figure below.
![Figure 10: Simple copy-protection mechanism implemented in SmokeLoader version 2014 version.](/cdn-cgi/image/format=auto/sites/default/files/images/blogs/figure_10_smokeloader1.png)
Figure 10: Simple copy-protection mechanism implemented in SmokeLoader version 2014 version.
The malware calculates the CRC32 value of the C2 URL string and compares it with a predefined expected value at various points in the code. This mechanism is likely designed to prevent other hackers from creating a builder that patches samples with new C2s, and therefore reduce potential sales of SmokeLoader.
Communication
The communication protocol for SmokeLoader version 2014 is similar to prior versions. SmokeLoader uses a simple text-based protocol that is encrypted and sent to a C2 server. The syntax for the protocol is the following:
arg1=value1&arg2=value2…&argN=valueN
SmokeLoader’s version 2014 panel recognizes the following arguments:
Argument | Description |
---|---|
| The C2 panel accepts a set of commands. Depending on the specified command additional arguments must be specified. |
| This argument is the bot ID and its length must be 40 bytes. |
| Additional information given with some commands. |
| Operating system version. |
| Victim’s Windows operating system architecture. |
| Mainly used together with the |
| Used in different commands for different purposes. For example, to ask for an update or to indicate that the update was successfully executed. |
| Used together with the |
| Process name included with the |
| Additional flag that may be sent with the |
| Additional flag that may be sent with the |
| Additional flag that may be sent with the |
| If the |
| Used together with the |
| If a file is submitted, the |
Table 2: SmokeLoader version 2014 network protocol.
The panel is able to handle the following commands (i.e., the command name specified in the cmd
argument):
Command (cmd) | Description |
---|---|
*with additional arguments | One of the main commands and differs depending on specified arguments:
|
*without arguments | If this command is received without arguments, it could be interpreted as a
|
| Used by the bot to inform the server that it has enabled the SOCKS proxy feature. The server will attempt to validate the bot proxy is active by connecting to the bot’s IP address on the specified port. |
| Confirms that the hosts specified in the |
| The bot submits results from executed shell commands to the server. The shell argument contains the results. |
| Submits the results from the form grabber plugin to the server. The |
| Submits the results from the ftp grabber plugin to the server. The |
| Submits stolen information to the server. The argument data contains the stolen information. |
| Submits information about installed security products to the server. The information is submitted in the |
| If one of the processes configured with the rules in the |
| Confirms the DDoS attack configured with the |
| Submits the information captured by the keylogger plugin to the server. The grab argument must contain a base64 encoded string with captured data. |
| If the HTTP query is application/bin, and the command is |
Table 3: The commands supported by SmokeLoader’s 2014 C2 server.
SmokeLoader version 2012 sent commands and arguments as plaintext using HTTP GET requests. In version 2014, the network protocol was updated to send the command and argument data via HTTP POST requests. The POST request body consists of an initial DWORD
containing the size of the data, followed by a DWORD
that functions as an RC4 key required to decrypt the remaining data.
To Be Continued
In our journey through Part 1 of this series, we explored the early versions of SmokeLoader, from its initial rudimentary framework to its adoption of a modular structure and encrypted network protocol. In Part 2, we dive deeper into SmokeLoader’s progression toward a more sophisticated, modular malware family with advanced anti-analysis techniques.
Zscaler Coverage
![Zscaler sandbox coverage](/cdn-cgi/image/format=auto/sites/default/files/images/blogs/smokeloader_coverage.png)
In addition to sandbox detections, Zscaler’s multilayered cloud security platform detects indicators related to SmokeLoader at various levels with the following threat names:
Was this post useful?
![dots pattern](/_next/image?url=%2Fassets%2Fimages%2Fcta_bgpattern.png&w=1920&q=75)
Get the latest Zscaler blog updates in your inbox
![](/_next/image?url=%2Fassets%2Fimages%2Floading.webp&w=256&q=75)
By submitting the form, you are agreeing to our privacy policy.