January 18, 2026
Introduction
In this blog post, I’ll share my analysis of a new infostealer variant that heavily relies on multiple stages of the Donut loader — one of the most challenging samples I’ve tackled so far.
The infection chain involved several layers of shellcode, multiple dropped executables, and repeated spawning of dllhost.exe. This complexity, combined with numerous anti-debugging tricks, repeatedly led me down rabbit holes during reverse engineering. A particularly misleading aspect was the use of dllhost.exe — I initially assumed classic DLL injection was taking place, but the campaign instead injected shellcode directly into the process thread.

To further evade EDR detection, the malware employs direct SYSCALLs for memory allocations. VirusTotal currently classifies this new variant as Lumma infostealer.
This multi-stage, heavily obfuscated approach highlights how infostealers continue to evolve with sophisticated evasion and loader techniques, making thorough manual analysis essential for understanding and detecting these threats.
Attack Flow
This new malware variant spreads through ClickFix campaigns, a common social-engineering tactic that tricks users with fake CAPTCHA or verification prompts.The infection begins when the victim follows the Fake Captcha which leads them to execute malicious VBScript and PowerShell scripts. These scripts download and run the first-stage executable.
The first-stage executable loads the Donut loader directly into memory. Donut shellcode then injects and executes the second-stage payload for further exploitation.The second-stage payload spawns the DllHost.exe process and employs APC injection to inject Donut shellcode into an existing thread of that process.

This Donut shellcode drops a third-stage executable payload. The third-stage payload once again launches DllHost.exe and performs a second round of Donut shellcode injection via APC.
Finally, this second instance of Donut shellcode drops the infostealer payload: ChromElevator (open-source Chrome App-Bound Encryption Decryption tool).ChromElevator targets Chromium-based browsers (such as Chrome, Edge, and Brave). The tool exfiltrates browser cookies, passwords, payment information, autofill data, and potentially OAuth tokens to the attacker’s Telegram Bot API.
Donut Loader – Brief Overview
In this section, I’ll focus specifically on the Donut loader module — the part this infostealer variant heavily relies on to load and execute its shellcode while spawning new processes for further stages.
How the Donut Loader Module Works in This Campaign:
Initial API Resolution: The loader begins by dynamically resolving the addresses of three key Windows APIs: VirtualAlloc, VirtualFree, RtlExitUserProcess
Multiple Evasion Techniques: The loader implements several well-known user-mode hooks/patching techniques to disable security mechanisms:
- AMSI Bypass (Anti-Malware Scan Interface) Loads amsi.dll into memory, then patches the functions AmsiScanBuffer and AmsiScanString with a fake implementation that always returns: S_OK + AMSI_RESULT_CLEAN → Effectively neuters any AMSI-based scanning of the shellcode.
- WLDP Bypass (Windows Lockdown Policy / Windows Defender Application Control) Overwrites WldpQueryDynamicCodeTrust and WldpIsClassInApprovedList with dummy functions and allows execution of dynamically generated/untrusted code without triggering policy blocks.
- ETW Bypass (Event Tracing for Windows) Patches EtwEventWrite function and prevents security products from receiving telemetry about suspicious activity.
Payload Handling: The payload is first loaded into memory in compressed form. It is then decompressed in-place using the native API RtlDecompressBuffer.
These techniques make both static and dynamic detection significantly harder — especially for EDRs that rely heavily on API monitoring, ETW telemetry, or AMSI scanning.
Technical Analysis
ClickFix Campaign – Initial Infection Vector
This infostealer variant is distributed through one of the currently most widespread social-engineering techniques: ClickFix (also known as “Fake Captcha” or “Browser Verification” scams).
Victims are lured to spam/malicious websites via Malvertising , Phishing and Compromised / hacked legitimate websites. Upon landing on the page, the user is immediately presented with a fake CAPTCHA verification instructions. The instructions trick the user into performing a specific sequence of clicks that ultimately spawn the MSHTA process and executes a malicious script.
Mshta.exe + PowerShell Scripts
In this campaign, mshta.exe is used to directly download and run a remote Visual Basic Script (Inter.odd) hosted on the attacker’s C2 server. The VBScript initiates the PowerShell process and retrieves the next stage PowerShell script.


The PowerShell script downloads the next stage payload from the attackers C2 server.

The next stage payload – an executable is dropped to the machine.
Stage1 : Rapid_interpreter_excellence.exe
The Donut-encoded shellcode is embedded directly inside the binary, in the .rdata section (read-only data).

Instead of calling high-level Windows APIs (e.g., VirtualAlloc, WriteProcessMemory, CreateRemoteThread) — which are heavily hooked/monitored by almost all EDRs — the loader uses direct syscalls to perform sensitive memory operations. This bypasses user-mode API hooks and significantly lowers detection rates.
The loader performs the following memory manipulation steps using SYSCALLS:
- NtAllocateVirtualMemory – Allocates a new memory region in the current process with RWX permissions.
- NtWriteVirtualMemory – Writes the Donut shellcode directly into the allocated memory region.
- NtProtectVirtualMemory – Changes memory protection .



Donut Shellcode – Second-Stage Payload Handling & Advanced Evasion
Once the initial loader successfully executes the Donut shellcode via direct syscalls, the shellcode takes over and performs a highly sophisticated in-memory loading sequence for the second-stage payload .
- The shellcode first resolves its own Import Address Table (IAT) dynamically (to avoid static imports).
- The payload is decompressed using RtlDecompressBuffer into a newly allocated memory page. The decompressed data contains a full PE file structure but the PE headers does not contain a valid section table.

- The Donut shellcode fully reconstructs a clean, valid PE structure — including the section table — in a brand-new memory page. This intentional damage prevents easy memory dumping of a valid PE file
- Anti-Analysis & Integrity Checks The shellcode creates a verification code that is later verified by the second-stage payload. This acts as a loader chain integrity check: if the payload detects it was not executed through the expected Donut loader path (e.g., dumped and run standalone in a debugger).

- The Donut shellcode resolves several network-related Windows APIs – InternetOpenA, InternetConnectA, HttpOpenRequestA, HttpSendRequestA, InternetCrackURL, etc.
- Once the second-stage PE is fully reconstructed and placed in its final memory location, the execution control is transferred to the second-stage Executable.
Stage 2 : Stack_distributed_quick.exe
The second stage executable contains yet another embedded third-stage payload stored in its .rdata section — continuing the multi-layered, nested loader approach.
While the overall structure and logic remain very similar to the first-stage Donut loader, this second stage introduces several important differences and additional anti-analysis protections.
Integrity Check and Debugger Detection
The second-stage code attempts to read a file named 12345.txt from the current working directory of the process. When the file(12345.txt) is present, it must contain a specific secret code (hash) that was generated and written by the first-stage Donut loader during the initial execution.

If the file does not exist → the malware immediately assumes it is running under a debugger or analysis environment (sandbox, manual debugging session, etc.). It then actively searches for the following debugging tools/ Virtual machine processes by enumerating running processes and matching names/hashes.
apdagent.exe|apimonitor.exe|azurearcsystray.exe|binaryninja.exe|burpsuite.exe|charles.exe|cred-store.exe|cutter.exe|dbgx.shell.exe|decoder.exe|device-sense.exe|df5serv.exe|dnspy.exe|drrun.exe|dumpcap.exe|dumpit.exe|fakenet.exe|fiddler.exe|frida-inject.exe|frida-server.exe|frida.exe|gdb.exe|httpanalyzerv7.exe|httpdebugger.exe|httpdebuggerproxy.exe|httpdebuggerui.exe|hvix64.exe|ida64.exe|idag.exe|idag64.exe|idaq.exe|idaq64.exe|idaw.exe|idaw64.exe|ilspy.exe|immunitydebugger.exe|inetsim.exe|joeboxcontrol.exe|ilspy.exe|immunitydebugger.exe|inetsim.exe|joeboxcontrol.exe|joeboxserver.exe|ksdumper.exe|ksdumperclient.exe|mitmdump.exe|netcat.exe|ollydbg.exe|pestudio.exe|pin.exe|prl_cc.exe|prl_tools.exe|private-cloud-proxy.exe|procmon.exe|processhacker.exe|procexp.exe|qemu-ga.exe|r2.exe|rammap.exe|rdpclip.exe|x64dbg.exe|tcpdump.exe|vboxservice.exe|vboxtray.exe|vgauthservice.exe|vmacthlp.exe|vmtoolsd.exe|vmwaretray.exe|vmwareuser.exe|wireshark.exe|x32dbg.exe|standard vga|hyper-v video|vmware svga|virtualbox graphics|parallels display|qxl|red hat qxl|bochs display|microsoft basic display|virtual display
This is a very specific anti-debug trick designed to detect when analysts extract and run the second stage standalone without the full loader chain.
Heavy String Obfuscation
Almost all strings (API names, file names, process names, etc.) are heavily obfuscated using a custom long function that combines: ROL (rotate left) operations,XOR with rolling keys. This makes static analysis significantly harder — strings only become readable at runtime after deobfuscation.


The second stage dynamically resolves the virtual addresses of the following NT syscalls . (NtWriteVirtualMemory, NtProtectVirtualMemory, NtReadVirtualMemory, NtAllocateVirtualMemory). These are used for all memory manipulation operations.
The embedded third-stage payload is decrypted using the BCryptDecrypt API.
The second stage creates a new, suspended instance of DllHost process. It then injects the decrypted third-stage payload into this process using user-mode Asynchronous Procedure Call (APC) injection — a stealthy technique that avoids creating remote threads directly.

The injection sequence uses direct syscalls only:
- NtAllocateVirtualMemory → allocate memory in the remote dllhost.exe
- NtWriteVirtualMemory → write the decrypted payload
- NtProtectVirtualMemory → set RX/RWX permissions
- NtQueueApcThread → queue an APC to an existing thread in dllhost.exe, pointing to the payload entry point
- NtResumeThread → resume the suspended main thread, triggering APC execution


Next we will move on the fourth stage.
DLLhost-> DonutLoader – 1
Once the APC executes, control lands inside yet another Donut loader shellcode — essentially the same sophisticated in-memory loader we’ve seen before, but now running inside the legitimate dllhost.exe process. This Donut instance generates yet another unique secret code and drops the next stage payload.

The next stage is an executable named – Commercial_outstanding_smart.exe
Stage 3: Commercial_outstanding_smart.exe
The third-stage reconstructed PE contains yet another payload embedded in its .rdata section. This final embedded payload follows a very similar structure to the previous stages but introduces additional anti-debugging, and environment checks before delivering the infostealer.
As in previous stages, the payload dynamically resolves all required Windows API functions.The code checks for the existence of a hidden system file in the following path: C:\ProgramData\~m%08X


If the file does not exist:
- A new hidden + system attribute file is created at that exact path.
- This acts as a mutex-like persistence marker to prevent multiple simultaneous executions on the same machine.
If the file already exists: the code stops at this stage and the infostealer payload is not dropped to the memory.
This stage reads the 12345.txt file again (from the current working directory) and verifies the secret code that was generated and passed by the previous Donut loader.
The payload actively scans the infected machine for various indicators that could reveal the presence of a debugging tools, or sandboxed environment(Ex: machine configurations, graphics/display adapters etc). If any of these indicators are found → the malware will immediately terminate execution.
The core infostealer binary is decrypted using the BCryptDecrypt API
A new instance of dllhost.exe is created in suspended state.The decrypted final payload is then injected into this process using the same stealthy APC injection technique and Syscalls. The injected payload is another Donut loader shellcode — the last layer in this deeply nested chain.
DLLhost-> DonutLoader – 2
Once the APC executes, control lands inside yet another Donut loader shellcode running inside the legitimate dllhost.exe process. This Donut instance generates yet another unique secret code and drops the next stage payload.
The final stage payload is an infostealer called Chromelevator.
ChromElevator
ChromElevator is a modern post-exploitation tool increasingly adopted by infostealer operators to extract highly protected data from Chromium-based browsers. It is used to decrypt App-Bound Encrypted (ABE) cookies, passwords & payment methods from Chromium-based browsers (Chrome, Brave, Edge) in user mode and no admin rights required. The ChromElevator also logs the activity in the log file named logs.txt.

The ChromElevator payload creates the following working directory to stage and save the exfiltrated browser data.

Once collection completes, the staged files are exfiltrated to the attacker’s infrastructure using the following Telegram Bot API request.
https://api.telegram[.]org/bot8456437646:AAHpe9SdXev4Yc5GbWLvxElNnJNczhKqiGA/sendDocument
Please check out the ChromElevator Github repository for more information.
IOC’s
- rapid_interpreter_excellence.exe
- intelligent_engine_protected.exe
- runtime_excellence_streamlined.exe
- gwps.odd
- inter.odd
- cache.odd