FortiGuard Labs recently captured Excel documents in the Microsoft OLE Compound File format that contain malicious VBA Macros. Their file names are Pago_detalles.xls, makbuzu.xls, and Pago.xls. I then conducted deep research on them and found that they all belong to the same malicious campaign that cryptojacks systems to mine for Monero (XMR) cryptocurrency.
Affected platforms: Microsoft Windows
Impacted parties: Windows Users
Impact: Cryptojack Victim’s Device to Mine Cryptocurrency
Severity level: Critical
In this analysis, I will show how the crypto miner software is delivered by opening the Excel document and how it is executed on a victim’s device. I also look at the techniques it uses to prevent its code from being analyzed, how it gains persistence on the victim’s device, and how the malware performs process hollowing to execute the Monero miner on the victim’s device.
The content and VBA project are similar in all three Excel documents.
Figure 1.1 – The view of one of the documents opened by Microsoft Excel
When the document is opened in Microsoft Excel, as shown in Figure 1.1, it pops up a yellow warning bar to alert the user that the document contains a risky Macro project, which will be executed once the “Enable Content” button is clicked.
Given that the content is written in Spanish, this campaign targets Spanish-speaking people. It shows a blurred picture of a statement that tricks the user into clicking the button on the yellow bar for a clearer view.
The VBA Macro project is password protected from viewing, editing, and debugging. Once I disarmed its protections, I found an auto-execution sub-procedure Workbook_Open() in the project that is executed automatically once the Excel document is opened.
After deobfuscating the VBA statements, it is easy to understand the purpose of the sub-procedure Workbook_Open(), as shown in Figure 1.2.
Figure 1.2 – Debugging the auto-run procedure “Workbook_Open()”
It downloads a file from hxxps[:]//www[.]tractorandinas[.]com/wocontent/templates.exe, saves it into the system’s Templates folder, and renames it “GHJFRGUNL.exe”. At the end of the Workbook_Open() auto-run procedure, it calls “FPKGNSJJDW_Shell_Application.Open (VMNXMOV_local_file)” to run the downloaded file on the victim’s device.
Diving into the Downloaded File
The downloaded file “GHJFRGUNL.exe” was developed using Microsoft .Net Framework and is protected by an obfuscator called “ConfuserEx v1.0.0”.
By deobfuscating the file, I located a .Net Exe file, which is easier for analysts to use to comprehend its work-flows. It contains a .Net resource, which can be obtained with its resource name “Fyyxdkrpjokzonmmc” by calling the API ResourceManager.GetObject().
Figure 2.1 is a screenshot of the deobfuscated Exe file in an analysis tool. The .Net resource is shown on the right.
Figure 2.1 – Screenshot of .Net Resource “Fyyxdkrpjokzonmmc”
The resource’s data is a GZip-compressed .Net module (DLL) file. It is extracted in memory and then loaded. Figure 2.2 shows the context code of doing that.
Figure 2.2 – Loads .Net module and invokes its entry point method
Next, it gets the type of the entry point function for the .Net module and calls it by calling the API Type.InvokeMember(). The function is named “YLbTOcLUZT” and is defined under the namespace.class “DKNYEHTGFSSZDfys0h6.dOICUYTjc8hIf6usABv”.
Figure 2.3 – Debugging at the entry point function of the .Net module
Figure 2.3 shows the dynamically loaded .Net module in a .Net debugger, where it breaks at the entry point function.
As you may have noticed, the module is thoroughly obfuscated, including the class name, variable names, obfuscated workflow, and more. It also includes functions to perform anti-tamper checks during the run time. These cause the system to crash if it detects any modifications made to the module. That means that it’s hard to deobfuscate. This was my biggest challenge in analyzing it.
According to my analysis, the downloaded file is like a malware loader and installer, and the .Net module is the payload module for the malware.
Gaining Persistence
The payload module determines if the current process file (“GHJFRGUNL.exe”) is located in the system “%AppData%” folder and runs with Administrator privilege. If not, it will exit the process and rerun it with Administrator privilege, popping up a message for the victim to confirm.
It copies the Exe file into the “%AppData%” folder and adds it to the system Task Scheduler. This ensures the process launches at startup and runs every two minutes.
Figure 3.1 – The malware is about to create a new task
It breaks at a function, as shown in Figure 3.1, where it uses a TaskScheduler object to create the new task with the TaskDefinition displayed at the bottom. The new task’s name is from the process name “GHJFRGUNL”.
Figure 3.2 is the screenshot of the system Task Scheduler. You can see that a new task has been created with the process name.
Figure 3.2 – Created task in the system Task Scheduler
Once completed, it can launch at system startup. The Task Scheduler repeatedly starts “GHJFRGUNL.exe” every two minutes in case the process or its sub-processes are killed by the victim due to high consumption of hardware resources (like CPU and memory). It also has a strategy for keeping only one process running simultaneously using a Mutex object.
Communicate with the C2 server
Its config block data is base64 encoded in the payload module (“Fyyxdkrpjokzonmmc.dll”), which is decoded and loaded in a config block.
This contains the malware configuration data, like flags that tell the malware how to work, its C2 server domain string and port numbers, malware variant name, and crypto key used to encrypt and decrypt packets between the client and C2 server.
The decoded config block data is a stream of bytes converted into an object by calling the Deserialize() function (from a third-party module, protobuf-net.dll). The config object is used throughout the payload module lifetime.
Figure 4.1 is a screenshot of the config data being deserialized into a global variable.
Figure 4.1 – Config object
There are two TCP port numbers in the config object. It repeatedly attempts to connect to the C2 server with two ports, one by one, until a connection is established. Next, it gathers basic information from the victim’s device, encrypts the collected information, and sends it to its C2 server.
Figure 4.2 – It’s about to encrypt collected data.
Figure 4.2 shows when the malware is about to call a function to encrypt the collected information carried by variable “u” and send it to the C2 server.
The collected information consists of many of the items shown below:
- “true” – A flag indicating if the current user is an administrator.
- “Explo” – A constant string from config object, malware variant name.
- “Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz” – Processer’s information.
- “Desktop” – It tells the victim’s computer type.
- “96f709c0c080fbcb92806bd724266a13” – It’s a sort of victim ID that is MD5 generated using the device hardware data, such as ProcessorID, DiskSerialNumber, and GraphicsAdapter.
- “Bobs” – Its current user name.
- “v1.6.4” – Its malware version, a decrypted constant string.
- “N/A” – This should be installed AV product information.
- “Untitled – Notepad” – This is the current topmost program title.
- 8 – Its memory size 8Gb.
It uses a Triple DES cipher algorithm to encrypt and decrypt the data between the malware and its C2 server. Figure 4.3 shows the encrypted packets captured by Wireshark.
Figure 4.3 – Encrypted packets sent and received
The cryptography key is “57dd8b6cc78fd8f51c2f5a”, taken from the config object.
Steps for sending data to the C2 server
- It serializes the information from an object variable (as shown in Figure 4.2) into a byte stream.
- It calls the DES encryption function.
- It uses the Send() function from the TcpClient’s socket object to send the encrypted data.
Steps for receiving data from the C2 server
- It receives the C2 server’s packets by calling the Recv() function of the TcpClient’s socket object.
- It calls the DES decryption function to decrypt the data to a byte stream.
- It deserializes the byte stream into an object variable.
Figure 4.4 – C2 server’s response packet deserialized into an object variable
Figure 4.4 shows the entire set of received data responding to the first packet with collected information to the C2 server. It has been converted into an object variable (referred to as a response object) from a byte stream. The response object leads the malware to execute further unauthorized actions on the victim’s device.
In the response object, there are two Onedriver URLs from which the malware will download two files. The two MD5 values in the response object are the hash values of the two files. It does not save the files to local folders but to the system registry under its sub-key, as shown in Figure 4.5.
Figure 4.5 – The downloaded files from Onedriver are saved in the system registry
The sub-key name “96f709c1c080fbcb92806bd724266a03” is the victim ID, as I mentioned earlier. It is generated with the device hardware information. The names of the values are the two files’ MD5 values, and the data is the content of the two files. It won’t download the two files if the relevant registry values exist.
Both of them are compressed PE files, which are named “plugin_3.dll” (File size: 2.3Mb, MD5:78B10BAE1DB822E486A2393F0ADBE627) and “plugin_4.dll” (File size: 37Kb, MD5: A722D3BCD1D9056D1BBE840197059BCE) on the website. To explain how they work together, I will refer to them by their names.
Process Hollowing
Decompressing “plugin_4.dll” gets a .Net dll file (“ClassLibrary1.dll”), which is used to perform process hollowing. “plugin_3.dll” contains an Exe file (“xmrig.exe”, the XMR Miner) that will be injected into another process by “plugin_4.dll”.
The payload module (“Fyyxdkrpjokzonmmc”) proceeds to dynamically load “ClassLibrary1.dll”, which is also thoroughly obfuscated. Its function, Plugin.Plugin.Run(), is the entry point function for process hollowing.
Figure 5.1 – The decrypted Miner in memory
After “xmrig.exe” is decompressed in memory, as shown in Figure 5.1, it calls the API CreateProcess() to create a process called “AddInProcess.exe”, which is from the response object (refer to Figure 4.4). The function parameter Creation Flag is 12 (i.e., CREATE_SUSPENDED | DETACHED_PROCESS).
Later, it calls a bunch of key Windows APIs, such as VirtualAlloc(), GetThreadContext(), WriteProcessMemory(), SetThreadContext(), and ResumeThread(), to deploy the “xmrig.exe” into the newly-created “AddInProcess.exe” process.
Afterward, “xmrig.exe” runs as “AddInProcess.exe”, and the malware payload module becomes the daemon process to the process-hollowed process to prevent it from being killed.
Monero (XMR) Miner
XMRig is a high-performance, open-source, cross-platform (Windows, Linux, Android, and macOS) cryptocurrency miner application, which is both a CPU and GPU miner supporting RandomX, KawPow, CryptoNight, and GhostRider algorithms.
However, this platform is also commonly abused by cybercriminals to perform cryptojacking, which means hackers hijack the victim’s computing resources to mine cryptocurrencies on their behalf.
“xmrig.exe” is XMrig’s Windows version application. It can use the CPU to mine for Monero coins. I manually decompressed the miner application from the downloaded “plugin_3.dll” into “plugin_3_1.exe”. You can see the detailed properties of this file in Figure 6.1.
Figure 6.1 – XMRig miner property
Taking a look back at the Process Hollowing section, it created a suspended new process of “AddInProcess.exe”. Other than the Creation Flag to API CreateProcess(), it also has a Command Line parameter, like “C:WindowsMicrosoft.NETFramework64v4.0.30319AddInProcess.exe -o xmr.2miners.com:13333 -u 88hKxLYFGsx4U{…}eF.Rig998 -p x –tls –algo rx/0 –cpu-max-threads-hint=50″.
The parameter string is from the response object (refer to Figure 4.4). It is not a parameter to the created “AddInProcess.exe” but for the xmrig.exe that has been injected into it.
The following table contains a description for each of the options:
-o, –url=URL |
It specifies the mining server and port. |
-a, –algo=ALGO |
It specifies mining algorithm to be used. |
-u, –user=USERNAME |
It is the hacker’s wallet address. |
-p, –pass=PASSWORD |
It is the password for mining server. |
–tls |
It enables SSL/TLS support. |
–cpu-max-threads-hint=N |
It specifies the maximum CPU threads count (in percentage) hint for autoconfig |
Figure 6.2 shows how XMRig is mining Monero for the attacker.
Figure 6.2 – XMRig is mining Monero
Summary
In this analysis, we walked through the entire process, from executing the VBA code in the Excel document to downloading an executable file (template.exe or GHJFRGUNL.exe).
Next, I explained how the payload .Net module is extracted from the executable file and executed. Then, you learned how the malware communicates with its C2 server and what control data (Monero miner) is received.
Last, I elaborated on how it injects a Monero miner into another process (“AddInProcess.exe”) by executing process hollowing to mine Monero on the attacker’s behalf.
Below is a workflow chart that depicts the entire process.
Figure 7.1 – Workflow of the entire process
Fortinet Protections
Fortinet customers are already protected from this campaign with FortiGuard’s Web Filtering, and AntiVirus services as follows:
The downloading URLs and C2 server are rated as “Malicious Websites” by the FortiGuard Web Filtering service.
The FortiGuard CDR (content disarm and reconstruction) service can disarm the malicious VBA project inside the Excel document.
The relevant samples are covered and blocked by the FortiGuard Antivirus service.
FortiGate, FortiMail, FortiClient, and FortiEDR support the FortiGuard AntiVirus service. The Fortinet AntiVirus engine is a part of each of those solutions. As a result, customers who have these products with up-to-date protections are protected.
We also suggest our readers go through the free NSE training: NSE 1 – Information Security Awareness, a module on Internet threats designed to help end users learn how to identify and protect themselves from phishing attacks.
IOCs:
URLs:
hxxps://www[.]tractorandinas[.]com/wocontent/templates[.]exe
hxxps://onedrive[.]live[.]com/download?cid=F32323276F5346E9&resid=F32323276F5346E9%21132&authkey=AJUNOnV3DDTyOJw
hxxps://onedrive[.]live[.]com/download?cid=F32323276F5346E9&resid=F32323276F5346E9%21131&authkey=ANCBF29YwxfXxd4
C2 Server List:
dnuocc[.]com:9077
dnuocc[.]com:9078
Relevant Sample SHA-256
[Pago.xls]
EF02701E2196F54B5858BCB67A41D34FC9A5F248EFDAE181C701C200950D638D
[makbuzu.xls]
68346D23F359A27744B49D6EA9BD229F2929D1CEE057670D2BA73545C0BA427D
[Pago_detalles.xls]
417AE2D5F5111DDF80B63C443E14B70EC2052B3E64A35940C9F81F262F7E526E
[templates.exe / GHJFRGUNL.exe]
8A2194A75F972890729328A15A01B34E327A0145A6121098315AF9ECBF86ED67
Learn more about Fortinet’s FortiGuard Labs threat research and global intelligence organization and Fortinet’s FortiGuard AI-powered Security Services portfolio. Sign up to receive our threat research blogs.