[Guest Diary] Dissecting DarkGate: Modular Malware Delivery and Persistence as a Service.
by John Moutos, SANS BACS Student (Version: 1)
[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].
Intro
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.
Context
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.
Analysis
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 (46.21.157.142)”. 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.
Takeaway
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:
693ff5db0a085db5094bb96cd4c0ce1d1d3fdc2fbf6b92c32836f3e61a089e7a
599ab65935afd40c3bc7f1734cbb8f3c8c7b4b16333b994472f34585ebebe882
107b32c5b789be9893f24d5bfe22633d25b7a3cae80082ef37b30e056869cc5c
f049356bb6a8a7cd82a58cdc9e48c492992d91088dda383bd597ff156d8d2929
17158c1a804bbf073d7f0f64a9c974312b3967a43bdc029219ab62545b94e724
2693c9032d5568a44f3e0d834b154d823104905322121328ae0a1600607a2175
237d1bca6e056df5bb16a1216a434634109478f882d3b1d58344c801d184f95d
2296f929340976c680d199ce8e47bd7136d9f4c1f7abc9df79843e094f894236
91274ec3e1678cc1e92c02bc54a24372b19d644c855c96409b2a67a648034ccf
ee1ffb1f1903746e98aba2b392979a63a346fa0feab0d0a75477eacc72fc26a6
f7e97b100abe658a0bad506218ff52b5b19adb75a421d7ad91d500c327685d29
C2 Domain, IP & Port:
“prodomainnameeforappru[.]com", 46.21.157.142:port 443
Comments
I would like to ask you two questions regarding the content of the article.
(1)
693ff5db0a085db5094bb96cd4c0ce1d1d3fdc2fbf6b92c32836f3e61a089e7a
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?
(2)
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.
ken
Feb 29th 2024
9 months ago