typeanalysisfamilylummastealerconfidencemediumcreated2026-08-26updated2026-08-26infostealermalware-familygolangobfuscationc2
SHA-256: b3ffa06a189a3454d74ee20e24d7c6a4c49673c360d9fc7cc0423e263f0fcbf8

lummastealer: b3ffa06a — Go 1.25.4 PE32, 14-icon .rsrc suite, invalid certificate table, PRNG sleep gate

Executive Summary

Go 1.25.4 PE32 infostealer with 130 randomized main.* functions, a 14-icon .rsrc suite, and an invalid Authenticode certificate table that points beyond EOF. Shares the PRNG sleep gate (800–1120 s) and dense namespace with the Lumma cluster, but carries no valid signing — neither the blizzard-tecnica.com R12 chain nor the ACR quiverquant.com chain. Static-only; CAPE skipped (no Windows guest).

What It Is

  • File: PE32 executable (GUI) Intel 80386, 7 sections, 2.94 MB ^[file.txt]
  • Compiler: Go 1.25.4+, GOARCH=386, GOOS=windows, CGO_ENABLED=0, -trimpath=true ^[strings.txt:1663-1671]
  • Module path: LkYepTgpfGoTJPv (randomized, 16-char mixed-case) ^[strings.txt:1663]
  • Build ID: BVrnoOrAVVaYdOlHLAPK/cOUBfNGrV1efNoya0Gh2/IGI22km3b5jkeMNXyJTd/7zDSX1Qeu_ZisY8QI7oe ^[strings.txt:8]
  • PE timestamp: null (1970-01-01 00:00:00) in all headers and resource directories ^[pefile.txt:34,274,328,339,350,370,390,410,430,451]
  • Signing: none valid. Security directory VA = 0x46DA00 (4,643,328), file size = 2,944,978 — points beyond EOF. rabin2 flags Invalid certificate table / signed: false. ^[rabin2-info.txt:1,28] ^[pefile.txt:232-234]
  • Resources: .rsrc present (~57 KB). 14 RT_ICON entries (16×16, 32×32, 64×64, 128×128, 256×256 RGBA PNG) plus RT_GROUP_ICON. ^[binwalk.txt:8-17] ^[pefile.txt:333,445]
  • Function count: 130 randomized main.* names (densest Lumma sibling observed). ^[strings.txt]

How It Works

This is a cluster sibling of lummastealer. The threat logic is concealed behind standard Go obfuscation patterns documented on the entity page. Distinctive features of this sample:

  1. Broken certificate table — unlike siblings 040e0d76 through 46e32500 which carry the blizzard-tecnica.com / R12 Let's Encrypt chain, this sample has a security directory that references memory outside the file. No valid Authenticode. This may represent a builder misconfiguration, an unsigned test build, or deliberate stripping.

  2. 14-icon .rsrc suite — larger than the typical 4-icon set seen on 040e0d76 and 7b74bea7. The builder clearly has an icon-toggle with variable quantity.

  3. PRNG sleep gate — main.main seeds math/rand with hardcoded 64-bit constants (0xd7b17f80 upper, 0xa1b203eb lower, 0x3d1a0000 delta), then sleeps Intn(0x320) + 0x320 = 800–1120 seconds before network activity. ^[r2:sym.main.main @ 0x49d820] This matches the gate observed in siblings 46e32500 and 142261c674f9.

  4. No static C2 — consistent with the cluster's runtime C2 decoding via prng-seeded-c2-url-decoding. No domain, IP, or URL strings recovered.

  5. Process manipulation imports — VirtualAlloc, CreateThread, ResumeThread, SetThreadContext, GetThreadContext, LoadLibraryW, LoadLibraryExW, GetProcAddress all imported statically via syscall stubs. ^[strings.txt:6053-6075]

Decompiled Behavior

Ghidra was not run (static-only pipeline). radare2 level-2 analysis recovered 2191 functions. Entry point is standard _rt0_386 Go runtime bootstrap (0x473250). main.main (0x49d820) performs:

  • Allocate math/rand RNG source and seed with composite constants.
  • Call main.skwogikfupwtfn (likely string decoder / API resolver).
  • Sleep via math/rand.(*Rand).Intn(0x320) + 0x320.
  • Call main.qxvfumjqexrbi (likely C2 connector / beacon).
  • Additional PRNG-derived timing loops feeding main.sbkoaiqhtm, main.iqtypn, and main.szqhkacm (payload stages).

The repeated pattern — seed → decoder → sleep → beacon → stage — is identical to siblings 46e32500 and 142261c674f9. ^[r2:sym.main.main]

C2 Infrastructure

No static C2 recovered. C2 is decoded at runtime via PRNG transform, consistent with prng-seeded-c2-url-decoding. No hardcoded domains, IPs, or URLs in strings.

Interesting Tidbits

  • Certificate table beyond EOF is unusual. Most Lumma siblings are signed (self-signed www.sjabr.org or Let's Encrypt R12 blizzard-tecnica.com). This sample may be an unsigned builder output or a post-processing strip.
  • 14 icons is the largest .rsrc suite in the Lumma cluster so far; previous max was ~8.
  • 130 main.* functions is the densest randomized namespace observed in this cluster, exceeding 142261c674f9 (92 functions).
  • capa and floss both failed on this sample — capa missing signatures, floss argument-parsing error. Reinforces the need for manual Go string analysis.

How To Mess With It (Homelab Replication)

Build a comparable Go binary:

go version   # need 1.25.4+
export GOOS=windows GOARCH=386 CGO_ENABLED=0
go build -trimpath -ldflags="-s -w -H=windowsgui" .

Target a binary with:

  • 100+ short randomized function names in main package
  • math/rand seed with hardcoded 64-bit composite
  • Sleep gate rand.Intn(800) + 800
  • syscall.LoadLibrary / syscall.GetProcAddress for runtime API resolution
  • Optional: embed multiple PNG icons via go:embed + github.com/akavel/rsrc

Verification: run rabin2 -I reproducer.exe — should show lang: go, signed: false, stripped: false, and a dense sym.main.* namespace.

Deployable Signatures

YARA rule

rule LUMMA_Go1254_PRNG_SleepGate {
    meta:
        description = "LummaStealer Go 1.25.4+ PE32 with PRNG sleep gate and dense randomized main namespace"
        author = "PacketPursuit"
        date = "2026-08-26"
        sha256 = "b3ffa06a189a3454d74ee20e24d7c6a4c49673c360d9fc7cc0423e263f0fcbf8"
    strings:
        $go_build = "go:buildid"
        $mod_path = /path\t[a-zA-Z]{16}/
        $trimpath = "build\t-trimpath=true"
        $cgo_off = "build\tCGO_ENABLED=0"
        $goarch = "build\tGOARCH=386"
        $goos = "build\tGOOS=windows"
        $seed1 = { 80 7F B1 D7 }
        $seed2 = { EB 03 B2 A1 }
        $virtalloc = "VirtualAlloc"
        $createthread = "CreateThread"
        $resume = "ResumeThread"
        $setctx = "SetThreadContext"
        $getctx = "GetThreadContext"
    condition:
        uint16(0) == 0x5A4D and
        6 of ($go_build, $mod_path, $trimpath, $cgo_off, $goarch, $goos) and
        2 of ($seed1, $seed2) and
        3 of ($virtalloc, $createthread, $resume, $setctx, $getctx) and
        #mod_path >= 1
}

Behavioral fingerprint

This binary is a Go 1.25.4 PE32 with a null PE timestamp, 100+ randomized main.* functions, and standard Go runtime strings. On execution it seeds math/rand with hardcoded constants, sleeps 800–1120 seconds, then resolves APIs via syscall.LoadLibrary/GetProcAddress and initiates HTTPS C2. No hardcoded network indicators are present in the file.

IOC list

Indicator Value Type
SHA-256 b3ffa06a189a3454d74ee20e24d7c6a4c49673c360d9fc7cc0423e263f0fcbf8 hash
Build module LkYepTgpfGoTJPv string
Go build ID BVrnoOrAVVaYdOlHLAPK/... string
Sleep gate 800–1120 s via math/rand.Intn(0x320)+0x320 behavior
PRNG seed constants 0xd7b17f80, 0xa1b203eb, 0x3d1a0000 constants
Certificate status Invalid table (VA beyond EOF) anomaly

Detection Signatures

  • capa: failed (missing signature path) ^[capa.txt]
  • Manual ATT&CK mapping:
    • T1055 — Process Injection (CreateThread, SetThreadContext, VirtualAlloc) ^[strings.txt:6053-6069]
    • T1027 — Obfuscated Files or Information (PRNG C2 decoding, randomized names)
    • T1497 — Virtualization/Sandbox Evasion (time-based sleep gate)
    • T1071 — Application Layer Protocol (HTTPS via net/http + crypto/tls) ^[strings.txt:1587]

References

Provenance

  • file.txt — file(1) output
  • strings.txt — Go strings and runtime artefacts (line numbers cited)
  • rabin2-info.txt — radare2 binary header summary (rabin2 -I)
  • pefile.txt — pefile.py parsed headers and resource directory
  • binwalk.txt — embedded PNG icon extraction
  • radare2 level-2 analysis + pdg decompilation of sym.main.main at 0x49d820
  • capa v7.1.0 (failed — missing signature path) ^[capa.txt]
  • floss v3.1.1 (failed — argument parsing error) ^[floss.txt]