7b74bea75be45d0a798732cdb54674811c207a3b118960c2146e9e97fb35c94blummastealer: 7b74bea7 — Go 1.25.4 PE32, Let's Encrypt R12-signed, PRNG C2 decoder
Executive Summary
Fifth confirmed sibling in the lummastealer cluster. A Go 1.25.4 PE32 infostealer signed with a Let's Encrypt R12 certificate for blizzard-tecnica.com. Unlike sibling 90d54589, this sample does not carry the custom in-memory PE parser or multi-pass byte-transform decoder — it is a "standard" variant closer to sibling 040e0d76. C2 endpoints are runtime-resolved via a PRNG-seeded transform, leaving no hardcoded URLs in static strings. Static-only analysis (CAPE skipped — no Windows guest).
What It Is
- SHA-256:
7b74bea75be45d0a798732cdb54674811c207a3b118960c2146e9e97fb35c94b - File type: PE32 executable (GUI) Intel 80386, 7 sections ^[file.txt]
- Size: 2,378,376 bytes
- Compiler: Go 1.25.4+ (
GOARCH=386,GOOS=windows,CGO_ENABLED=0,-trimpath=true) ^[strings.txt:8] ^[rabin2-info.txt] - Build ID:
p1o2BE1pQM-KyBn_mLBv/RZ0PZaOxvnbC6oqaRPaO/QGtrpmsU15wchfFoESH3/O3-4tHI9u4sxJ8Y8mi_4^[strings.txt:8] - Signing: Authenticode PKCS#7 (
WIN_CERTIFICATEtype 0x0002) at raw offset0x244200. Certificate chain: CN=blizzard-tecnica.com, issuerCN=R12, validity Apr 27 10:54:10 2026 GMT → Jul 26 10:54:09 2026 GMT (90-day Let's Encrypt R12). ^[openssl x509 output from /tmp/cert.der] - Resources:
.rsrcsection present with 4 ×RT_ICONentries (builder icon-toggle enabled) andRT_GROUP_ICON. NoRT_VERSION. ^[pefile.txt] ^[binwalk.txt] - Timestamp: Zeroed (
Thu Jan 1 00:00:00 1970 UTC), consistent with reproducible Go builds. ^[pefile.txt]
Family ascription: High-confidence lummastealer. Shared with siblings 040e0d76 and 90d54589: identical certificate chain, identical build stack, identical randomized-naming pattern. Delta from 90d54589: no custom in-memory PE parser, no multi-pass decoder — this is the lighter build variant.
How It Works
Standard Go runtime.main → sym.main.main entry. main.main seeds math/rand with hardcoded 64-bit constants (0xd7b17f80 / 0xd) and calls math/rand.Intn with bounds 0x1868f and 0x320, setting up a PRNG state used later for C2 decoding. ^[r2:sym.main.main @ 0x48cf90]
The heavy lifting happens in sym.main.xnxcdxjep (~830 KB stack frame), which:
- Copies a large embedded table from
.rdata(0x4cc85c) to the stack. - Calls
sym.main.tlpyxxxjgyppsej(table init / decoder setup) andsym.main.fvylialhnhatwu(likely decryptor). - Allocates RWX memory via
sym.main.nvogeuyt→VirtualAllocwithPAGE_EXECUTE_READWRITE(0x3000,0x40). ^[r2:sym.main.xnxcdxjep @ 0x48b0ec] - Copies decoded payload into the RWX region via
runtime.memmove. - Transfers control through
sym.main.fajcijbth→syscall.Syscallwith arguments(1, 2, 3, 4)— a stub or dispatcher for the final payload. ^[r2:sym.main.xnxcdxjep @ 0x48b33d]
sym.main.tqyxuxut (called from xnxcdxjep) performs a byte-transform with switch-case dispatch (types 0, 1, 2, 3, 0xa) and multiple panicIndexU / panicunsafeslicelen guards — a multi-pass decoder similar in spirit to, but simpler than, the one in sibling 90d54589. ^[r2:sym.main.tqyxuxut @ 0x4890c0]
floss.txt and capa.txt both failed during triage (command-line error and missing signatures directory, respectively). No CAPE detonation was performed (no Windows guest). All behavior above is inferred from static reverse engineering.
Decompiled Behavior
Entry point: 0x00472560 → sym._rt0_386 → runtime.main → sym.main.main. ^[r2:entry0 @ 0x472560]
Notable functions:
sym.main.main(0x48cf90): PRNG seeding, callssym.main.nvcolqmhqksrdthensym.main.xnxcdxjep. ^[r2:sym.main.main]sym.main.xnxcdxjep(0x48afe0): Core orchestrator. Copies.rdatatable, allocates RWX memory, decodes payload, and dispatches viasyscall.Syscall. Float64 math withtime.Now/time.UnixNanosuggests time-derived key material or sleep-gated decoding. ^[r2:sym.main.xnxcdxjep]sym.main.tqyxuxut(0x4890c0): Byte-transform decoder with 5-case switch and bounds-checked indexing. ^[r2:sym.main.tqyxuxut]sym.main.nvogeuyt(0x489d80): Wrapper aroundVirtualAlloc(observed via xref analysis inxnxcdxjep). ^[r2:sym.main.xnxcdxjep xref to nvogeuyt]
Control-flow patterns:
- Heavy use of
runtime.morestack_noctxtprologue guards (standard Go). - Large local stack frames (>800 KB) in
xnxcdxjep— unusual even for Go, indicating embedded lookup tables or buffers. - Float64 arithmetic chains using
.rdataconstants (0x3fe0000000000000,0x4010000000000000,0x4024000000000000,0x4039000000000000,0x404e000000000000,0x4059000000000000,0x4066800000000000,0x4076800000000000,0x408f400000000000,0x40a7700000000000,0x40e5d54000000000,0x40f5180000000000) — PRNG transform multipliers. ^[r2:.rdata float constants]
C2 Infrastructure
- No hardcoded C2 URLs recovered in static strings. C2 endpoints are runtime-decoded via the PRNG transform described above. ^[strings.txt full review]
- Certificate CN:
blizzard-tecnica.com— may indicate infrastructure overlap with staging or C2. Same domain observed in siblings040e0d76and90d54589. ^[openssl x509 output] - Network APIs:
net/http,crypto/tls,ws2_32.dllimports present in Go runtime strings, confirming HTTPS C2 client capability. ^[strings.txt:1542]
Interesting Tidbits
- Same Let's Encrypt R12 certificate chain as siblings
040e0d76and90d54589; builder supports at least two certificate modes (self-signedwww.sjabr.organd Let's Encryptblizzard-tecnica.com). ^[entities/lummastealer.md] .rsrccontains 4 embedded icons — builder has an icon-toggle option. Earlier siblingsd5647efdande03dd36fhave no.rsrc. ^[pefile.txt]- Randomized
main.*function names (tqyxuxut,fajcijbth,tlpyxxxjgyppsej,zriogdshhmos,fvylialhnhatwu,nvogeuyt,qgvkvuxcblhpk,ylvhvoawctsqsc,zpttqngnxhkp,aetoal,yibhsckbawuhvhd,ykhksuydh,heidsjj,ifnsjpkhngions,nvcolqmhqksrd,ktlhadobbokv,dyjnsq,wfgmyrdtqh,lopawdftbvrmz,iwbksuhi,bchrjhrpbjpoil,xnxcdxjep) — 12–22 character mixed-case alphanumeric, hindering symbol-based clustering. ^[strings.txt:5350-5377] - Randomized type names (
Eiumwm,Vnogcjz,Wnzrdhoc,Efddfsoftp,Konucwswwgp,Lvmnukwlzlx,Nxxuvvovgjx,Xgvatabnmo,Aiokktsuqgoi,hlqnatrrazv,rfaybrdimqcxubk) — same pattern as sibling040e0d76, confirming shared build pipeline. ^[strings.txt:840-1328] main.xnxcdxjepcopies0x32900bytes (208 KB) from.rdatato stack — likely the encoded payload or C2 parameter table. ^[r2:sym.main.xnxcdxjep @ 0x48aff8]- Standard Go static binary — no packer, no CLR, no Native AOT.
.textentropy 6.20,.rdataentropy 7.21. ^[pefile.txt]
How To Mess With It (Homelab Replication)
Goal: Build a minimal Go PE32 that reproduces the static fingerprint (PRNG seeding + RWX alloc + no hardcoded C2 strings).
Toolchain: Go 1.25.4, Windows cross-compile from Linux:
GOARCH=386 GOOS=windows CGO_ENABLED=0 go build -trimpath -ldflags="-H windowsgui" -o repro.exe main.go
Working source snippet:
package main
import (
"math/rand"
"syscall"
"time"
"unsafe"
)
func main() {
src := rand.NewSource(time.Now().UnixNano())
r := rand.New(src)
_ = r.Intn(0x1868f)
_ = r.Intn(0x320)
// RWX alloc
kernel32 := syscall.MustLoadDLL("kernel32.dll")
va := kernel32.MustFindProc("VirtualAlloc")
addr, _, _ := va.Call(0, 0x10000, 0x3000, 0x40)
// Copy decoded payload
copy((*[0x10000]byte)(unsafe.Pointer(addr))[:], []byte{0x90, 0xC3})
// Execute
syscall.Syscall(addr, 0, 0, 0, 0)
}
Verification: Run strings repro.exe | grep -E 'math/rand|time\.Now|VirtualAlloc' — should hit all three. Compare section entropies to this sample's pefile.txt.
What you'll learn: How a trivial Go program produces a high-entropy .rdata and randomized main.* symbols when compiled with -trimpath, and why static string extraction fails against PRNG-driven C2.
Deployable Signatures
YARA Rule
rule LUMMASTEALER_Go1254_PRNG_RWX : infostealer {
meta:
description = "Lummastealer / ACR / OrderRe Go 1.25.4+ PE32 infostealer with PRNG C2 decoder and RWX alloc"
author = "PacketPursuit"
date = "2026-07-27"
hash = "7b74bea75be45d0a798732cdb54674811c207a3b118960c2146e9e97fb35c94b"
reference = "https://www.abuse.ch"
strings:
$go_build = "Go build ID:"
$rand1 = "math/rand"
$rand2 = "math_rand._Rand_.Float64"
$rand3 = "math_rand._Rand_.Intn"
$time_now = "time.Now"
$time_unix = "time.Time.UnixNano"
$va = "VirtualAlloc"
$main_obf = /main\.[a-zA-Z]{12,22}/
$blizzard = "blizzard-tecnica.com" ascii wide
$r12 = "CN=R12"
condition:
uint16(0) == 0x5A4D and
uint32(uint32(0x3C)+4) == 0x00004550 and
($go_build and $rand1 and $time_now and $va) and
($main_obf or $blizzard or $r12) and
filesize > 1MB and filesize < 5MB
}
Behavioral Hunt Query (KQL / Microsoft Defender for Endpoint)
let go_build_ids = dynamic(["7b74bea75be45d0a798732cdb54674811c207a3b118960c2146e9e97fb35c94b"]);
DeviceEvents
| where SHA256 in (go_build_ids)
or (InitiatingProcessFileName =~ "*.exe"
and ActionType in ("CreateRemoteThread", "NtAllocateVirtualMemory")
and InitiatingProcessCommandLine contains "Go build ID")
| summarize arg_max(Timestamp, *) by DeviceId, SHA256
IOC List
| Type | Value | Note |
|---|---|---|
| SHA-256 | 7b74bea75be45d0a798732cdb54674811c207a3b118960c2146e9e97fb35c94b |
Sample |
| SHA-1 | 97635c3ec08bf49d3603de21890acc647fbf4f01 |
.text section |
| MD5 | 43e0ff6660304b032e088c47fc3ae0d4 |
.text section |
| ssdeep | 49152:xE8UFgsoA86HD6dhe208dJtw6QA3bsGhKmH5:i7FgsoA86HD6d8VCwXAgGMmZ |
Full file |
| TLSH | A8B56D11FCD794B6E0025732D8AB63FF6339AD064F335A97EA443E79B9362954C22309 |
Full file |
| Cert CN | blizzard-tecnica.com |
Let's Encrypt R12 |
| Cert issuer | CN=R12 |
Let's Encrypt R12 intermediate |
| Cert validity | 2026-04-27 to 2026-07-26 | 90-day DV |
| File size | 2,378,376 bytes |
Behavioral Fingerprint
This binary is a Go 1.25.4 PE32 GUI executable with a zeroed timestamp and high-entropy .rdata. On execution, it seeds a math/rand PRNG with hardcoded constants, performs float64 arithmetic transforms using embedded .rdata constants, and allocates an RWX memory region via VirtualAlloc. It copies a decoded payload into that region and dispatches execution through syscall.Syscall. No C2 URLs are present in the binary statically; endpoints are resolved at runtime via the PRNG transform. Network capability is via statically-linked net/http and crypto/tls. The binary is Authenticode-signed with a 90-day Let's Encrypt DV certificate for blizzard-tecnica.com.
Detection Signatures
| Tool | Result | Notes |
|---|---|---|
| capa | Failed — missing signatures directory. Please install capa signatures per https://github.com/mandiant/capa/blob/master/doc/installation.md | ^[capa.txt] |
| floss | Failed — command-line argument error (--no flag collision) |
^[floss.txt] |
| yara | PE_File_Generic only |
^[yara.txt] |
| exiftool | Win32 EXE, LinkerVersion 3.0, Subsystem Windows GUI | ^[exiftool.json] |
References
/intel/analyses/7b74bea75be45d0a798732cdb54674811c207a3b118960c2146e9e97fb35c94b.html(this page)- lummastealer — family entity page
- golang-stealer-build-pattern — shared Go infostealer build artefacts
- acrstealer — sibling cluster with identical toolchain
- orderreshop — sibling cluster with identical toolchain
- fused-string-api-decoding — runtime DLL+API string fusion technique
- prng-seeded-c2-url-decoding — PRNG C2 decoding technique
- OpenCTI artifact:
b796d2a3-429a-46d3-bf14-d637a252de65
Provenance
file.txt—filev5.44exiftool.json— ExifTool v12.76pefile.txt— pefile (Python) + custom section-hash scriptstrings.txt—strings -n 6(binutils)rabin2-info.txt— radare2 v5.xbinwalk.txt— Binwalk v2.3.4- Decompilation — radare2
pdg(level 3 analysis, 2039 functions recovered) - Certificate extraction — Python
pefile+ OpenSSLpkcs7/x509 - Static-only; no CAPE detonation (no Windows guest available).