Analysis and Report by Fabian Marquardt (@marqufabi)
Recently, Telekom Security CTI was made aware via trust groups in which we are engaged about a new malware campaign that is distributed via phishing emails. The malspam campaign used stolen email threads to lure victim users into clicking the contained hyperlink, which downloaded the malware.
Attention to this malware campaign was also fueled by a false attribution of one of the malware samples to Emotet. Even though this attribution later turned out as a false positive match of an automated detection rule, it caused the security research community to focus on this new campaign.
Initial analysis quickly revealed significant similarity to the DarkGate malware, based on the use of a similar initial infection routine (AutoIt scripts) and the observed C2 communication protocol, which matched past analyses of the same malware family. Further analysis confirmed this initial attribution, since embedded strings and contained functionality clearly identified the sample as part of the DarkGate malware family.
Further analysis of the sample revealed detailed insights on DarkGate’s functionality, specifically the builtin evasion techniques, the malware configuration and its features. Our results align with other recent publications about DarkGate. Furthermore, we provide an approach for configuration extraction that in our eyes is more robust and flexible than the existing ones.
We also collected and summarized available information about the actor who is apparently the sole developer of DarkGate. This actor advertised the DarkGate malware on several cybercrime forums and posted information about the features of the malware that match our analysis results. Furthermore, the actor posted several demo videos, which show details of the DarkGate backend panel.
The current spike in DarkGate malware activity is plausible given the fact that the developer of the malware has recently started to rent out the malware to a limited number of affiliates. Before that, the malware was only used privately by the developer. It can be expected that the introduction of the MaaS program will lead to more frequent malware campaigns involving DarkGate malware, meaning that the malware will likely pose as an ongoing threat in the months and years to come.
During the last weeks, Telekom Security observed an infection chain where the initial payload was delivered via an MSI installer file. Victims would get this file by clicking a link that is contained in a phishing message that they received. This link initially points to what is likely a traffic distribution system (TDS). If the requirements set by the attacker are met, the TDS will redirect the victim user to the final payload URL for the MSI download. When the user opens the downloaded MSI file, the DarkGate infection is triggered. The details of the infection process will be described later on.
Additionally, Telekom Security observed samples of a different campaign where the initial payload was delivered as a Visual Basic script. In this case, we do not know how exactly the initial payload was delivered to the victim user. The script, which is obfuscated and contains decoy/junk code, eventually invokes the curl
binary that comes pre-installed with Windows to download the AutoIt executable and script file from an attacker-controlled server. Thereafter, the infection chain works exactly as in the other campaign described in this document.
In the campaign where the initial payload was delivered as an MSI file, the file seems to be generated by the Software “MSI Wrapper” by www.exemsi.com, as can be seen from file Metadata:
Application Verifier x64 External Package - UNREGISTERED - Wrapped using MSI Wrapper from www.exemsi.com
For this infection chain, the initial payload is self-contained, meaning that all further payloads are embedded into the file and that no further payloads need to be pulled from external sources to complete the DarkGate infection. Specifically, the file contains an AutoIt executable and a corresponding script which is executed by the installer.
For the campaign where the initial payload was delivered as a VBS file, the sample contained a lot of garbage functions, which can be seen in the screenshot below. The real infection code is hidden in several strings, which are additionally obfuscated by inserting random junk sequences. After removing this obfuscation layer, the script logic is easily readable and rather simple. The script will spawn a cmd.exe
shell using ShellExecute
and use the curl
binary that is shipped by default in current Windows installations to download an AutoIt executable and a corresponding AutoIt script. Both files will be placed in a newly created folder on the C:\
drive. Notably, in at least one case we observed that the script was copying the curl
binary to the new folder and invoking it from there, which is most likely an attempt of the threat actor to evade existing EDR detection rules.
The AutoIt script is bundled with the .au3
file extension which is usually used for plain-text scripts. Instead it contains a pre-compiled script, which would typically use the .a3x
extension. We can see that it is a compiled script from the magic bytes AU3!EA06
, which for some reason are not at the start of the file, but follow a long sequence of base64-encoded data (we will come back to that below!).
The script can be decompiled using myAut2Exe (a pre-compiled binary can be found here) after renaming the file from .au3
to .a3x
. Analysis of the decompiled script shows that the sole purpose of the script is to execute a shellcode that is contained as a hex-encoded string:
The screenshot above only shows an excerpt of the complete sequence to create the shellcode string. This string is then decoded to binary data and written to a newly allocated memory area using the BinaryToString
and DllStructCreate
function calls. Finally, two commands are executed. These commands are obfuscated as hex-encoded strings. Decoding these strings reveals their purpose, which is to make the newly allocated memory area executable with VirtualProtect
and call the shellcode using CallWindowProc
:
DllCall("kernel32.dll", "BOOL", "VirtualProtect", "ptr", DllStructGetPtr($MFCKuCoyGW), "int", BinaryLen($MzrsVimcSw), "dword", 0x40, "dword*", $oldprotect)
DllCall("user32.dll", "lresult", "C"&chr(97)&"llWindowProc", "ptr", DllStructGetPtr($MFCKuCoyGW), "hwnd", 0, "uint", 0, "wparam", 0, "lparam", 0)
We will later on see that extraction and analysis of this shellcode is actually not required if we are only interested in the final DarkGate malware payload. However, in the following part we will quickly go over the remaining infection chain steps to give a brief overview of the complete process.
The shellcode embeds a PE file in the form of stack strings, as can be seen in the screenshot below (characteristic MZP
header at the start of the constructed string). The sole purpose of the shellcode is to load and eventually execute this PE file. We did not analyze all details of this process. Instead we emulated the shellcode to the point where the complete PE file was written to the stack and then dumped the corresponding memory section for further analysis.
The PE file extracted from the previous step is rather small (~15 KB). When executing it in our sandbox, we were presented with the following error message. Apparently, the file is some sort of loader that requires an additional resource to function properly.
When tracing the loader with a debugger, it became evident that it was trying to locate and read the .au3
script file described above. If the .au3
file was found, the program execution continued and it was visible that the loader accessed the base64-encoded sequences present in the script file to decode and execute yet another PE file.
As other researchers already described the specifics of this process are as follows: In the script file, there exist several base64 strings that are separated with a |
character. The loader will use the second of these strings to compute a single byte XOR key. The third base64 string contains the final payload, which is the DarkGate malware sample. After performing the base64 decoding, the loader applies the XOR key and a final NOT operation to reveal the decrypted PE file.
It should be noted that this process can easily be implemented by researchers to allow for static decryption of DarkGate malware samples that make use of this encryption process. Futhermore, due to the use of just a single byte XOR key, there is a very limited number of possible permutations of the encrypted PE file. This can be helpful for several reasons:
MZ
header.Obviously, such brute-force processes can also yield false positive results. Hence careful validation of the decrypted payloads is required.
With the steps described above we are able to unpack the main payload binary, which is the DarkGate malware itself. The sample is programmed and compiled using Delphi. When reverse engineering the sample, Ghidra initially was not able to reconstruct the used Delphi library functions and objects. Using the Dhrake project (which uses the output generated by Interactive Delphi Reconstructor (IDR)) greatly helped to make the decompiled sample more readable.
For reversing the sample, we had the following main objectives:
Our analysis of the unpacked/decrypted DarkGate malware sample revealed that beside some human-readable strings there exist a lot of base64-encoded strings. However, it was not possible to reveal any meaningful content by applying standard base64 decoding. As other researchers already pointed out the string encryption uses base64, but with a non-standard alphabet/table. The binary contains multiple functions that receive the encoded string and the alphabet as an input and will output the decoded string.
Notably, there are two different alphabets which are used for different purposes: One alphabet is used to decode different strings used throughout the binary, whereas the other alphabet is used solely for decoding of the sample configuration.
Our analysis of further DarkGate samples shows that at least one of the alphabet strings changes frequently. Hence, to provide a robust string and configuration decoder, we need to identify the used alphabet for each analyzed sample. We could of course do this by searching for the relevant functions in each binary and extracting the referenced strings, but this would be error-prone even if only small parts of the code or build process change.
So instead we can make use of the characteristics of the strings in question: These strings will always have the same length and contain each character of the base64 alphabet exactly once. Basically we are looking for strings that are different permutations of the same characters. We can easily implement this by first searching for potential candidates with a regular expression like [A-Za-z0-9+/=]{64}
and then checking which candidate contains each expected character exactly once, which we implemented by simply sorting all characters of the string and comparing the result to a given reference string. This is a robust approach that successfully identified the two custom alphabet strings for all samples that we have analyzed.
Once we have found a way to decode the encoded base64 strings, accessing and dumping the malware configuration is rather trivial: Configuration data is contained in two different strings. While one of the strings holds the addresses of the used C2 servers, the other one is a key-value list that contains all other configuration parameters and flags.
Each configuration value is given as a numeric key in the range of 0 to 20, e.g. the flag that controls startup/persistence behavior is set using either 1=No
or 1=Yes
. Through reverse engineering we identified the purpose of most of the used flags and values. Our configuration extractor performs a translation of all known flags to a more human-readable format and outputs the result in JSON format:
{
"anti_analysis": false,
"anti_debug": false,
"anti_vm": false,
"c2_ping_interval": 4,
"c2_port": 7891,
"c2_servers": [
"http://80.66.88.145"
],
"check_disk": true,
"check_ram": true,
"check_xeon": false,
"crypter_au3": true,
"crypter_dll": false,
"crypter_rawstub": false,
"crypto_key": "bIWRRCGvGiXOga",
"flag_14": 4,
"flag_18": true,
"flag_19": true,
"internal_mutex": "bbbGcB",
"min_disk": 50,
"min_ram": 4096,
"rootkit": true,
"startup_persistence": true
}
The meanings of each flag are as follows:
anti_analysis
(6) and anti_vm
(3) - Enable checks for the presence of typical hardware/driver identifiers that are used by common sandbox and VM solutions.anti_debug
(17) - Enables periodic checking of whether or not a debugger is attached to the process.c2_ping_interval
(16) - Sets the initial sleep interval that is used between two “pings” to the C2 server. This value is adaptive and can be changed through various functions of the C2 protocol.c2_port
(0) - Sets the port to use for C2 communication. Since the actual addresses of the C2 servers are stored in a different string, the same port is used for all configured servers.c2_servers
- Not part of the key-value list, but stored in a separate string. Multiple servers can be stored and are separated with the |
charactercheck_disk
(5) and check_ram
(8) - Enables checking of a minimum disk/RAM size. If enabled, the values of min_disk
(4) and min_ram
(7) will be used.check_xeon
(9) - Enables checking of the CPU to determine whether or not a Xeon processor is used.crypter_au3
(13), crypter_dll
(12) and crypter_rawstub
(11) - Configure which packing/crypting mechanism is used for the sample. These flags are used in quite a number of different functions (rootkit, persistence, self-update, …) to trigger the appropriate program logic that applies to each mechanism.crypto_key
(15) - Used in the C2 communication protocol to encrypt submitted data. We did not yet perform a detailed analysis of this.internal_mutex
(10) - Name of the mutex that is used apparently to synchronize different threads or processes of the DarkGate malware. We did not yet perform a detailed analysis of this.rootkit
(2) - Enables different mechanisms to inject the malware code into other processes using process hollowing techniques.startup_persistence
(1) - Enables persistence functions of the malware that can write a copy of the malware code to disk and create registry run keys.For flags where we do not yet know their purpose, we simply maintain the numerical value as flag_XX
in the configuration output.
Monitoring for specific combinations of configuration flags could be a potential approach to trace and identify different campaigns or affiliates of the malware. For example, one can see that the following configuration obtained from another DarkGate sample is quite different to the configuration above.
{
"anti_analysis": false,
"anti_debug": false,
"anti_vm": false,
"c2_ping_interval": 32,
"c2_port": 80,
"c2_servers": [
"http://a-1bcdn.com",
"http://avayacloud.com.global.prod.fastly.net",
"http://intranet.mcasavaya.com"
],
"check_disk": false,
"check_ram": false,
"check_xeon": false,
"crypter_au3": true,
"crypter_dll": false,
"crypter_rawstub": false,
"crypto_key": "nqSRmVfSEQwfgo",
"flag_14": 32,
"flag_18": true,
"flag_19": true,
"internal_mutex": "dEcCaG",
"min_disk": 100,
"min_ram": 4096,
"rootkit": true,
"startup_persistence": true
}
In the following paragraphs, we will summarize further findings of our analysis regarding the capabilities and TTPs of the DarkGate malware.
If enabled, the malware will write a copy of itself to disk and create a registry run key to persist execution between reboots.
For tasks such as the deletion of system restore points the malware can elevate to SYSTEM privileges.
As already described above, the sample contains multiple functions to evade typical analysis tools. When the corresponding features are enabled and the sample detects an environment that matches one of the checks, it will simply terminate the process.
Additionally, the malware will look for multiple well-known AV products and may alter its behavior depending on the result. The found AV product will also be communicated back to the C2 server.
The malware may also masquerade its presence and inject itself into legitimate Windows processes depending on the used configuration.
The malware contains multiple functions to steal passwords, cookies or other confidential data from the victim system. Targeted programs range from web browsers to email software and also other software such as Discord or FileZilla. Notably, the malware uses multiple legitimate freeware tools published by Nirsoft to extract confidential data.
The malware is able to query different data sources to obtain information about the operating system, the logged on user, the currently running programs and other things. This information will be sent to the C2 server and is available in the threat actor’s panel.
In addition to the mechanisms already described above, the malware may also collect arbitrary files from the victim system when requested through the C2 channel.
After some initialization functions, the malware proceeds to a function that we identify as the “C2 main loop”. In this loop, the malware periodically polls the C2 server for new instructions, executes the received commands, and finally sends back the results to the C2 server.
Each command is identified by a numerical value and the C2 main loop that we analyzed contains well over 100 different commands. We did not analyze thoroughly all of the contained commands and functions, but to give a rough overview most commands fall in one of the following categories:
Below one can see an excerpt of some exemplary functions triggered by different commands.
The developer provided several short videos where some of the backend panel functions are shown. Initially, the developer opened the “stub builder” through the menu button of the main window. Through several tabs, affiliates can set the different configuration options of the malware:
In addition, there exists an “LNK exploit builder” to disguise the true nature of the malicious content:
When the developer executed the built malware in their virtual machine, the victim system became visible in the panel:
The different commands that can be executed on the victim system are available through a context menu:
Finally, the developer provided a short demo of the integrated file manager to view directory contents on the victim system:
A user who goes by the handle RastaFarEye has been advertising DarkGate Loader on the xss.is
and exploit.in
cybercrime forums since June 16, 2023. The user seems to be the sole developer of the malware and states that more than 20.000 hours of work have been invested since 2017 to develop the project.
The actor is offering different pricing models (1 day = 1k USD, 1 month = 15k USD, 1 year = 100k USD) and claims that the price will likely be raised in the future. In addition, the actor seems to limit access to at most 10 affiliates (“slots”) to “keep this project private”.
The actor advertises DarkGate as the “ultimate tool for pentesters/redteamers” and that it has “features that you won’t find anywhere”. In addition, the actor proclaims many times that the tool is completely undetected by common AV products.
After initial publication, the actor frequently provided updates about bug fixes, new features and other changes.
The actor has provided the following contact addresses:
[email protected]
09B950550CAD95899AC17C0B1384CD55C9BD81396B19EFFE2E80839D641D3221860ADEA89733
https://t.me/evtokens
The actor posted on the xss.is
and exploit.in
cybercrime forums mainly in English and also developed the panel and malware in English language. However, from some observed grammatical errors it can be assumed that English is not the actor’s native language.
When the actor received questions in Russian language, they were able to provide answers in Russian language, too. The actor also used cyrillic alphabet for their username Растафарай on Telegram, which can be transliterated to Rastafarai.
Apart from many English strings, the DarkGate samples we analyzed also contain some Spanish strings, such as for example administrador de tareas (task manager). In addition, demo videos posted by the actor show that the system locale and keyboard layout is set to Spanish. The videos also show that the victim VM maintained by the actor connects to the panel with an IP address from Spain. However, this address likely belongs to a VPN or anonymization service.
149.248.0.82
179.60.149.3
185.143.223.64
185.8.106.231
45.89.65.198
5.34.178.21
80.66.88.145
89.248.193.66
a-1bcdn.com
avayacloud.com.global.prod.fastly.net
drkgatevservicceoffice.net
intranet.mcasavaya.com
onlysportsfitnessam.com
reactervnamnat.com
sanibroadbandcommunicton.duckdns.org
xfirecovery.pro
The analysis results of this report are mainly based on the following sample. Results were confirmed by checking other samples found via hunting queries.
SHA256 6e068b9dcd8df03fd6456faeb4293c036b91a130a18f86a945c8964a576c1c70 (Link to MalwareBazaar)