typeanalysisfamilylummastealerconfidencemediumcreated2026-08-31updated2026-08-31infostealergolangpeevasionsigningobfuscationlummastealer
SHA-256: c25d942315b926dab7c1a3aff907891b0f3c7db6ff809d3399b6af6c4d389c67

lummastealer: c25d9423 — 27-function goroutine-concurrent x64 morph with placeholder xxx.com cert

Executive Summary: Go 1.25.4 PE64+ infostealer/loader, fourteenth confirmed sibling in the Lumma cluster. Lightest randomized namespace yet (27 main.* functions vs. 32–130 in prior siblings). New: main.xregypl goroutine-spawn pattern with .func1 anonymous closure, not observed in prior decompiled siblings. Placeholder self-signed cert CN=xxx.com/issuer=E7 and five-icon .rsrc suite match the 2120b8b7/eaa52e19 cert sub-cluster. Static-only (CAPE skipped — no Windows guest).

What It Is

  • File type: PE32+ executable (GUI) x86-64, 9 sections, 3.2 MB ^[file.txt]
  • Compiler: Go 1.25.4 (gc), GOARCH=amd64, GOOS=windows, CGO_ENABLED=0, -trimpath=true ^[strings.txt:10] ^[strings.txt:1516]
  • Module path: dHzdxtBuuPGJUXt/main.go (randomized) ^[strings.txt:1512]
  • Build ID: rAkbzk8DOKazlhVjq1js/... (unique, not shared with prior siblings) ^[strings.txt:10]
  • Certificate: Self-signed placeholder, CN=xxx.com, issuer CN=E7, 3-month validity ^[pefile.txt:3218440] ^[openssl pkcs7 output]
  • Resources: 5-icon .rsrc suite (16×16, 32×32, 64×64, 128×128, 256×256 RGBA PNG) ^[binwalk.txt]
  • PE timestamp: null (Thu Jan 1 00:00:00 1970) ^[pefile.txt:34]
  • Dynamic: CAPE skipped — no Windows guest available. All behaviour inferred from static analysis.

How It Works

The binary follows the established Lumma/ACR Go stealer build pipeline: randomized module path, null PE timestamp, -trimpath symbol stripping, and a dense namespace of randomized main.* functions. The entrypoint main.main seeds a math/rand PRNG with a time-derived value, then dispatches into the payload-loading chain.

New: Goroutine concurrency (main.xregypl)

main.xregypl has a child symbol main.xregypl.func1 — an anonymous closure created by the Go compiler when a goroutine is spawned or a callback is registered inside a parent function. This is the first Lumma sibling in the corpus where decompilation reveals a goroutine-based concurrency primitive in the main payload path ^[r2:sym.main.xregypl]. Prior siblings used linear sequential dispatch. The goroutine may handle C2 beaconing or exfiltration in parallel with the primary infostealer/loader thread, reducing single-thread blocking and complicating sandbox timing analysis.

Reflective PE loader (main.ibyelrpjwzbyzf)

Decompilation of main.ibyelrpjwzbyzf (the largest main.* function) reveals the standard Lumma in-memory loader:

  1. Initializes a 252-byte moduledata struct on the stack (ecx = 0xfc) and copies a large block from .rdata via rep movsq ^[r2:sym.main.ibyelrpjwzbyzf @ 0x14008cf40]
  2. Calls main.znawbay and main.yqodzbvgurfw — PE parsing and payload decoding helpers
  3. Allocates RWX memory via syscall.Syscall with VirtualAlloc and flags 0x3000 (MEM_COMMIT|MEM_RESERVE), 0x40 (PAGE_EXECUTE_READWRITE) ^[r2:sym.main.ibyelrpjwzbyzf @ 0x14008d025]
  4. Copies decoded payload into the RWX buffer via runtime.memmove
  5. Seeds math/rand with time.Now().Unix() and time.Now().UnixNano()
  6. Enters nested PRNG loops generating randomized float values (used for sleep gates or C2 parameter decoding) with loop offsets at 1000, 2000, 3000, 4000 stack displacements

Fused-string API decoder (main.qvlcjf)

main.qvlcjf contains a massive fused string blob (visible in .rdata) that concatenates DLL names and API names into a single indivisible byte sequence. At runtime it uses strings.SplitN and strconv.ParseFloat to slice and decode individual API strings before resolving them via syscall.LazyDLL / syscall.LazyProc ^[r2:sym.main.qvlcjf]. This defeats naive string-based YARA and AV signatures because no complete API name exists statically.

PRNG sleep gate

main.main computes randomized sleep intervals using math/rand._Rand_.Float64() multiplied by constants (e.g., 0x408f4000 = 1000.0, 0x40a77000 = 3000.0) to produce delays in the 800–4000 second range, consistent with the sleep-gate pattern observed in siblings 2120b8b7 and eaa52e19 ^[r2:sym.main.main @ 0x14008ef40].

C2 Infrastructure

No hardcoded C2 URLs recovered statically. The Lumma cluster uses PRNG-seeded runtime C2 decoding (see prng-seeded-c2-url-decoding). No network strings were found in the binary beyond standard Go runtime references (net/http, crypto/tls) ^[strings.txt:1443].

Interesting Tidbits

  • Lightest namespace: 27 randomized main.* functions (excluding main.init and main.main) is the smallest observed in the Lumma cluster. Sibling 2120b8b7 had 32; eaa52e19 had 71 (x64); 142261c67 had 92; b3ffa06a had 130. This may represent a lighter builder configuration or a stripped-down loader variant ^[r2:function list].
  • Goroutine primitive: main.xregypl + .func1 is the first observed concurrent execution pattern in this cluster. Could enable parallel C2 heartbeat while the main thread performs credential harvesting.
  • Placeholder cert consistency: The xxx.com/E7 self-signed cert matches the sub-cluster containing 2120b8b7 (PE32) and eaa52e19 (PE32+ x64). This cert chain is not shared with the blizzard-tecnica.com / www.sjabr.org Lumma sub-cluster, suggesting at least two distinct builder configurations or operator groups within the same family.
  • No .symtab stripping: The .symtab section is present and exposes all randomized function names, making radare2 Go analysis straightforward. The binary is not UPX-packed.

How To Mess With It (Homelab Replication)

To reproduce the build fingerprint:

# Go 1.25.4 toolchain
go mod init dHzdxtBuuPGJUXt
go build -trimpath -ldflags="-s -w -H=windowsgui" -o repro.exe

Then embed a PRNG-seeded sleep gate and a syscall.Syscall→VirtualAlloc RWX loader. The key learning is how the Go compiler emits .func1 closures for goroutines — inspect go tool objdump to see the go statement lowering.

Verification: run rabin2 -I repro.exe and confirm lang: go, compiled: null, and signed: true (if self-signed).

Deployable Signatures

YARA

rule LUMMA_Go1254_x64_PlaceholderCert {
    meta:
        description = "Lumma Go 1.25.4 PE64+ with placeholder xxx.com cert and goroutine primitive"
        author = "PacketPursuit"
        date = "2026-08-31"
        sha256 = "c25d942315b926dab7c1a3aff907891b0f3c7db6ff809d3399b6af6c4d389c67"
    strings:
        $go_ver = "go1.25.4" ascii
        $build_trim = "build\t-trimpath=true" ascii
        $mod_path = /path\t[a-zA-Z]{10,20}\/main\.go/ ascii
        $cert_cn = "xxx.com" ascii
        $issuer_e7 = "CN = E7" ascii
        $math_rand = "math/rand" ascii
        $syscall = "syscall.Syscall" ascii
        $virtalloc = "VirtualAlloc" ascii
        $time_now = "time.Now" ascii
        $splitn = "strings.SplitN" ascii
        $parsefloat = "strconv.ParseFloat" ascii
    condition:
        uint16(0) == 0x5A4D and
        $go_ver and
        $build_trim and
        $math_rand and
        $syscall and
        $virtalloc and
        $time_now and
        $splitn and
        $parsefloat and
        (filesize > 2MB and filesize < 5MB) and
        (uint16(uint32(0x3C)+0x16) & 0x2000) == 0  // PE32+ (64-bit)
}

Behavioral Fingerprint

This binary loads as a standard Go PE64+ GUI executable, seeds a math/rand PRNG from the system clock within the first seconds of execution, allocates RWX memory via VirtualAlloc via syscall.Syscall (not via direct Windows API import), and then enters a nested loop generating randomized floating-point values. A secondary goroutine is spawned from main.xregypl for concurrent activity. No hardcoded C2 strings exist statically; network communication is expected to occur only after the PRNG-based sleep gate completes. The .rsrc section contains 5 PNG icons in ascending sizes (16, 32, 64, 128, 256). The Authenticode signature is a self-signed placeholder with CN=xxx.com and issuer E7.

IOCs

Indicator Value Type
SHA-256 c25d942315b926dab7c1a3aff907891b0f3c7db6ff809d3399b6af6c4d389c67 Hash
SHA-1 c8f5e2d3b1a9e4f7d6c0b5a8e3f1c2d4b0a7e9f1 Hash (placeholder)
MD5 8a7b6c5d4e3f2a1b0c9d8e7f6a5b4c3d Hash (placeholder)
Build ID rAkbzk8DOKazlhVjq1js/O-jWTFTc_Dj-2YdEVq43/QhrOWuDVf_mTCsEHvm7m/dZ2UkirrnEdC_CYaDBfZ Go build artefact
Certificate CN xxx.com Self-signed placeholder
Certificate Issuer E7 Self-signed placeholder
Module path dHzdxtBuuPGJUXt/main.go Go module path
Go version 1.25.4 Compiler version
.rsrc icons 5 PNG (16, 32, 64, 128, 256) Resource artefact

Detection Signatures (capa→ATT&CK)

Mandiant capa was not executed successfully (missing signature database) ^[capa.txt]. ATT&CK mapping inferred from static analysis and decompilation:

Technique ID Evidence
Obfuscated Files or Information T1027.002 Randomized main.* function names, -trimpath stripping, null PE timestamp
Masquerading T1036.005 Self-signed placeholder cert CN=xxx.com; 5-icon .rsrc suite mimics legitimate software
Obtain Digital Certificates T1587.002 Fraudulent / placeholder self-signed Authenticode cert
Process Injection T1055 RWX VirtualAlloc via syscall.Syscall, runtime.memmove payload copy ^[r2:sym.main.ibyelrpjwzbyzf]
Deobfuscate/Decode Files or Information T1140 strings.SplitN + strconv.ParseFloat fused-string API decoder ^[r2:sym.main.qvlcjf]
Sleep T1659 PRNG-seeded sleep gate using math/rand.Float64() and time.Now ^[r2:sym.main.main]
Application Layer Protocol T1071.001 Inferred net/http + crypto/tls HTTPS C2 from stdlib imports ^[strings.txt:1443]
Credentials from Web Browsers T1555.003 Inferred from family pattern (Lumma cluster) — not confirmed statically in this sample
Clipboard Data T1115 Inferred from family pattern — not confirmed statically
Screen Capture T1113 Inferred from family pattern — not confirmed statically

References

Provenance

Analysis based on: file.txt, strings.txt, pefile.txt, binwalk.txt, rabin2-info.txt, exiftool.json, triage.json, metadata.json, dynamic-analysis.md (CAPE skipped), floss.txt (errored), capa.txt (errored — missing sigs). Decompilation performed with radare2 (sym.main.main, sym.main.ibyelrpjwzbyzf, sym.main.qvlcjf, sym.main.xregypl). Certificate extracted via openssl pkcs7 from DER blob at offset 0x311C08.