Blog

MintsLoader: StealC and BOINC Delivery

BY eSentire Threat Response Unit (TRU)

January 16, 2025 | 9 MINS READ

Threat Intelligence

Threat Response Unit

TRU Positive/Bulletin

Want to learn more on how to achieve Cyber Resilience?

TALK TO AN EXPERT

Adversaries don’t work 9-5 and neither do we. At eSentire, our 24/7 SOCs are staffed with Elite Threat Hunters and Cyber Analysts who hunt, investigate, contain and respond to threats within minutes.

We have discovered some of the most dangerous threats and nation state attacks in our space – including the Kaseya MSP breach and the more_eggs malware.

Our Security Operations Centers are supported with Threat Intelligence, Tactical Threat Response and Advanced Threat Analytics driven by our Threat Response Unit – the TRU team.

In TRU Positives, eSentire’s Threat Response Unit (TRU) provides a summary of a recent threat investigation. We outline how we responded to the confirmed threat and what recommendations we have going forward.

Here’s the latest from our TRU Team…

What did we find?

In early January 2025, the eSentire Threat Response Unit (TRU) identified an ongoing campaign involving MintsLoader delivering second stage payloads like Stealc and the Berkeley Open Infrastructure for Network Computing (BOINC) client. MintsLoader is a PowerShell based malware loader that has been seen delivered via spam emails with a link to Kongtuke/ClickFix pages or a JScript file. MintsLoader features a Domain Generation Algorithm (DGA) with a seed value based on the addition of the current day of the month and a constant, combined with anti-VM techniques to evade sandboxes and malware researchers. Impacted organizations in the United States and Europe include the Electricity, Oil & Gas and Law Firms & Legal Services industries. 

The MintsLoader infection process begins when the victim clicks a link in a spam email which downloads a JScript file matching the regex pattern, “Fattura[0-9]{8}.js”.

Figure 1 – JScript download
Figure 1 – JScript download

The contents of the script can be seen in the following figure.

Figure 2 – JScript obfuscated contents
Figure 2 – JScript obfuscated contents

The contents of the deobfuscated JScript can be seen below. First a sleep occurs for 13 seconds, then a WScript.Shell object is instantiated, and the Run method is called to execute the first MintsLoader associated command in PowerShell. This command uses the curl command to retrieve the first stage of MintsLoader. Before the script exits, it deletes itself, likely as a measure to make it more difficult for responders to acquire the file for analysis. It is worth noting that the format of the PowerShell command is identical in cases where MintsLoader is instead delivered via ClickFix/KongTuke, however it is executed in a Run prompt instead of via WScript.

Figure 3 - Deobfuscated JScript contents
Figure 3 - Deobfuscated JScript contents

The response from the MintsLoader C2 is obfuscated and is more PowerShell that uses Invoke-Expression (iex) again to execute the next stage.

Figure 4 – Obfuscated first stage
Figure 4 – Obfuscated first stage

The next stage of PowerShell is obfuscated as well and begins with decoding each line as an array of integers to their equivalent ASCII values.

Figure 5 – Obfuscated next stage
Figure 5 – Obfuscated next stage

The beginning of the deobfuscated script checks if the victim machine is a virtual machine via the WMI object Get-MpComputerStatus cmdlet property IsVirtualMachine. Also shown in the figure below, the variable “$key” stores a value that is used throughout the script and later is sent to the C2.

Figure 6 – Check if virtual machine via Get-MpComputerStatus
Figure 6 – Check if virtual machine via Get-MpComputerStatus

Next the cmdlet Win32_VideoController is queried and the object AdapterDACType is matched against the following strings. The first statement in the switch statement aims to identify a system that is likely not a virtual machine by checking for the presence of the strings “Internal” or “Integrated”. The remaining strings that are checked are as follows and serve to identify the machine as a VM and specifically target VMWare and KVM/QEMU/Bochs based hypervisors.

Figure 7 – Check if virtual machine via Win32_VideoController object AdapterDACType
Figure 7 – Check if virtual machine via Win32_VideoController object AdapterDACType

Next, two constants are added to the $key variable and the WMI cmdlet Win32_CacheMemory is queried, acquiring the first object’s purpose property and comparing it in a switch statement. The first two conditions in the switch statement check if the property equals L1 or is less than 4 characters, which aims to identify virtual machines. The final check aims to identify if a system is likely a physical machine.

Figure 8 – Check if virtual machine via Win32_CacheMemory
Figure 8 – Check if virtual machine via Win32_CacheMemory

MintsLoader then makes use of a DGA that uses a seed value consisting of the current day of the month plus a constant in a loop. The loop is iterated 15 times over and the System.Random object and Next method are utilized as indexes into the character array “abcdefghijklmn”. Finally, the resulting C2 domain is appended with the TLD of the C2 server (.top).

Figure 9 – DGA generate C2 server for the day
Figure 9 – DGA generate C2 server for the day

A string containing part of the URI path is then built from a random ascii-numeric character array with a length of 10 characters using the Get-Random cmdlet. This is used as part of the full C2 URI path. The query parameters are built first by getting the computer name via the environment variable ComputerName which is used as the value for the id query parameter, the aforementioned $key variable is used as the value for the key query parameter, and the s query parameter contains a hard-coded number, e.g. 527. The curl command is used again to invoke the request to the C2 and the response from the C2 is invoked again via iex.

Figure 10 – Send request to C2 and invoke response
Figure 10 – Send request to C2 and invoke response

The following is a list of all the possible DGA generated domains identified in this campaign.

Figure 11 – Known DGA domains
Figure 11 – Known DGA domains

The final PowerShell stage is also obfuscated and decodes more integers to ASCII. When deobfuscated, a poorly written and known Anti-Malware Scan Interface (AMSI) bypass technique fails to run due to improper de-obfuscation. A web request is then invoked to download the payload from temp[.]sh, a file hosting site that is a clone of Pomf[.]se. The response is written to the temp directory and is executed. Though the file hosting site is no longer serving the file, the SHA-256 of the file is available for download in VirusTotal. This file is a packed sample of the information stealing malware StealC.

Figure 12 – Final stage, download/execute StealC
Figure 12 – Final stage, download/execute StealC

StealC is an information stealer advertised by its developer “Plymouth” on Russian-speaking underground forums and has been sold as a Malware-as-a-Service since January 2023. Re-engineered from the information stealer Arkei first seen in 2018, StealC targets sensitive data stored by web browsers, extensions, applications, crypto-wallets, and email clients, including financial data, passwords, and tokens. Several legitimate DLLs, e.g. sqlite3.dll, nss3.dll, mozglue.dll, softokn3.dll, and others are downloaded and utilized as part of this process. Harvested data is exfiltrated to its command and control (C2) server using HTTP POST requests.

The admin panel for StealC can be seen in the figure below, which provides threat actors with a variety of features, such as a query builder for sorting through stolen logs.

Figure 13 – StealC operator panel from sales thread on exploit[.]in (Feb 2023)
Figure 13 – StealC operator panel from sales thread on exploit[.]in (Feb 2023)

StealC makes use of XOR encrypted strings to hide from static analysis. The routine that handles decryption of the strings is one of the first behaviors by StealC, the resulting decrypted strings are stored as DWORD pointers.

Figure 14 – StealC string decryption
Figure 14 – StealC string decryption

For this particular sample (138d2a62b73e89fc4d09416bcefed27e139ae90016ba4493efc5fbf43b66acfa) we identified the following C2 URL and Botnet ID in the strings:

Figure 15 – StealC C2 and Botnet ID
Figure 15 – StealC C2 and Botnet ID

After string decryption and resolving APIs there are several anti-debug/anti-analysis subroutines. For example, the C code included below checks if the username of the current user is “JohnDoe”. If so, the malware exits.

Figure 16 – StealC username check for JohnDoe
Figure 16 – StealC username check for JohnDoe

StealC contains a check to ensure the malware doesn’t run on any systems that have the default language ID associated with Russia, Ukraine, Belarus, Kazakhstan, or Uzbekistan. If any of these languages match, the malware exits.

Figure 17 – StealC check for banned countries
Figure 17 – StealC check for banned countries

The count of processor cores is checked, if the system only has a single core, the malware exits.

Figure 18 – StealC processors check
Figure 18 – StealC processors check

The total memory of the system is retrieved, if less than 1111 MB, the malware exits.

Figure 19 – StealC memory check
Figure 19 – StealC memory check

The vertical height of the system's resolution is checked, if less than 666, the malware exits.

Figure 20 – StealC resolution check
Figure 20 – StealC resolution check

Prior to communicating with C2, a hardware ID (HWID) is generated. This HWID is generated based on the C:\ drive volume serial number and is unlikely to change so it is likely checked by threat actors to filter stolen logs in the backend or as a measure to deny access to known sandboxes. The python script here can be used to generate the HWID and decode an existing HWID if one is identified in incidents where HTTP traffic has been captured.

Figure 21 – StealC HWID generation via Volume Serial
Figure 21 – StealC HWID generation via Volume Serial

The following figure displays the initial HTTP POST request to the script gate where “<HWID>” represents the generated HWID. Though the C2 is no longer online, the response would contain a base64 encoded configuration. Subsequent HTTP POST requests follow a similar format and are used for exfiltration of harvested files, credentials, and other sensitive information. HTTP GET requests are used for retrieving needed third party libraries, such as sqlite3.dll.

Figure 22 – StealC Initial C2 request
Figure 22 – StealC Initial C2 request

What did we do?

What can you learn from this TRU Positive?

Recommendations from the Threat Response Unit (TRU):

Indicators of Compromise

You can access the Indicators of Compromise here.

References

https://www.huntress.com/blog/fake-browser-updates-lead-to-boinc-volunteer-computing-software
https://www.forcepoint.com/blog/x-labs/malicious-javascript-code-sent-via-pec-email-italy
https://levelblue.com/blogs/labs-research/asyncrat-loader-obfuscation-dgas-decoys-and-govno
https://x.com/CERTCyberdef/status/1849392561024065779

eSentire Unit
eSentire Threat Response Unit (TRU)

The eSentire Threat Response Unit (TRU) is an industry-leading threat research team committed to helping your organization become more resilient. TRU is an elite team of threat hunters and researchers that supports our 24/7 Security Operations Centers (SOCs), builds threat detection models across the eSentire XDR Cloud Platform, and works as an extension of your security team to continuously improve our Managed Detection and Response service. By providing complete visibility across your attack surface and performing global threat sweeps and proactive hypothesis-driven threat hunts augmented by original threat research, we are laser-focused on defending your organization against known and unknown threats.

Read the Latest from eSentire