FortiGuard Labs Threat Research

Analyzing Malware Code that Cryptojacks System to Mine for Monero Crypto

By Xiaopeng Zhang | January 31, 2023

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:\Windows\Microsoft.NET\Framework64\v4.0.30319\AddInProcess.exe -o -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.


It enables SSL/TLS support.


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


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 trainingNSE 1 – Information Security Awareness, a module on Internet threats designed to help end users learn how to identify and protect themselves from phishing attacks.







C2 Server List:




Relevant Sample SHA-256







[templates.exe / GHJFRGUNL.exe]



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.