Reversing LummaC2: Inside the Stealer That Survived a Global Takedown

In May 2025, Microsoft, the FBI, Europol, and a coalition of cybersecurity companies seized approximately 2,300 malicious domains, dismantled five administration panels, and sinkholed the command-and-control infrastructure behind LummaC2 — the world's most prolific information stealer. Europol called it "the world's most significant infostealer threat." Within days, it was back. This article breaks down how LummaC2 actually works under the hood: the anti-analysis techniques that make it difficult to reverse, the evasion mechanisms that keep it alive in sandboxes, and the architectural decisions that allowed it to survive the largest coordinated malware takedown in recent history.

Background: From Underground Forum to Global Threat

LummaC2 (also known as Lumma Stealer or LummaC2 Stealer) is an information-stealing malware written in C and assembly that first appeared for sale on Russian-language underground forums in December 2022. Its developer, operating under the alias "Shamel" (and sometimes "Lumma"), sells access through a Malware-as-a-Service (MaaS) model with tiered pricing ranging from $250 to $1,000 per month. Higher tiers let buyers generate custom malware builds, add their own crypters, and track stolen data through a dedicated web portal.

The stealer's target list is extensive. It extracts saved credentials, cookies, autofill data, and browsing history from Chromium-based and Gecko-based browsers. It targets over 80 cryptocurrency wallet extensions and desktop wallets, 2FA browser extensions, password managers, VPN clients, FTP applications, and messaging platforms including Telegram and Discord. Once collected, the stolen data is archived and exfiltrated to attacker-controlled servers via encrypted HTTP POST requests using a multipart/form-data content type.

By November 2024, Check Point Research reported that LummaC2 accounted for over half — 51% — of all infostealer logs for sale on the Russian dark web. IBM X-Force's 2025 threat intelligence report documented an 84% increase in infostealers delivered via phishing, with Lumma as the most prevalent by a significant margin. The FBI estimated that Lumma had been involved in approximately 10 million infections globally by the time of the takedown.

Context

Lumma infections are frequently a precursor to ransomware. Microsoft has documented its use by Octo Tempest (Scattered Spider) as an initial access vector, and multiple ransomware affiliates rely on Lumma logs for credential-based entry into enterprise networks.

The May 2025 Takedown — and What Happened Next

On May 21, 2025, Microsoft's Digital Crimes Unit (DCU) announced a coordinated global disruption of LummaC2's infrastructure. The operation was the result of a court order obtained on May 13 from the U.S. District Court for the Northern District of Georgia, and it brought together the DOJ, FBI, Europol's European Cybercrime Centre (EC3), Japan's Cybercrime Control Center (JC3), and cybersecurity firms including ESET, Bitsight, Lumen, Cloudflare, CleanDNS, and GMO Registry.

"Between March 16, 2025, and May 16, 2025, Microsoft identified over 394,000 Windows computers globally infected by the Lumma malware. Working with law enforcement and industry partners, we have severed communications between the malicious tool and victims." — Steven Masada, Assistant General Counsel, Microsoft Digital Crimes Unit

The numbers were significant: approximately 2,300 malicious domains seized, with over 1,300 redirected to Microsoft-controlled sinkhole servers. The DOJ simultaneously seized five core administration domains — the user panels where paying affiliates logged in to deploy the malware and access stolen data. Europol's Edvardas Šileris, head of the European Cybercrime Centre, called the operation "a clear example of how public-private partnerships are transforming the fight against cybercrime."

It lasted about 48 hours.

Threat intelligence data tracked by Lumu showed that new indicators of compromise (IoCs) dropped to 57 on May 21 — the day of the announcement — down from 243 on May 20. By May 22, new IoCs had already climbed to 287. By May 28, they hit 457, nearly double the pre-takedown peak. Trend Micro confirmed the pattern: the number of unique accounts targeted by Lumma dipped briefly in May, then returned to normal levels through June and July 2025.

Lumma's developer posted on the XSS underground forum confirming the domain seizures but contesting the FBI's claim of having seized the main server. The server, the developer wrote, was beyond the geographic reach of U.S. law enforcement. The FBI had instead "penetrated the server through an unknown exploit and formatted all the disks." The developer claimed functionality was quickly restored and logging was increased. Check Point's security researchers corroborated that the operation's physical infrastructure was beyond the reach of authorities cooperating in the takedown.

"Most takedowns hit the surface, not the roots. The kingpins behind these operations are rarely unmasked, let alone arrested. Until that changes, the threat won't disappear." — Amir Ramzan, SOCRadar Threat Intelligence

Post-takedown, Trend Micro observed that Lumma operators shifted away from Cloudflare services for domain obfuscation, moving instead to hosting providers based in Russia — including Selectel — that are less likely to cooperate with Western law enforcement. The malware's distribution channels also evolved: less reliance on public underground forums, more use of encrypted Telegram channels, GitHub repositories disguised as game cheats, and social media platforms including YouTube and Facebook.

To understand why LummaC2 is this resilient, you have to look at the binary itself.

Unpacking LummaC2: The Packer and Initial Execution

LummaC2 v4.0 samples do not ship as bare executables. The developer strongly discourages affiliates from distributing unpacked builds, and the malware is typically wrapped in at least one layer of packing or crypting before deployment. Recent campaigns analyzed by Netskope Threat Labs have used Nullsoft Scriptable Install System (NSIS) installer files as an outer wrapper, with AutoIt scripts as an intermediate stage before the actual Lumma payload is loaded.

The packing process observed by Outpost24's KrakenLabs research team follows a two-layer approach. In the first layer, the packer loads an encrypted resource from the PE's resource section. The decryption routine XORs each byte of the resource with a hardcoded key, producing a second-stage PE in memory. In the second layer, this decrypted PE is mapped into the process's virtual address space: the packer copies section data, applies relocations, and finally transfers execution to the payload's original entry point via CreateThread, passing NTHeaders->OptionalHeader.AddressOfEntryPoint as the thread routine parameter.

For analysts, the critical interception point is between the two layers. After the resource has been decrypted into an allocated buffer but before relocations are applied, the unpacked LummaC2 v4.0 binary can be dumped cleanly from memory for static analysis. Waiting until after relocation makes reconstruction more difficult because addresses have already been patched for the in-memory base.

Once unpacked, the real complexity begins.

Control Flow Flattening: Breaking the Analysis Flow

Starting with version 4.0, LummaC2 applies control flow flattening (CFF) to all default builds — even samples that do not use an external packer. This is a significant escalation from earlier versions, which relied primarily on junk string insertion for obfuscation.

Control flow flattening is an obfuscation technique that transforms a program's natural branching structure into a single large loop controlled by a state variable. Instead of code flowing sequentially from block A to block B to block C, the flattened version places all blocks inside a switch-case dispatcher. A state variable determines which block executes next, and each block updates the state variable before returning to the dispatcher. The result is that every basic block appears to be reachable from every other block, destroying the hierarchical call graph that disassemblers like IDA Pro and Ghidra rely on to reconstruct program logic.

In LummaC2's implementation, the dispatcher loop occupies the top of most functions. Each iteration reads the current state value, dispatches to the corresponding block, and the block writes a new state value before jumping back to the dispatcher. For reverse engineers, this means you cannot simply read the disassembly top-to-bottom — you have to trace the state variable through each transition to reconstruct the actual execution order.

Palo Alto's Unit42 research team published an IDA Python script to assist with deobfuscation by emulating execution through the flattened control flow. Outpost24's KrakenLabs adapted this approach for IDA Python 7.4+ with support for live debugging sessions, enabling analysts to step through the dispatcher and record the actual block ordering at runtime.

Stack-Based Control Structures

LummaC2 v4.0 also uses an unusual stack allocation pattern. Several routines call alloca_probe or its equivalent to allocate significant extra stack space, then use ESI as a pointer into a large structure stored on the stack. This structure holds intermediate values, configuration data, and the parameters used in the anti-sandbox checks described below. To make sense of these routines, analysts need to define a custom structure in IDA that maps the stack layout and rename fields as they are identified during reverse engineering.

API Resolution: PEB Walking and API Hashing

LummaC2 does not call LoadLibrary or GetProcAddress to resolve Windows API functions. Both of these calls are heavily monitored by endpoint detection and response (EDR) products, and their presence in an import table is itself a signal for static analysis. Instead, LummaC2 resolves every API call it needs by walking the Process Environment Block (PEB) — a user-mode data structure maintained by the Windows kernel for each process that contains, among other things, the list of all loaded modules.

The process works as follows. First, the malware accesses the PEB via the Thread Environment Block (TEB). On 32-bit processes, the PEB is located at FS:[0x30]; on 64-bit processes, at GS:[0x60]. LummaC2's implementation avoids the direct FS:[0x30] access — instead, it computes the offset indirectly through FS:[EAX], where EAX has been set to 0x30 through a series of stack manipulations. This indirection is specifically designed to confuse automated disassembly tools that pattern-match on the standard PEB access instruction.

; Standard PEB access (what LummaC2 avoids)
mov eax, fs:[0x30]        ; PEB

; LummaC2's indirect approach
; ... stack manipulation sets EAX = 0x30 ...
mov eax, fs:[eax]         ; PEB via indirect offset

Once the PEB is located, the malware traverses the PEB->Ldr field to reach the PEB_LDR_DATA structure, then walks the InLoadOrderModuleList — a doubly-linked list of LDR_DATA_TABLE_ENTRY structures, one for each loaded DLL. It iterates this list to find ntdll.dll, kernel32.dll, and user32.dll by comparing module names.

For each target DLL, LummaC2 then parses the PE export table to locate specific functions. But rather than comparing function names as plaintext strings, it uses API hashing. The malware computes a hash of each exported function name and compares the result against a table of pre-computed hash values embedded in the binary. Outpost24's analysis identified the hashing algorithm as MurmurHash2, a non-cryptographic hash function that produces 32-bit output. The hash values are stored in the ECX register and passed to a resolution function that emulates the hashing algorithm against every export in the target DLL until a match is found.

KrakenLabs developed an approach to defeat this: they used the Unicorn Engine to emulate the MurmurHash2 implementation extracted from the binary, running it against a complete dictionary of Windows API function names to build a lookup table mapping hash values to function names. They then used an IDA Python script to annotate each hashed API call in the disassembly with a comment identifying the resolved function — transforming opaque hash comparisons into readable API names without needing to execute the malware.

Heaven's Gate: Crossing the 32/64-Bit Boundary

LummaC2 is compiled as a 32-bit PE executable. On modern 64-bit Windows systems, 32-bit processes run under the WoW64 (Windows-on-Windows 64-bit) compatibility layer. Under WoW64, a 32-bit process has access to a 32-bit view of the system — it loads the 32-bit versions of system DLLs from SysWOW64, and its API calls are translated through a thunking layer before reaching the kernel.

LummaC2 exploits this architecture through a technique known as Heaven's Gate, first documented by researchers Roy G Biv and DefJam. The technique allows a 32-bit process to execute 64-bit code directly, bypassing the WoW64 translation layer entirely. It works by manipulating the x86 segment selector: on Windows, 32-bit code runs in segment 0x23 and 64-bit code runs in segment 0x33. By pushing the 0x33 selector onto the stack and executing a far return (RETF) instruction, the processor switches to 64-bit mode at the target address.

; Heaven's Gate transition: 32-bit to 64-bit
push   0x33              ; 64-bit code segment selector
call   $+5               ; push next instruction address
add    [esp], 5           ; adjust return address past RETF
retf                      ; far return switches to 64-bit mode
; --- now executing in 64-bit mode ---

In 64-bit mode, LummaC2 can access the 64-bit PEB, locate the 64-bit version of ntdll.dll, and invoke native system calls (via ZwOpenFile, for example) directly — completely sidestepping any hooks that EDR products have placed on the 32-bit ntdll.dll. WithSecure's analysis of a Lumma infection confirmed that the malware uses this technique to call ZwOpenFile through the 64-bit syscall path after resolving the ntdll base address from the 64-bit PEB.

This is particularly effective against security products that only hook the 32-bit API layer of WoW64 processes, which is the majority of EDR implementations. By switching to 64-bit execution, the malware's system calls pass through an entirely unmonitored code path.

The Trigonometry Trick: Anti-Sandbox via Mouse Movement

This is the technique that made headlines. LummaC2 v4.0 introduced an anti-sandbox mechanism that uses trigonometry to determine whether a human being is operating the mouse — and refuses to execute its payload until it is satisfied.

Automated malware sandboxes typically either do not generate mouse movement at all, or generate it synthetically — moving the cursor in straight lines, at regular intervals, or through scripted patterns. LummaC2 exploits this by capturing the cursor position at multiple points over time using GetCursorPos, then calculating the Euclidean distance between consecutive positions and the angle of movement using inverse trigonometric functions.

Specifically, the malware captures a sequence of cursor positions, computes the vector between each consecutive pair, and uses the arctangent function to derive the angle of movement. It then checks whether the resulting angles vary in a way consistent with natural human mouse behavior — meaning curves, direction changes, and non-uniform velocity. A sandbox that moves the cursor in a straight line from point A to point B will produce a consistent angle across all samples, which LummaC2 detects and rejects.

The key value in the implementation is a threshold angle of 45.0 degrees, which is stored in the stack-based control structure described earlier. The malware compares calculated angular differences against this threshold to determine whether the movement pattern is sufficiently "human." If the check fails, the malware enters a wait loop and re-checks periodically, effectively delaying detonation indefinitely until real user activity is detected.

Bypass

For analysts needing to detonate LummaC2 in a sandbox, the bypass is straightforward: inject realistic mouse movement into the analysis VM using a script that introduces random curves, variable speeds, and direction changes. The critical point is angular variance — straight-line movements at constant speed will fail the check every time. Alternatively, patching the conditional jump after the trigonometric comparison to always take the "human detected" branch will skip the check entirely.

EDR Evasion: ntdll Remapping and ETW-Ti Disabling

Beyond Heaven's Gate, LummaC2 employs additional techniques specifically targeting endpoint detection products.

ntdll Remapping

Modern EDR products work by injecting a monitoring DLL into every process at startup and placing inline hooks (detours) on key functions in ntdll.dll — the lowest user-mode layer before system calls enter the kernel. When the hooked function is called, execution is redirected to the EDR's inspection code before proceeding to the actual system call.

LummaC2 defeats this by remapping a clean copy of ntdll.dll from disk. The malware reads the original ntdll.dll file from the system directory, maps it into memory as a new section, and resolves function addresses from this clean copy rather than the hooked version already loaded in the process. Because the new mapping is loaded directly from disk, it contains no EDR hooks. System calls made through this remapped ntdll bypass all user-mode monitoring.

ETW-Ti Callback Disabling

Event Tracing for Windows Threat Intelligence (ETW-Ti) is a kernel-level telemetry source that security tools rely on to detect suspicious behavior like process injection, memory allocation in remote processes, and thread creation. Cybersecurity researchers at CyberPress documented that recent LummaC2 variants attempt to disable ETW-Ti callbacks, removing a critical data source from the security product's visibility. With ETW-Ti disabled, the malware can perform actions like remote memory allocation and thread injection without generating the kernel-level events that would normally trigger an EDR alert.

Additional Anti-Analysis Checks

LummaC2 also performs standard but thorough anti-analysis checks on execution. It calls GetForegroundWindow and compares window titles against known debuggers. It scans for DLLs associated with security tools loaded in the process space. It checks for sandbox-specific artifacts and virtual machine indicators. And in a common pattern among malware originating from Russian-speaking developers, it checks the system locale — if the language code is 0x419 (Russian), it terminates immediately to avoid infecting systems in that region.

String Encryption

Earlier versions of LummaC2 used a crude string obfuscation technique: inserting the junk string "edx765" into the middle of meaningful strings, then stripping it at runtime. Version 4.0 upgraded to XOR-based string encryption. Each encrypted string is decrypted at runtime by XORing with a key, and the configuration file retrieved from the C2 server is Base64-encoded and then XOR-encrypted using the first 32 bytes of the configuration as the key. This prevents static extraction of C2 addresses and target lists from the binary.

Delivery: ClickFix, EtherHiding, and Fake CAPTCHAs

LummaC2's delivery infrastructure is as engineered as its evasion. Microsoft documented multiple concurrent delivery campaigns throughout early 2025, each exploiting a different trust mechanism.

ClickFix and Fake CAPTCHAs

In the ClickFix technique, compromised or attacker-controlled websites display a fake error message — typically a browser verification prompt or CAPTCHA — that instructs the victim to "fix" a problem by pressing Windows+R and pasting a command. The pasted command is a PowerShell one-liner, base64-encoded, that downloads and executes the Lumma payload. In a campaign targeting Canadian users documented by Microsoft in April 2025, the PowerShell chain went through multiple stages: an initial mshta.exe command downloaded obfuscated JavaScript from an attacker-controlled IP, which executed a second PowerShell command, which downloaded more PowerShell code, which finally downloaded and launched the Lumma executable.

The entire chain runs fileless until the final payload — each intermediate stage executes in memory via legitimate Windows binaries (mshta.exe, powershell.exe), making network-level and file-system-level detection extremely difficult.

EtherHiding

In April 2025, Microsoft observed LummaC2 campaigns using EtherHiding — a technique that stores parts of the malicious code in smart contracts on blockchain platforms, specifically Binance Smart Chain (BSC). Because the code lives on the blockchain, traditional blocking methods like IP blacklisting, domain takedown, and content-based detection are ineffective. The smart contract serves as an immutable, censorship-resistant hosting platform for the malware's configuration or stage-two payload URL.

Fallback C2 via Steam Community

If all hardcoded C2 domains become unreachable — as happened during the May 2025 takedown — LummaC2 has a fallback mechanism. It generates new C2 URLs by parsing Steam Community profile usernames, which contain encrypted C2 addresses that are regularly rotated. This creates a resilient C2 channel that leverages a trusted, high-traffic platform unlikely to be blocked at the network level.

Detection and Defense

LummaC2 is sophisticated, but not invincible. Each of its evasion techniques has known detection vectors.

  1. Monitor for Heaven's Gate indicators. The 0x33 segment selector transition and RETF instruction sequence are detectable through behavioral rules. EDR products that instrument both the 32-bit and 64-bit ntdll paths will catch this. Process memory scans for the characteristic opcode sequence (push 0x33; call $+5; add [esp], 5; retf) can flag binaries using this technique.
  2. Detect ntdll remapping. A clean process should have exactly one mapping of ntdll.dll. A second mapping — especially one loaded via NtCreateSection or direct file reads of the ntdll on disk — is a strong indicator of EDR evasion. Memory forensics tools like Volatility can detect duplicate ntdll mappings.
  3. Watch for PEB access patterns. Legitimate applications rarely walk the PEB's InLoadOrderModuleList manually. Behavioral rules that flag manual PEB traversal (access to FS:[0x30] or GS:[0x60] followed by Ldr->InLoadOrderModuleList enumeration) can detect this common malware technique across families, not just Lumma.
  4. Block LOLBin abuse chains. The ClickFix delivery chain relies on mshta.exe spawning powershell.exe. Application control policies that restrict mshta.exe execution and monitor for PowerShell downloading remote content will disrupt the most common Lumma delivery vector.
  5. Implement credential hygiene. Lumma exists to steal credentials. MFA — particularly phishing-resistant MFA like FIDO2 — limits the value of stolen passwords. Session token rotation and short cookie lifetimes reduce the window for session hijacking via stolen cookies.
  6. Deploy YARA rules for known indicators. The MurmurHash2 API hashing implementation, the "edx765" string marker (still present in some variants), and the trigonometric function calls in combination with GetCursorPos are all viable YARA signatures.
rule LummaC2_AntiSandbox_Trigonometry {
    meta:
        description = "Detects LummaC2 trigonometry-based sandbox evasion"
        author = "NoHackie"
        date = "2026-02-12"
    strings:
        $api1 = "GetCursorPos" ascii
        $api2 = "atan2" ascii
        $math = { 00 00 00 00 00 80 46 40 }  // 45.0 double
        $cff  = { 83 F8 ?? 0F 87 }            // CFF dispatcher cmp/ja
    condition:
        uint16(0) == 0x5A4D and
        $api1 and $api2 and $math and $cff
}

The broader lesson from LummaC2 is structural. The May 2025 takedown was the largest coordinated action ever taken against a single infostealer, and it produced measurable disruption — for about two days. The malware's modular architecture, decentralized affiliate model, and geographic insulation of its core infrastructure allowed it to recover faster than any previous takedown target. As Selena Larson, staff threat researcher at Proofpoint, noted: "While we are still seeing some Lumma Stealer activity, disruptions can have impacts beyond infrastructure takedowns. All disruptions impose cost on threat actors."

That cost, however, was temporary. Lumma is still active, still evolving, and still the most widely used infostealer in the criminal ecosystem. Understanding how it works at the binary level is no longer optional for defenders — it is baseline knowledge.

Sources

  • Microsoft Digital Crimes Unit — "Disrupting Lumma Stealer: Microsoft leads global action against favored cybercrime tool" (May 21, 2025)
  • Microsoft Security Blog — "Lumma Stealer: Breaking down the delivery techniques and capabilities of a prolific infostealer" (May 21, 2025)
  • Outpost24 KrakenLabs — "Analyzing LummaC2 stealer's novel Anti-Sandbox technique: Leveraging trigonometry for human behavior detection" (November 2025)
  • Outpost24 KrakenLabs — "LummaC2 stealer: Everything you need to know" (November 2025)
  • WithSecure Labs — "Reverse engineering a Lumma infection" (2025)
  • Trend Micro — "Back to Business: Lumma Stealer Returns with Stealthier Methods" (July 22, 2025)
  • CyberPress — "Researchers Discover New Variant of Lumma InfoStealer Featuring Code Flow Obfuscation" (April 22, 2025)
  • Netskope Threat Labs — "Beyond Signatures: Detecting Lumma Stealer with an ML-Powered Sandbox" (September 25, 2025)
  • Check Point Research — "Lumma Malware: Unmasking the Stealthy Infostealer" (July 2025)
  • Europol / EC3 — Joint disruption statement (May 21, 2025)
  • FBI — Lumma Stealer infection estimates cited via CISA Joint Advisory AA25-141A (May 21, 2025)
  • IBM X-Force — 2025 Threat Intelligence Index (infostealer distribution data)
  • Lumu — "Advisory Alert: Lumma Stealer Rebounds After Takedown" (November 2025)
  • Palo Alto Unit42 — IDA Python CFF deobfuscation scripts (referenced by Outpost24)
  • Proofpoint (Selena Larson) — Post-disruption commentary via The Hacker News (May 28, 2025)
← all articles