90d54589bfae10deb74fa349668a5af649c546b8eddb75d5000174601920cf77lummastealer: 90d54589 — Go 1.25.4 PE32, blizzard-tecnica.com R12 cert, custom PE parser + multi-pass decoder
Executive Summary
Signed Go infostealer sibling carrying the same blizzard-tecnica.com / R12 certificate chain observed in LummaStealer 040e0d76, but augmented with a custom in-memory PE parser and multi-pass byte-transformation decoder previously documented in the ACRStealer / OrderReshop sub-cluster. Static C2 is fully absent; network indicators are runtime-decoded via a PRNG-seeded transform. This sample is evidence of technique cross-pollination across what OpenCTI labels as distinct families.
What It Is
- File: PE32 executable (GUI) Intel 80386, 7 sections, 2.33 MB ^[file.txt] ^[pefile.txt:1]
- Compiler: Go 1.25.4,
GOARCH=386,GOOS=windows,CGO_ENABLED=0,-trimpath=true^[strings.txt:1616-1625] ^[strings.txt:5443-5453] - Module path:
JuYWgOhherjqrZN(14-character randomized alphanumeric) ^[strings.txt:1618] - Signing: Authenticode certificate CN=
blizzard-tecnica.com, issuerR12(Let's Encrypt), embedded atIMAGE_DIRECTORY_ENTRY_SECURITYoffset0x238808^[strings.txt:8828] ^[binwalk.txt:10-11] ^[pefile.txt] - Resources:
.rsrcsection contains a 256×256 PNG icon (social-engineering masquerade) ^[binwalk.txt:8] - Family label:
lummastealer— certificate matches LummaStealer sibling040e0d76exactly; build toolchain matches the broader ACR/Lumma/OrderRe cluster. See lummastealer for cluster overview.
How It Works
At launch the binary follows the standard Go runtime.main entry, then branches into a series of obfuscated routines before any network activity:
-
API resolution via fused-string blob —
sym.main.lvkctpxqokfbuilds asyscall._LazyProc_from a monolithic.rdatablob that concatenates DLL names and API names without delimiters (VirtualAllocinvalid_slothost_is_downillegal_seekGetLengthSidGetLastErrorGetStdHandleGetTempPathWLoadLibraryW...) ^[r2:sym.main.lvkctpxqokf @ 0x489d80] ^[strings.txt:1180]. This defeats naive string extraction and YARA rules that look for standaloneVirtualAlloc. See fused-string-api-decoding for the technique. -
Custom in-memory PE parser —
sym.main.zhfogrmvalidates MZ (0x5A4D) and PE (0x4550) signatures, then walks section headers in memory. The function takes a base pointer and size, performs bounds-checked slice operations, and returns a structured representation of the PE layout ^[r2:sym.main.zhfogrm @ 0x489ab0]. Identical behavior to ACRStealer siblingd5655568and OrderReshop. -
Multi-pass byte-transform decoder —
sym.main.gyxsukxrkxtmperforms a looped arithmetic decode over a byte slice:imulwith hardcoded constants (0x4d4873ed,0x54741fac), right-shifts, subtraction, XOR, and byte swaps. The output is fed into a second pass that XORs with values derived from amath/rand-seeded stream ^[r2:sym.main.gyxsukxrkxtm @ 0x489810]. This is the same algorithm class observed in OrderReshop (main.tnlzbjjyqfzrdbk). -
PRNG loop —
sym.main.qptkpczseedsmath/randfrom runtime state (likely current time), callsFloat64, performs floating-point multiply-add, and feeds the result intosym.main.omqfro, which drives the decoder ^[r2:sym.main.qptkpcz @ 0x48acf0]. No hardcoded C2 URLs exist in the static image. -
Direct syscall wrapper —
sym.main.shzldzgiewrapssyscall.SyscallNwith hardcoded parameter counts, suggesting intentional bypass of standard Gosyscallconvenience wrappers ^[r2:sym.main.shzldzgie @ 0x4899d0].
Decompiled Behavior
Entry point (sym.main.main @ 0x48cfa0): allocates a runtime.newobject buffer, performs integer math on the result, then calls into the PRNG-decoder chain before any library load. The entry does not immediately import net/http symbols — networking is deferred until after C2 decode.
Notable functions called by entry:
sym.main.iugvukwvbpnun— orchestrates the fused API loader and PE parser (caller oflvkctpxqokf,zhfogrm,gyxsukxrkxtm,qptkpcz)sym.main.lvkctpxqokf— resolves APIs via fused blob +syscall._LazyProc_.Callsym.main.zhfogrm— custom PE parser (MZ/PE validation + section enumeration)sym.main.gyxsukxrkxtm— multi-pass arithmetic decodersym.main.qptkpcz—math/randseed + float pipelinesym.main.shzldzgie— rawsyscall.SyscallNwrapper
Observed control flow: entry → PRNG seed → decoder → API resolution → (network, inferred). No anti-VM or debugger checks were recovered in the static image; the binary relies on string obfuscation and runtime decoding for evasion.
C2 Infrastructure
No hardcoded C2 indicators recovered statically. All network strings are runtime-decoded via the PRNG-seeded multi-pass transform. The binary statically links net/http, crypto/tls, and crypto/x509 ^[strings.txt], confirming HTTPS C2 capability. Dynamic analysis was skipped (no CAPE Windows guest available) ^[dynamic-analysis.md].
Interesting Tidbits
- Certificate match: The
blizzard-tecnica.com/ R12 certificate is identical to LummaStealer040e0d76— same CN, same issuer, same 90-day Let's Encrypt validity pattern. This is stronger evidence than build metadata alone. - Technique cross-pollination: Custom PE parser + multi-pass decoder were first observed in ACRStealer sibling
d5655568and OrderReshop. Their presence here links the LummaStealer certificate cluster to the ACR/OrderRe codebase. - No
.rsrcabsence: Unlike earlier LummaStealer siblingsd5647efdande03dd36f(which have no icon resources), this sample carries a full 256×256 PNG icon — consistent with the builder's icon-toggle option noted in040e0d76. - Go 1.25.4 vs 1.26.2: Latest ACRStealer siblings have moved to Go 1.26.2. This sample stays at 1.25.4, aligning with the LummaStealer build timeline rather than the newest ACRStealer builds.
- Fused blob offset: The fused API/DLL blob sits at raw offset
0xa7ebainside.rdata^[strings.txt:1180], immediately following Go runtime strings.
How To Mess With It (Homelab Replication)
Toolchain:
- Go 1.25.4 for Windows 386
- Build flags:
GOOS=windows GOARCH=386 CGO_ENABLED=0 go build -ldflags="-s -w -trimpath" -o repro.exe
Recipe for fused-string API decoding:
- Declare a single
var fused = []byte("kernel32.dllVirtualAllocGetTempPathW...") - Slice substrings by
(offset, length)pairs stored in a parallel table - Pass each slice to
syscall.LoadLibrary/syscall.GetProcAddress - Verify with
strings repro.exe | grep VirtualAlloc— should return nothing standalone
See fused-string-api-decoding for a working 50-line reproduction.
What you'll learn: How Go's -trimpath + randomized module paths + fused API blobs produce a binary that evades both static strings tools and naive import-table analysis.
Deployable Signatures
YARA Rule
rule LUMMA_Go1254_FusedBlob_CustomPEParser
{
meta:
description = "LummaStealer / ACR cluster: Go 1.25.4 signed PE32 with fused API blob and custom PE parser"
author = "PacketPursuit"
date = "2026-07-27"
sha256 = "90d54589bfae10deb74fa349668a5af649c546b8eddb75d5000174601920cf77"
strings:
$go_build = "go1.25.4" ascii
$trimpath = "-trimpath=true" ascii
$mod_path = /path\t[a-zA-Z0-9]{12,20}/
$fused1 = "VirtualAllocinvalid_slothost_is_down" ascii
$fused2 = "GetLengthSidGetLastErrorGetStdHandleGetTempPathWLoadLibraryW" ascii
$cert_cn = "blizzard-tecnica.com" ascii
condition:
uint16(0) == 0x5A4D and
$go_build and
$trimpath and
$mod_path and
($fused1 or $fused2 or $cert_cn) and
pe.number_of_sections >= 6
}
Sigma Rule
title: Go Infostealer Fused API Blob Resolution
description: Detects a Go process that loads multiple Windows APIs via LoadLibrary/GetProcAddress from a fused string blob instead of the import table.
status: experimental
logsource:
product: windows
category: process_access
detection:
selection:
Image|endswith: '.exe'
CallTrace|contains:
- 'LoadLibraryW'
- 'GetProcAddress'
filter:
LoadedImage|contains:
- 'kernel32.dll'
- 'advapi32.dll'
- 'ws2_32.dll'
- 'crypt32.dll'
- 'shell32.dll'
- 'ntdll.dll'
condition: selection and filter
# In practice: a single Go PE32 process that loads 4+ DLLs via LoadLibrary within 5 seconds of launch
falsepositives:
- Go programs that legitimately use syscall.LoadLibrary for plugin loading
level: medium
IOC List
| Indicator | Value | Type |
|---|---|---|
| SHA-256 | 90d54589bfae10deb74fa349668a5af649c546b8eddb75d5000174601920cf77 |
hash |
| SHA-1 | 6648314f14c4d399ac2a72b9bc9c1b6afe1d24b1 |
hash |
| MD5 | f9b997a998c7b47802f9a2fbaf95c807 |
hash |
| Certificate CN | blizzard-tecnica.com |
cert |
| Certificate Issuer | R12 |
cert |
| Module path | JuYWgOhherjqrZN |
build artifact |
| Go version | go1.25.4 |
build artifact |
| Fused blob substring | VirtualAllocinvalid_slothost_is_downillegal_seek |
string artifact |
Behavioral Fingerprint Statement
A signed PE32 GUI executable compiled with Go 1.25.4 for Windows 386, carrying a randomized module path and a .rsrc PNG icon. At runtime it allocates RWX memory, resolves Windows APIs via a fused .rdata string blob using syscall.LoadLibrary / GetProcAddress, and decodes C2 strings through a multi-pass arithmetic transform seeded by math/rand. No hardcoded C2 URLs exist in the static image; the binary relies entirely on runtime decoding. The Authenticode certificate is a 90-day Let's Encrypt DV cert for blizzard-tecnica.com.
Detection Signatures
- MITRE ATT&CK: T1055 (Process Injection — inferred from
VirtualAlloc+ RWX staging), T1027 (Obfuscated Files or Information — fused strings + multi-pass decoder), T1071.001 (Application Layer Protocol: Web — HTTPS C2 inferred fromcrypto/tlslinkage), T1564.003 (Hide Artifacts: Hidden Window — Windows GUI subsystem), T1583.001 (Acquire Infrastructure: Domains — Let's Encrypt cert for fraudulent domain) - Capa: Not applicable — capa signatures were unavailable during triage (
capa.txtcontains only install-error output) ^[capa.txt]
References
- Artifact ID:
f6427b51-8a28-48bf-86f6-310c119b9e01 - Triage label:
acrstealer(OpenCTI), reclassified tolummastealerbased on certificate provenance - Related wiki pages: lummastealer, acrstealer, orderreshop, fused-string-api-decoding, golang-stealer-build-pattern
- LummaStealer sibling with identical certificate: /intel/analyses/040e0d767faccb2b706ec81553b14743f1d24f508c69bb5921716bdeb14ca1cb.html
- ACRStealer sibling with custom PE parser + multi-pass decoder: /intel/analyses/d5655568fee9c610139d41d367afc74e768e1c8baf70e37912e9ebeb27b5d411.html
Provenance
Static analysis performed 2026-07-27 on pp-hermes (Linux 6.14.8-2-pve). Tools: file 5.44, strings GNU binutils 2.42, exiftool 12.76, pefile Python library, radare2 5.9.8 (aaa analysis level 3), binwalk 2.3.4. No dynamic execution (CAPE skipped — no Windows guest). All behavioral claims trace to strings, PE structure, or r2 decompilation.