Tracking the C2 Infrastructure Behind a Lumma Stealer Spread Through itch.io

Mehmet Akif Mehmet Akif
Jul 14, 2026 14 min read 189 views
Share:
Tracking the C2 Infrastructure Behind a Lumma Stealer Spread Through itch.io

Tracking the C2 Infrastructure Behind a Lumma Stealer Spread Through itch.io

A follow-up to G DATA's December 2025 report: from the delivery chain to the C2 infrastructure


A note on framing. This is not a discovery write-up; it's a follow-up and enrichment piece. The sample I analyzed is the publicly documented one from the campaign G DATA covered in December 2025 (a2bacb00dfdb338b496d3128705f76c8cc935e6bd33e06271fb3e34d769d0a2b). I'm not the one who first unraveled the delivery chain. G DATA did. I also pulled the Command & Control (C2) data from VirusTotal's sandbox report rather than from my own static extraction, and below I'm honest about why that extraction attempt failed. What this write-up contributes is the part G DATA left out: compiling, verifying, and enriching the C2 and hosting infrastructure through passive OSINT. Most of the work in CTI isn't discovering something new. It's turning scattered pieces into a verified, actionable whole, and that's what this post tries to do.


TL;DR

  • Fake "update" links dropped into itch.io comment sections and Patreon pages push victims toward a .zip. The game.exe inside it is a nexe-compiled Node.js loader that, once run, loads a Lumma Stealer into memory.
  • G DATA unraveled the technical chain but published only four hashes as IOCs, with no C2.
  • This post closes that gap: a primary C2 at complexideasmadesimple[.]com (behind Cloudflare), a fallback IP, a secondary payload dropper, and the infrastructure hosting all of it, a Seychelles-registered, abuse-tolerant provider (Omegatech Ltd / AS202412).
  • The timeline is telling. The C2 domain was registered on October 19, 2025, just ahead of G DATA's December report. Fresh infrastructure.

0. Context: how you stumble onto lures like this

One morning I was poking around Google looking for a new game to play, and I found one that caught my eye on itch.io. While reading through the comments on its page, I noticed that some users were posting links to external sources, sharing zip and rar files. That, in itself, is fertile ground for spreading malware. People who are enthusiastic about something tend to burn through content that excites them, whether it's a new update, a fan mod, or anything that sparks curiosity, very quickly. And that's exactly what makes even people who normally wouldn't fall for a trap fall for one.

Afterward, while searching to see whether anyone had already written about this, I came across a G DATA article from December 2025 describing Lumma Stealer being distributed through itch.io. That report laid out the malware's technical chain very well and provided the IOC hashes for the sample. So I decided to analyze the very same malware G DATA had analyzed.

Track Malware Analysis like this every Monday.

Every Monday, the 5 threats SOC teams can't afford to miss — with analyst commentary.

What follows is that analysis: a single concrete instance of this pattern, taken apart from the outside in.


1. The delivery chain, outside in

Step 1: Distribution. itch.io comments and Patreon links lead to Updated Version.zip.

Step 2: The archive. Inside the zip is game.exe. It isn't a game; it's a nexe-compiled Node.js application. nexe bundles a Node.js project into a single executable, packing the Node runtime plus the application's JS into one PE. It's a legitimate tool, being abused here. (G DATA flagged this as a notable example of nexe abuse seen in the wild.)

Step 3: The embedded JS. nexe appends the application's JS to the end of the runtime and marks it with a sentinel: <nexe~~sentinel>. To find the actual malicious logic, you don't need to wade through 400,000-plus lines of Node runtime. You just carve out the payload that sits after this sentinel.



2. Deobfuscation: obfuscator.io and four "paste artifacts"

The carved-out JS was obfuscated with obfuscator.io, using the classic string-array pattern. Every string is collected into a single array, shuffled by a rotation IIFE, and pulled back out through a decoder function named f(). The right tool for this is webcrack.

But before I could hand it to webcrack, the source wouldn't pass node --check. The syntax had been corrupted somewhere during extraction/transfer. Four distinct artifact types surfaced one at a time, each node --check error pointing to the next:

# Corrupted Should be Pattern
1 == = === triple comparison
2 != = !== general <op> = pattern
3 = > => arrow function
4 /\s + / g /\s+/g whitespace inside a regex

A short Node script cleaned all four in one pass:

const fs = require('fs');
let s = fs.readFileSync('payload.js', 'utf8');
s = s.replace(/([=!<>])=  =/g, '$1==');   // === !== >== <== first
s = s.replace(/=\s+>/g, '=>');            // arrow: = >  ->  =>  (after ===)
s = s.replace(/>  >/g, '>>').replace(/<  </g, '<<');
s = s.replace(/&  &/g, '&&').replace(/\|  \|/g, '||');
s = s.replace(/\/\\s \+  \/ g/g, '/\\s+/g');
fs.writeFileSync('payload_clean.js', s);
console.log('done, len:', s.length);

There was also a key side finding, an anti-analysis gate readable with the naked eye, no deobfuscation required:

const m = os.totalmem() / 0x40000000;   // 0x40000000 = 1 GB
const n = os.cpus().length;
(m < 0x4 || n <= 0x2) && process.exit();  // RAM < 4GB or cores <= 2 => exit

This line explains why automated sandboxes couldn't "detonate" the sample: most sandboxes run with 2 cores / low RAM, the gate closes, and the malware terminates itself. G DATA documented six anti-analysis layers in total: RAM/cores; a sandbox username list; a list of analysis processes (fakenet, wireshark, ida64, x64dbg, and so on); the GPU name (via WMI win32_VideoController); a screen refresh rate below 29 Hz; and the disk model (vbox/vmware/qemu).

When I ran webcrack, the output was clean:

String Array: e, length 308
String Array Rotate: yes
String Array Decoders: f
inline-decoded-strings: 513 changes

A 308-element string array, the f() decoder, and 513 decoded strings inlined back into the source. I now had readable JS.


3. Two embedded executables

The deobfuscated source held two long Base64 blobs, both starting with TVqQAA…, the Base64 encoding of the MZ header, which is the Windows PE signature. So the JS had two PEs embedded inside it.

Decoding and writing them to disk (without executing them):

File Size What it is
stage2_0 217,600 B Native N-API addon (modules.node), the loader
stage2_1 809,472 B The actual payload (echoforge.exe), Lumma

What the JS does with these blobs lays out the whole architecture:

const d = path.join(os.tmpdir(), "modules.node");
await fs.writeFile(d, Buffer.from(blob0, "base64"));   // stage2_0 to disk
const g = require(d);                                    // native addon loads
if (typeof g.PodstilkaBidena !== "function") throw new Error("Invalid");
g.PodstilkaBidena(Buffer.from(blob1, "base64"));         // stage2_1 into MEMORY

So stage2_0 is written to %temp% as modules.node and loaded with require(); the second PE (stage2_1) is then passed as an argument to the addon's exported PodstilkaBidena function and loaded into memory. No .exe ever touches disk, only the .node. That's why AV and automated tooling looking for a dropped .exe miss it.

A note: PodstilkaBidena ("Biden's doormat") and the Suka error string in the loader carry Russian connotations. But Lumma is a Malware-as-a-Service, so this is an affiliate's build, not the work of whoever wrote Lumma. The most you can say is "Russian-speaking affiliate, low confidence"; you can't attribute it to a group.


4. Identifying the payload: Lumma Stealer

I examined stage2_1 in Detect It Easy (DIE):

  • Native x64 PE, written in C (Compiler: MSVC 19.29, VS2019 v16.11). Not .NET, so there's no dnSpy/decompile route; this is native reverse engineering.
  • No external packer signature. Entropy map: .text at 6.58 (normal for native code), .rdata at 5.57 (not packed), whole file "not packed (79%)". So this is an unpacked payload, with no UPX/Themida layer over it.
  • Fake version metadata: echoforge.exe, "AetherForge Labs", "Cryonix Engine", "Stream Data Processing Framework", v2.8.63, a 2012 copyright, all fabricated. No such company or product exists; it's there to pass as legitimate software.
  • VirusTotal's sandbox report captured the string Do you want to run a malware?... in memory at runtime. This string doesn't exist statically in the payload (it's encrypted, like the config) and only surfaces at runtime.

VirusTotal confirmation: 49 of 66 engines flag it as malicious; the Zenbox label reads STEALER / TROJAN / EVADER. The payload hash (a2bacb00…) matches G DATA's reported Lumma payload exactly, so this is unquestionably the same sample and the same campaign. (The modules.node hash 1d405b03… matches G DATA's as well.)


5. An honest failure: my static config extraction attempt

I tried to extract the C2 statically from the payload, without running it, by decrypting the config. Explaining how that attempt failed may be more instructive than the single IOC it would have produced.

Lumma keeps its config encrypted inside .rdata. Expecting an encrypted block to stand out by high entropy, I ran an entropy scan. A single high-entropy island turned up, around 0x7e000, at entropy 7.35. "There's the config," I thought. But looking at the hex:

0x7e020: 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f
0x7e030: 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f
...
0x7e0a0: 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f

This wasn't encrypted data. It was a lookup table where every byte value appears exactly once, in order (0x00 to 0xFF). That's precisely why it produced high entropy: a uniform distribution is maximum entropy. High entropy doesn't mean randomness; order produces high entropy too. A classic false positive.

The real reason no plaintext C2 ever came out I learned afterward: since January 2025, Lumma has used ChaCha20 instead of XOR for config decryption (a change eSentire documented). The structure is 16 bytes of magic, a 32-byte key, an 8-byte nonce (padded to 12 with four nulls), and then the encrypted C2 data; the key/nonce differ from sample to sample. On top of that, because the payload uses Control Flow Flattening and syscall/Heaven's Gate, its import table is atypical, which is why the imphash (fd6cd08c…) is nearly unique and imphash-based hunting is useless against this family. These are real obstacles that make static extraction significantly harder.

The call: rather than burning hours on a manual ChaCha20 offset hunt, I took the ground truth from VirusTotal's sandbox report and enriched it with passive OSINT.


6. C2 infrastructure

6.1 Confirmed C2 / network indicators (VT sandbox, high confidence)

The beacons the sandbox observed show Lumma's characteristic URL pattern: a random path plus an odd extension.

https://complexideasmadesimple[.]com/yF4Ipr4mShEoCvtdnYR4L6LHRMEO7kVJ/752bdr3i.nxnnd
https://158.94.208[.]98/yF4Ipr4mShEoCvtdnYR4L6LHRMEO7kVJ/752bdr3i.nxnnd

Secondary payload dropper:

http://178.16.52[.]82/GaAgU0eHWeSJ9Ia5lhlz4PuhckC2bNOv/1BOi0tXTJJWgZS1BzlecvJPgUWQPYe3K.exe
http://178.16.52[.]82/GaAgU0eHWeSJ9Ia5lhlz4PuhckC2bNOv/8GVk01wwWXHHto7BJ1pwBajM8YOnUuQf.exe
Indicator Type Note
complexideasmadesimple[.]com Primary C2 Behind Cloudflare
158.94.208[.]98 C2 / fallback IP Direct beacon
178.16.52[.]82 Secondary payload dropper Pulls 2 additional .exe

TLS / JA3:

SNI         complexideasmadesimple[.]com
Thumbprint  3ba7e9f806eb30d2f4e3f905e53f07e9acf08e1e
JA3         5ee1dbcc205a447afd485796a3511bf1
JA3         839e17dc9efe87a1a0c474f61a114dc8
JA3         ac16e93e717c02fdeeba8cd9e48a0eda

On noise: evdocmtlhlrtdannemtzcqi.ni showed up in a memory pattern but is likely a decode artifact or partial string, so I'm not reporting it as C2. NTP servers, cloudflare-dns.com, and *.pki.goog calls are benign OS / DoH noise, which I excluded.

6.2 Hosting infrastructure (passive OSINT)

The strongest correlation is that both malicious IPs sit with the same provider.

  • Omegatech Ltd, registered in Seychelles (offshore); IP location Frankfurt, Germany; AS202412.
  • Seychelles offshore registration, its own autonomous system, and Frankfurt hosting together form a classic abuse-tolerant / bulletproof profile. Legitimate operations don't hide their infrastructure behind Seychelles; that structure is chosen to dodge abuse complaints and takedowns.

The C2 domain's WHOIS clarifies the timeline:

Domain      complexideasmadesimple[.]com
Registered  2025-10-19
Expires     2026-10-19
Registrar   CNOBIN INFORMATION TECHNOLOGY LIMITED ([email protected])
Status      clientTransferProhibited
NS          angelina.ns.cloudflare.com / decker.ns.cloudflare.com

The domain was registered on October 19, 2025, just before G DATA's December report. The use of Cloudflare NS lets the real C2 IP hide behind Cloudflare's reverse proxy, which is why VT doesn't show a direct origin IP for the domain. So the domain isn't "IP-less"; it's behind Cloudflare.

6.3 Related infrastructure (medium confidence)

158.94.208[.]98 also hosts a .top cluster that is separately flagged as malicious:

Domain Status
nmso3[.]top 8 warnings
paynmt[.]top 7 warnings
pmntso[.]top 5 warnings
app-subito[.]top same IP
global-apps[.]top same IP

The naming profile (paynmt, pmntso, app-subito) carries financial-phishing/panel connotations. These are not this sample's C2. They're related but separate infrastructure sitting on the same server. I'm reporting them as "medium confidence, same infrastructure."

6.4 What I'm not reporting (shared-hosting noise)

Domains on 178.16.52[.]82 such as katariasecurities[.]com, mydancemirrorparty[.]com, northeastinbcc[.]com, and wethepeople[.]community are most likely shared hosting, and I couldn't tie them to this campaign. Reporting them as C2 would be both wrong and unfair to innocent site owners. This is the classic trap of reverse-IP results: a single IP can host dozens of unrelated domains.


7. Confidence levels

  • High: the C2/IPs the VT sandbox showed beaconing directly (complexideasmadesimple[.]com, 158.94.208[.]98, 178.16.52[.]82); the hosting infrastructure (Omegatech / AS202412).
  • Medium: the flagged .top cluster on the same IP.
  • Low / uncertain: the .ni artifact; the affiliate-language inference (PodstilkaBidena / Suka).
  • Excluded: OS/NTP/DoH noise; the shared-hosting .com domains.

8. Victim-side behavior (VT sandbox summary)

The data Lumma targets in this sample lines up with the family's known profile:

  • Crypto wallets: Bitcoin, Dogecoin, Litecoin, Qtum, Monero (registry keys)
  • Browsers: Chromium-based, including cookies and extension data
  • Email / sessions: Outlook, The Bat!, PuTTY sessions, Windscribe VPN
  • UAC bypass: CMSTP, via cmstp.exe /au plus %temp%\tmp.ini (Sigma "high")
  • Dropped files: go9181h.exe, pMzC2hY-.exe into %AppData%\Local\Microsoft\

9. IOC appendix

Hashes

# Delivery chain (G DATA's original IOCs)
Updated Version.zip   SHA256  79250523a057a7dd9a6080099c8c2f83eb683ab9b37ecab149fc73524f7c4bd1
game.exe              SHA256  102b99b00a60f33246bd89bd2b3cb9cfae2844d453484e932b3a5ca634fb308c
mains.js              SHA256  80e538cabade94e1883f9e72bb608dc02f79808aec48136b5bbb00c2a1717f64
modules.node          SHA256  1d405b03bc5913b6b43c06550ef0b9b02196b270625e4dc5fa0c37e8a424be25

# Lumma payload (echoforge.exe)
                      SHA256  a2bacb00dfdb338b496d3128705f76c8cc935e6bd33e06271fb3e34d769d0a2b
                      SHA1    2064fc6bb6f8b252655940dee26e252bf677668b
                      MD5     8ec0c83b92ce415c3c4c13f47094fa35
                      imphash fd6cd08ccd9f2d990549b215e2509ff2
                      authentihash 1ab40234f9d7847db44d16d6b7d9f0b599cf916e823e41b6c25c8a64d580d5d7

C2 / network (high confidence)

complexideasmadesimple[.]com            # primary C2 (Cloudflare-fronted)
158.94.208[.]98                         # C2 / fallback IP
178.16.52[.]82                          # secondary payload dropper

Beacon / URL pattern

https://complexideasmadesimple[.]com/yF4Ipr4mShEoCvtdnYR4L6LHRMEO7kVJ/752bdr3i.nxnnd
https://158.94.208[.]98/yF4Ipr4mShEoCvtdnYR4L6LHRMEO7kVJ/752bdr3i.nxnnd
http://178.16.52[.]82/GaAgU0eHWeSJ9Ia5lhlz4PuhckC2bNOv/1BOi0tXTJJWgZS1BzlecvJPgUWQPYe3K.exe
http://178.16.52[.]82/GaAgU0eHWeSJ9Ia5lhlz4PuhckC2bNOv/8GVk01wwWXHHto7BJ1pwBajM8YOnUuQf.exe

Related infrastructure (medium confidence)

nmso3[.]top  paynmt[.]top  pmntso[.]top  app-subito[.]top  global-apps[.]top   # on 158.94.208[.]98

TLS / JA3

SNI         complexideasmadesimple[.]com
thumbprint  3ba7e9f806eb30d2f4e3f905e53f07e9acf08e1e
JA3         5ee1dbcc205a447afd485796a3511bf1 / 839e17dc9efe87a1a0c474f61a114dc8 / ac16e93e717c02fdeeba8cd9e48a0eda

Infrastructure

Omegatech Ltd  :  Seychelles registration / Frankfurt hosting / AS202412

Host indicators

%AppData%\Local\Microsoft\go9181h.exe
%AppData%\Local\Microsoft\pMzC2hY-.exe
%Temp%\modules.node
export: PodstilkaBidena   (modules.node native N-API addon)

No active probing or scanning was performed against the C2 infrastructure; all infrastructure observation was drawn from passive sources (WHOIS, passive DNS, VT).


10. Sources

  • G DATA, LummaStealer dropped via fake updates from itch.io and Patreon (2025-12-08, J. Grana)
  • eSentire, Lumma Stealer updated to use ChaCha20 cipher for config decryption (2025-01)
  • Outpost24 / KrakenLabs, LummaC2: everything you need to know (2025)
  • Microsoft, Lumma delivery & capabilities (2025-05)
  • VirusTotal, sample a2bacb00… sandbox report
  • networksdb / WHOIS, passive infrastructure data
Mehmet Akif

Mehmet Akif

CTI Analyst

CTI Digest · Every Monday, 9:00 (Europe/Istanbul)

Track Malware Analysis threats like this — every Monday.

Every Monday, the 5 threats SOC teams can't afford to miss — with analyst commentary.

Comments (0)

Leave a Comment

* Required fields. Privacy Policy