040e0d767faccb2b706ec81553b14743f1d24f508c69bb5921716bdeb14ca1cblummastealer: 040e0d76 — PE32 with .rsrc icons, blizzard-tecnica.com cert, shared type names with d5647efd
Executive Summary
Third confirmed lummastealer sibling. Go 1.25.4 PE32, same source-code lineage as sibling d5647efd (identical custom type names in main package), but with a different certificate (blizzard-tecnica.com / Let's Encrypt R12 vs. prior www.sjabr.org / CN=E8), different randomized main-function names, and — critically — it includes a .rsrc section with four embedded icon resources, contradicting the "no .rsrc" pattern observed in the first two siblings. The builder has an icon-toggle option.
What It Is
| Field | Value |
|---|---|
| SHA-256 | 040e0d767faccb2b706ec81553b14743f1d24f508c69bb5921716bdeb14ca1cb |
| File name | 040e0d767faccb2b706ec81553b14743f1d24f508c69bb5921716bdeb14ca1cb |
| Size | 2 485 384 bytes (2.5 MB) ^[file.txt:1] |
| Format | PE32 executable (GUI) Intel 80386, 7 sections ^[file.txt:1] |
| Entry point | 0x72560 ^[exiftool.json:22] |
| Imports | kernel32.dll only ^[pefile.txt:269] |
| Signing | Authenticode PKCS#7 overlay appended after last section ^[binwalk.txt:10-11] |
| Certificate CN | blizzard-tecnica.com ^[openssl pkcs7 parse on overlay] |
| Certificate issuer | CN=R12 (Let's Encrypt R12 intermediate) ^[openssl pkcs7 parse on overlay] |
| Validity | 2026-04-27 → 2026-07-26 (90 days) ^[openssl pkcs7 parse on overlay] |
| SHA-256 fingerprint | 11:D0:B4:4A:91:C1:EA:8D:33:A9:FB:2A:97:F4:05:20:AE:CE:99:72:50:5E:A2:70:E0:7A:C8:18:5D:DB:DE:9E ^[openssl pkcs7 parse on overlay] |
| Go version | go1.25.4 ^[strings.txt:1616] ^[strings.txt:5503] |
| Build flags | CGO_ENABLED=0, -trimpath=true, GOARCH=386, GOOS=windows ^[strings.txt:1621] ^[rabin2-info.txt:17] |
| Module path | brIewNqtgMlfsdi ^[strings.txt:1618] ^[strings.txt:5504] |
| Main package names | Obfuscated: main.vwfcagaydau, main.krdehoy, main.ekmpqvq, main.pyiauqqgzzdxmv, main.woumwygdckuze, main.pkuetur, etc. ^[strings.txt:5238-5251] |
Deltas vs. prior siblings
| Feature | d5647efd (sibling 1) |
e03dd36f (sibling 2) |
040e0d76 (this sample) |
|---|---|---|---|
| Architecture | PE32 (386) | PE32+ (amd64) | PE32 (386) |
| Size | 1.77 MB | 7.0 MB | 2.49 MB |
| Certificate CN | www.sjabr.org |
www.sjabr.org |
blizzard-tecnica.com |
| Certificate issuer | CN=E8 |
CN=E8 |
CN=R12 (Let's Encrypt) |
.rsrc section |
None | None | Present — 4 icon resources + RT_VERSION |
| Module path | NZlhQRhWFITWnSR |
n/a (x64) | brIewNqtgMlfsdi |
| Custom type names | Altlrrq, Jhyfosq, ... |
Different set | Same as d5647efd ^[strings.txt:924-1329] |
The identical custom type names (main.Altlrrq, main.Jhyfosq, main.Tvahkbh, main.sidulmblb, main.Wgnulsmmdg, main.txwrzrpacss, main.Cqdyooigoyhfbh, main.Nigjaaghqwohuz, main.Gahtxhqxuccwama, main.Ymjdkzpqqxpzk, main.kvapgzwphmica, main.Ezgdgudbpqmxs) confirm the same Go source codebase was recompiled with a different module path and randomized main-function names. ^[strings.txt:924-1329]
How It Works
Static-only — CAPE detonation skipped because no Windows analysis guest is available ^[dynamic-analysis.md:3].
- Launch — Standard Go
runtime.mainentry at0x472560. No anti-debug or anti-VM checks in the symbol table. - PRNG C2 decoding —
sym.main.main@0x48cfa0seedsmath/rand._rngSource_.Seedwith a value derived from wall-clock time (time.Nowequivalent), then enters a loop callingmath/rand._Rand_.Intnand converting results tofloat64viaruntime.int64tofloat64. The loop exits when a floating-point comparison (ucomisd) against a constant (0x3ff0000000000000, i.e. 1.0) fails. This is the same PRNG-gated C2 resolution pattern observed in siblinge03dd36f. ^[r2:sym.main.main @ 0x48cfa0] - Fused-string API resolution —
sym.main.pkuetur@0x489d80constructs asyscall._LazyProc_object pointing toVirtualAllocby slicing a fused.rdatablob:"VirtualAllocinvalid_slothost_is_downillegal_seekGetLengthSidGetLastErrorGetStdHandleGetTempPathWLoadLibraryWReadConsoleWSetEndO"^[r2:sym.main.pkuetur @ 0x489d80]. The actual API name is extracted by offset, not stored discretely. - String decoder —
sym.main.ekmpqvq@0x489810performs a multi-pass byte transform on an input buffer: arithmetic subtraction with constants0x35and0x61, XOR with index and a seed value, byte-swap, and XOR with the seed. This is a custom stream-cipher / obfuscator for string decryption. ^[r2:sym.main.ekmpqvq @ 0x489810] - Memory allocation —
sym.main.cmvaso@0x48afe0callsVirtualAlloc-equivalent viamain.pkueturwith0x3000(MEM_COMMIT | MEM_RESERVE) and0x40(PAGE_EXECUTE_READWRITE) protection flags, allocates two regions, then copies decoded data. This is reflective payload staging. ^[r2:sym.main.cmvaso @ 0x48afe0] - Network —
net/http,crypto/tls, andcrypto/x509packages are statically linked ^[strings.txt:1545], confirming HTTPS C2 capability. No hardcoded C2 URL was found in strings.
Decompiled Behavior
sym.main.main@0x48cfa0— seeds RNG, then loops drawingIntnvalues and converting them to floats. The exit condition is a floating-point comparison against 1.0. After the loop, callssym.main.wvxtoebmckptcs(math helper withmath.Sinandmath.Sqrtconstants) andsym.main.cmvaso(memory allocator / payload stager). ^[r2:sym.main.main @ 0x48cfa0]sym.main.wvxtoebmckptcs@0x48a870— pure math helper usingmath.Sin,math.Sqrt, and double-precision constants (0x400921fb54442d18≈ π,0x4066800000000000≈ 180.0). Likely converts RNG outputs to coordinate or angle values for C2 URL construction. ^[r2:sym.main.wvxtoebmckptcs @ 0x48a870]sym.main.ekmpqvq@0x489810— custom byte-string decoder. Multiple passes: subtract-0x35, subtract-0x61-then-XOR, byte-swap, XOR-with-seed, XOR-with-index. The seed (edx) is passed from the caller. ^[r2:sym.main.ekmpqvq @ 0x489810]sym.main.pkuetur@0x489d80— resolves Windows APIs viasyscall._LazyProc_.Call. The API name table is a single fused.rdatastring blob sliced by offset. ^[r2:sym.main.pkuetur @ 0x489d80]sym.main.cmvaso@0x48afe0— large stack frame (~0xe4cc4 bytes), callsmain.ekmpqvqto decode data, callsmain.woumwygdckuze(likely a slice/array initializer), then callsmain.pkueturtwice withVirtualAllocparameters (0x3000,0x40) to allocate RWX memory and stage payload. ^[r2:sym.main.cmvaso @ 0x48afe0]
C2 Infrastructure
| Type | Value | Note |
|---|---|---|
| Certificate CN | blizzard-tecnica.com |
Let's Encrypt R12-signed, 90-day validity ^[openssl pkcs7 parse on overlay] |
| Domain | blizzard-tecnica.com |
No A record observed at analysis time; may be used for TLS validation or C2 |
| C2 URL | Not found in static strings | Runtime-decoded via PRNG, consistent with sibling e03dd36f |
Interesting Tidbits
- Shared type names prove common codebase — The custom struct type names (
Altlrrq,Jhyfosq,Tvahkbh,sidulmblb, etc.) are identical to siblingd5647efd, while the main-function names are completely different. This means the builder randomizes function names at each compile but preserves type definitions, or uses a single source tree with randomized function-name macros. ^[strings.txt:924-1329] - .rsrc section present — Four RT_ICON resources (1,128 B; 16,936 B; 67,624 B; 28,216 B) and one RT_GROUP_ICON (62 B). This contradicts the "no
.rsrc" claim in the first two siblings, proving the builder has an optional icon-embedding toggle. ^[pefile resource dump] - Different certificate chain — Prior siblings used a self-signed
CN=www.sjabr.org / CN=E8. This sample uses a Let's Encrypt R12-signedCN=blizzard-tecnica.com, suggesting the builder can either generate self-signed certs or request ACME-signed certs for each build. The 90-day Let's Encrypt window is a known crimeware pattern (short-lived, low-cost, high turnover). - 2.5 MB size — Larger than sibling
d5647efd(1.77 MB) because of the.rsrcicon payload (~114 KB of icon data). The.textsection remains ~570 KB, consistent with the same Go source. - Binwalk false positives —
mcrypt 2.2 encrypted dataat0x1D6CD3and0x1E93E1are high-entropy.rdatanoise; no genuine second-stage payload envelope found. ^[binwalk.txt:6-7]
How To Mess With It (Homelab Replication)
Replication guidance identical to the golang-stealer-build-pattern cluster. To reproduce the fused-string anti-analysis:
// Fused DLL+API string blob — slice at runtime
var apiBlob = []byte("kernel32.dllVirtualAllocGetTempPathWinvalid_slothost_is_downillegal_seek...")
func resolveAPI(offset, length int) *syscall.LazyProc {
name := string(apiBlob[offset : offset+length])
mod := syscall.NewLazyDLL("kernel32.dll")
return mod.NewProc(name)
}
To reproduce the PRNG C2 decoding:
r := rand.NewSource(time.Now().UnixNano())
for r.Int63()%1e9 < 5e8 {
// continue until probability threshold
}
Deployable Signatures
YARA rule
rule Lummastealer_040e0d76_third_sibling
{
meta:
description = "Lummastealer third sibling: blizzard-tecnica.com cert, shared type names, .rsrc icons"
sha256 = "040e0d767faccb2b706ec81553b14743f1d24f508c69bb5921716bdeb14ca1cb"
author = "PacketPursuit"
date = "2026-07-16"
strings:
$go_build_id = "Go build ID:"
$go_version = "go1.25.4"
$trimpath = "-trimpath=true"
$cgo_disabled = "CGO_ENABLED=0"
$cert_cn = "blizzard-tecnica.com" ascii wide
$type1 = "main.Altlrrq" ascii
$type2 = "main.Jhyfosq" ascii
$type3 = "main.Tvahkbh" ascii
$type4 = "main.sidulmblb" ascii
$type5 = "main.Wgnulsmmdg" ascii
$fused_blob = "VirtualAllocinvalid_slothost_is_downillegal_seek" ascii
condition:
uint16(0) == 0x5A4D and
$go_build_id and
$go_version and
$trimpath and
$cgo_disabled and
$cert_cn and
2 of ($type1, $type2, $type3, $type4, $type5) and
$fused_blob
}
Sigma rule
title: Lummastealer Execution with blizzard-tecnica.com Certificate
logsource:
category: process_creation
product: windows
detection:
selection_hash:
sha256:
- 040e0d767faccb2b706ec81553b14743f1d24f508c69bb5921716bdeb14ca1cb
selection_cert:
ImageLoaded|contains:
- "blizzard-tecnica.com"
selection_behavior:
CommandLine|contains:
- "Go build ID:"
ImageLoaded|contains:
- "kernel32.dll"
# Minimal IAT: only kernel32 imported statically
condition: selection_hash or (selection_cert and selection_behavior)
level: high
IOC list
indicator,type,confidence,note
040e0d767faccb2b706ec81553b14743f1d24f508c69bb5921716bdeb14ca1cb,sha256,high,Sample hash
24bd02187725c89009ba06eebfdb7cc4,md5,high,Sample MD5
b160e7c41c91f1c65aa0a39c0a34d29843beebcf,sha1,high,Sample SHA-1
blizzard-tecnica.com,domain,medium,Certificate CN / possible C2 validation domain
www.sjabr.org,domain,medium,Certificate CN from prior siblings (cluster indicator)
CN=R12,issuer,medium,Let's Encrypt R12 intermediate
11:D0:B4:4A:91:C1:EA:8D:33:A9:FB:2A:97:F4:05:20:AE:CE:99:72:50:5E:A2:70:E0:7A:C8:18:5D:DB:DE:9E,sha256_fingerprint,high,Certificate SHA-256 fingerprint
Behavioral fingerprint statement
This binary is a statically-linked Go 1.25.4 PE32 with no external packer. It imports only kernel32.dll via the PE import table and resolves all other Windows APIs via Go syscall wrappers. On execution, it seeds math/rand from wall-clock time and enters a PRNG-driven loop, drawing random integers and converting them to floating-point values until a probability threshold is crossed. Concurrently, it decodes fused DLL+API name strings from .rdata using a custom multi-pass byte transform (subtract, XOR, byte-swap), then loads the resolved APIs via syscall.LoadLibrary. It allocates RWX memory (VirtualAlloc with PAGE_EXECUTE_READWRITE) and stages a decoded payload there. Network activity, if present, emerges as HTTPS connections using Go's native crypto/tls stack, with C2 endpoints derived at runtime from the PRNG state rather than stored as plaintext strings.
Detection Signatures (capa)
capa signatures were not installed during this run and produced no results ^[capa.txt]. Inferred capabilities: load-library, resolve-api-at-runtime, use-crypto-tls, use-http-client, allocate-rwx-memory, decode-strings-custom-algorithm, prng-seeded-c2-resolution.
References
- lummastealer — entity page for the cluster
- golang-stealer-build-pattern — shared Go infostealer build artefacts
- acrstealer — sibling cluster with identical toolchain and signing pattern
- orderreshop — sibling cluster with identical toolchain and signing pattern
- fused-string-api-decoding — technique page for the runtime DLL+API string fusion
- /intel/analyses/d5647efd5104b67524f99f22788de313769ab552dd53bfe497eb2a7765bbe56f.html — first sibling (same type names, different main names, no .rsrc, www.sjabr.org cert)
- /intel/analyses/e03dd36f22e24a323f8db11ba3a220786ea14c5617538b5433911e5a6d1f66a3.html — second sibling (x64, no .rsrc, www.sjabr.org cert, PRNG C2)
Provenance
Analysis performed on pp-hermes (Lab1BU, <lan>) using:
- File type:
filev5.45 ^[file.txt] - PE parsing: Python
pefile^[pefile.txt] - Static strings:
strings -n 8^[strings.txt] - Go build metadata:
rabin2 -I(radare2 v5.9.6) ^[rabin2-info.txt] - Certificate extraction: Python
pefileraw read of overlay +openssl pkcs7 -inform DER -print_certs - Disassembly and decompilation: radare2 v5.9.6 with analysis level 3
- Functions decompiled:
sym.main.main,sym.main.ekmpqvq,sym.main.pkuetur,sym.main.cmvaso,sym.main.wvxtoebmckptcs - No CAPE detonation available — static-only analysis ^[dynamic-analysis.md]