[Guest Diary] Dissecting DarkGate: Modular Malware Delivery and Persistence as a Service.

Published: 2024-02-29
Last Updated: 2024-02-29 01:41:25 UTC
by John Moutos, SANS BACS Student (Version: 1)
1 comment(s)

[This is a Guest Diary by John Moutos, an ISC intern as part of the SANS.edu Bachelor's Degree in Applied Cybersecurity (BACS) program [1].


From a handful of malware analysis communities I participate in, it is not uncommon for new or interesting samples to be shared, and for them to capture the attention of several members, myself included. In this case, what appeared to be a routine phishing PDF, led to the delivery of a much more suspicious MSI, signed with a valid code signing certificate, and with a surprisingly low signature-based detection rate on VirusTotal [2] (at time of analysis) due to use of several layered stages.


Modern malware utilizing multiple layers of abstraction to avoid detection or response is not a new concept, and as a result of this continuous effort, automated malware triage systems and sandboxes have become crucial in responding to new or heavily protected samples, where static analysis methods have failed, or heuristic analysis checks have come back clean. Attackers are wise to this, and often use legitimate file formats outside of the PE family, or protect their final stage payload with multiple layers to avoid being detected through static analysis, and subsequently profiled through dynamic analysis or with the aid of a sandbox / automated triage system.


The following sample not only fit the profile previously mentioned, but was also taking advantage of a presumably stolen or fraudulent code signing certificate to pass reputation checks.

At a first glance, the downloaded PDF appears normal and is of fairly small size.

Figure 1: Initial PDF Details

Opening the PDF with any suitable viewer, we can see an attempt to convince unknowing users to download a file, promising to resolve the fake load error.

Figure 2: Initial PDF Displayed

The “Open” button points to a wrapped doubleclick[.]net AD URL (“hxxps[://]adclick[.]g[.]doubleclick[.]net//pcs/click?f1587wub8-24-TzRtAOnedriveBskd&&adurl=//selectwendormo9tres[.]com?utm_content=AAhqplxaJo&session_id=3VHLBRuVfwDKTPWgylgR&id=b2WBu&filter=FSBMsIgzmQ-pIvZl&lang=zh&locale=US”), which when followed arrives at “hxxp[://]95[.]164[.]63[.]54/documents/build-x64[.]zip/build-x64[.]msi”. It is with this MSI where the initial infection chain starts, assuming the unsuspecting user proceeds to run the MSI after download.

Inspecting the MSI, it does not appear to be artificially inflated with junk data as per the file size, and as a bonus it has a valid digital signature from a genuine certificate issued to “Inoellact EloubantTech Optimization Information Co., Ltd.” from GlobalSign [3].

Figure 3: Downloaded MSI Details

Figure 4: MSI Signature & Certificate Details

To extract the content from the MSI, there are a plethora of tools that can be used. Universal Extractor [4], 7-Zip [5], and the built-in extractor feature in the multi-purpose analysis tool “Detect It Easy” (DIE) [6] will handle the job without issue.

Figure 5: MSI Opened in DIE

With the content of the MSI extracted, there are two important files to note, the first named “Binary.bz.WrappedSetupProgram”, which is the embedded cabinet (CAB) file, and the second named “Binary.bz.CustomActionDll” which is an embedded DLL.

Figure 6: Extracted Cabinet File in DIE

Figure 7: Extracted DLL File in DIE

The DLL only serves to assist in the deployment of the cabinet file during the MSI installation process, but it should be noted it also has several other execution paths, corresponding to different installer modes and the respective entry point followed.

Figure 8: Extracted DLL Entry points

Returning back to the extracted cabinet (CAB) file, we can simply open it with 7-Zip to view the contents.

Figure 9: Cabinet File Contents

The file “iTunesHelper.exe” has a valid signature from Apple, whereas the “sqlite3.dll” and “CoreFoundation.dll” files are unsigned. These files will presumably be loaded (“CoreFoundation.dll” is listed in the Import Table) when “iTunesHelper.exe” is launched, so I will focus on these files.

Due to how Windows searches for and loads DLLs [7], the “iTunesHelper” application will load any DLL named “CoreFoundation”. Windows first searches the directory where the application launched from, and in this case, it would find a match and load the DLL. Windows then falls back to the System32 directory, then the System directory, the Windows directory, the current working directory, all directories in the system PATH environment variable and lastly all directories in the user PATH environment variable.

Figure 10: iTunesHelper EXE Signature

Figure 11: iTunesHelper EXE Import Table

Upon closer inspection at the “sqlite3” DLL, it does not appear to be a valid PE (Portable Executable) file, but it will be revisited.

Figure 12: sqlite3 File Junk Data

Inspecting the “CoreFoundation” DLL with a disassembler such as IDA [8], Ghidra [9], or Binary Ninja [10], and going to the main entry point, we can trace the execution flow up to where a function named “CFAbsoluteTimeAddGregorianUnits” is called, which when followed checks if the process it has been loaded into is running from the path “c:\\debug”, followed by a message box popup with the string “debug dll start”. This functionality is unrelated to the malicious behavior, but is a good indication the file has been tampered with, along with the lack of a valid signature.

Figure 13: CoreFoundation DLL Entry Point

Figure 14: CoreFoundation DLL Debug Directory Check

Following the “CFAbsoluteTimeAddGregorianUnits” execution flow further down, we can find a reference to the bundled “sqlite3" DLL.

Figure 15: sqlite3 File Reference in CoreFoundation DLL

Switching back to the “sqlite3” DLL, using DIE to view the strings in the file, there appears to be an AutoIt compiled script header value denoted by the characters “AU3!EA06”. Opening the the file with a hex editor such as HxD [11] or DIE (DIE has a built-in one), we can confirm the presence of the AutoIt [12] compiled script header. This will be revisited shortly.

Figure 16: AutoIt Compiled Script Header in sqlite3 File

Switching gears back to the “CoreFoundation” DLL, following the references to the “sqlite3” DLL, we can find a block of code that resembles a XOR decryption routine. Looking for cross-references to this decryption code leads to more references to the “sqlite3” file, along with a familiar string. The string “VzXLKSZE” is scattered throughout the “sqlite3” file, and fills up the majority of the space within the file. Between this, and the reference to the XOR decryption routine, we can assume this may be the key used to decrypt the “sqite3” file.

Figure 17: sqlite3 File and Key References in CoreFoundation DLL

Figure 18: XOR Key in sqlite3 File

Loading “sqlite3” into a tool like CyberChef [13], the XOR operation can be used, and when provided with the discovered key, the file content is decrypted, and appears to have a valid PE header, denoted by the MZ characters at the beginning.

Figure 19: XOR Decrypting sqlite3 File

After saving the decrypted content (“sqlite3decrypted.dll”) to disk, we can load it into DIE to verify it does resemble a valid PE file.

Figure 20: Decrypted sqlite3 File in DIE

Dropping the decrypted binary (“sqlite3decrypted.dll”) into a disassembler and following execution flow from the entry point, we can see the next stage takes the form of the AutoIt compiled script discovered before, and this DLL serves to drop the script, the actual AutoIt executable, and a “test.txt“ file into the “c:\temp” directory, before executing the script with AutoIt.

Figure 21: Decrypted sqlite3 File Pseudocode

To extract the compiled script, we can revisit the original encrypted “sqlite3.dll” file, and look for the delimiter used to separate the script content from the rest of the binary. It should also be noted that the delimiter string “delimitador” can be found in the “sqlite3decrypted.dll” file.

Figure 22: Delimiter String in Decrypted sqlite3 File

Knowing the string delimiter to look for, we can carve out the AutoIt compiled script from the original “sqlite3” file. A hex editor can be used to do this easily.

Figure 23: Start Delimiter in Original sqlite3 File

Figure 24: End Delimiter in Original sqlite3 File

The AutoIt script, now saved to disk, unfortunately is unusable while still compiled, and must be decompiled with a tool such as myAutToExe [14].

Figure 25: Compiled AutoIt Script Extracted

With the script decompiled, we can see it is obfuscated using character substitution, which we must reverse before we can proceed.

Figure 26: Decompiled AutoIt Script Obfuscation

The AutoIt “STRINGSPLIT” function [15] is being called on the content of test.txt, read using “FILEREAD” [16], with a blank delimiter, and with mode 2, which sets the starting count of the array to 0 instead of 1.

Figure 27: test.txt File Content

For example; $A[0] would be the character “(”, and $A[1] would be the character “n”.

Once the character substitution is reversed and the script is now readable, we can see it construct shellcode from the content above and attempt to load and execute it in memory. It additionally checks if any Sophos products are installed, and will switch execution flows if this check fails.

The VirtualProtect Windows API [17] is used to modify the allocated memory region protection, so the shellcode can be copied and executed using the EnumWindows Windows API [18].

Figure 28: AutoIt Script Content

Following the reference to the shellcode data stored across the variable named “$BZXRGFO”, we can see that it uses the AutoIt function BinaryToString [19], which converts a given value from binary representation to string form.

Knowing this we can extract the embedded shellcode blob and hex decode it. Once again, CyberChef has a hex decode operation that can handle this task for us.

Figure 29: Decoding the Included Shellcode

After saving the decoded shellcode data as a file, if we open it with a hex editor, we can see the start of a valid PE header after a large chunk of garbage data. To properly disassemble the file with a tool such as IDA or Ghidra, the garbage data will need to be removed (if the junk data is left, the entry point will have to be manually specified).

Figure 30: PE Header in Extracted Shellcode File

The junk data can be stripped with a hex editor or other file manipulation tools, and once removed we can load the cleaned file into DIE to verify the file is detected as a valid PE.

Figure 31: Extracted Shellcode File in DIE

Loading this final stage file into a disassembler, and going to the entry point, we can spot the XOR key utilized in previous stages

Figure 32: Final Stage File Disassembly

With the help of a debugger (I used x32dbg [20]), we can dump the final stage config data at runtime post-decryption to reveal the C2 server it reports home to, which is located at the domain “prodomainnameeforappru[.]com (”. It should be noted that the final stage shellcode when executed in memory at runtime, will be mapped in a newly spawned “VBC.exe” (Visual Basic command line compiler) process.

Figure 33: Extracting C2 Domain with x32dbg

Flow Summary

  • Initial PDF (“case_-2023_4824647818.pdf”): Deliver MSI via AD download link.
  • Downloaded First Stage MSI (“build-x64.msi”): Unpack embedded cabinet file.
  • Extracted Cabinet File (“Binary.bz.WrappedSetupProgram”): Contains encrypted next stage DLL, and dummy app to use with tampered DLL for sideloading.
  • Dummy App (“iTunesHelper.exe”): Used to load tampered import DLL.
  • Tampered Import DLL (“CoreFoundation.dll”): Used to load and XOR decrypt next stage DLL
  • Encrypted Second Stage DLL (“sqlite3.dll”): Drop embedded compiled AutoIt script, AutoIt binary, and character substitution alphabet, and invoke compiled script with AutoIt binary.
  • AutoIt Binary (“autoit.exe”): Used to execute compiled AutoIt script.
  • Character Substitution Alphabet (“test.txt”): Used to run compiled AutoIt script (or deobfuscate a decompiled version).
  • Compiled Third Stage AutoIt Script (“script.a3x”): Construct final stage shellcode to load and execute in allocated memory.
  • Final Stage DarkGate Agent (“finalstage.dat” or found in memory of host “vbc.exe” process at runtime): Beacon home and provide remote access / additional malware delivery functionality.


DarkGate is a commodity loader with remote access and modular plugin capability, written in Borland Delphi that is advertised under the Malware-as-a-Service (MaaS) business model on popular cybercrime forums [22]. It mainly serves to deliver other malware, commonly infostealers to compromised hosts and either aid in exfiltration of the data or futher access and persistence. As modern AV/EDR products scrutinize PE files much more aggressively, alternative file types that can nest additional stages and still look legitimate are becoming far too attractive to MaaS providers. Automated triage solutions and sandboxes can help uncover some of these protected samples, but it may not be feasible or cost effective for an organization to run every installation package or installer they utilize through a sandbox.

As this MSI delivery avenue is less and less successful, DarkGate may switch to alternate means of nesting additional stages, but as of writing, other recent samples can be dissected by applying a similar routine to that above.

Being able to triage samples manually when signature-based scanning fails, or reputation checks are bypassed due to the use of a code signing certificate can be crucial when threat hunting, or responding to incidents within an organization that may not have access to a sandbox or automated triage products.

Figure 34: DarkGate File Manager [21]

Figure 35: DarkGate Miscellaneous Features [21]

Figure 36: DarkGate Remote Access Features [21]

References, Appendix, & Tools Used

[1] https://www.sans.edu/cyber-security-programs/bachelors-degree/
[2] https://www.virustotal.com/gui/file/693ff5db0a085db5094bb96cd4c0ce1d1d3fdc2fbf6b92c32836f3e61a089e7a
[3] https://www.globalsign.com/en
[4] https://legroom.net/software/uniextract
[5] https://7-zip.org/
[6] https://github.com/horsicq/DIE-engine/releases
[7] https://dmcxblue.gitbook.io/red-team-notes/persistence/dll-search-order-hijacking
[8] https://hex-rays.com/ida-pro/
[9] https://ghidra-sre.org/
[10] https://binary.ninja/
[11] https://mh-nexus.de/en/hxd/
[12] https://www.autoitscript.com/site/autoit/
[13] https://github.com/gchq/CyberChef
[14] https://github.com/PonyPC/myaut_contrib
[15] https://www.autoitscript.com/autoit3/docs/functions/StringSplit.htm
[16] https://www.autoitscript.com/autoit3/docs/functions/FileRead.htm
[17] https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect
[18] https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumwindows
[19] https://www.autoitscript.com/autoit3/docs/functions/BinaryToString.htm
[20] https://x64dbg.com/
[21] https://github.security.telekom.com/
[22] https://malpedia.caad.fkie.fraunhofer.de/details/win.darkgate

Indicators of Compromise

SHA-256 Hashes:


C2 Domain, IP & Port:
“prodomainnameeforappru[.]com", 443

1 comment(s)


Hello. I'm an engineer studying malware analysis.

I would like to ask you two questions regarding the content of the article.


I have verified the signature and certificate of the MSI file with the above HASH value mentioned in the article. But in my environment this file appears to be unsigned. Is this just my environment?

Please tell me the steps to extract the two files "Binary.bz.WrappedSetupProgram" and "Binary.bz.CustomActionDll" from an MSI file using Detect It Easy.

Thank you.

Diary Archives