d5655568fee9c610139d41d367afc74e768e1c8baf70e37912e9ebeb27b5d411acrstealer: d5655568 — Fourth signed Go 1.26.2 sibling, custom PE parser + multi-pass decoder
What It Is
Fourth observed sibling of the ACR Stealer cluster. A signed PE32 executable compiled with Go 1.26.2 (GOARCH=386, GOOS=windows, CGO_ENABLED=0, -trimpath=true) carrying a randomized module path (JPYhJIzovpOdAaG) and the same Authenticode certificate (CN=me.muz.li, issuer=R13) seen in sibling 16a4344d ^[strings.txt:1675]. The binary embeds a custom in-memory PE parser and a multi-pass byte-transformation decoder — TTPs previously documented on the related orderreshop entity but now confirmed present in this PE32 acrstealer lineage.
Family attribution is from OpenCTI labels (acrstealer, flur-constzoo-surf, signed, 5-252-155-72) ^[triage.json]. No CAPE detonation was available, so dynamic behaviour is inferred from static artefacts and family metadata ^[dynamic-analysis.md].
| Attribute | Value |
|---|---|
| SHA-256 | d5655568fee9c610139d41d367afc74e768e1c8baf70e37912e9ebeb27b5d411 |
| Filename | hjbk.exe ^[metadata.json] |
| Size | 2,463,360 bytes (2.5 MB) |
| Type | PE32 executable (GUI) Intel 80386, 7 sections ^[file.txt] |
| Compiler | Go 1.26.2, GOARCH=386, GOOS=windows, CGO_ENABLED=0, -trimpath=true ^[strings.txt:1673-1680] |
| Module | JPYhJIzovpOdAaG (devel) — randomized per-build ^[strings.txt:1675] |
| Build ID | PSCioB1MKYaFM9sNgZAa/IOMtzCRaKWar5JHR4EqI/OGOaB66ms6QDBBZz9gzL/QM2VFsMEgGnpAVrhLuk7 ^[strings.txt:8] |
| Signed | Authenticode certificate embedded at offset 0x258e00, size 0x880 ^[pefile.txt] ^[rabin2-info.txt] |
| Cert subject | CN = me.muz.li |
| Cert issuer | CN = R13 |
| Resources | .rsrc section with multiple icons (social-engineering masquerade) ^[pefile.txt] ^[binwalk.txt] |
| IAT | kernel32.dll only (45 imports); Go runtime resolves the rest dynamically ^[pefile.txt] |
How It Works
Entry Point — PRNG Seeding & Obfuscated Dispatch
Static decompilation of main.main (radare2, 0x0049a590) shows the same entry pattern as siblings 6871848b, c577c6c8, and 16a4344d:
- Stack growth check —
sym.runtime.morestack_noctxtif the goroutine stack is exhausted ^[r2:sym.main.main]. - PRNG seeding — constructs a
math/rand.Source, then seeds it with timestamp-derived constants0x3d1a0000and0xa1b203eb(byte locations0x8f56fand0x8f579in.text) ^[r2:sym.main.main]. - Randomised dispatch — invokes
sym.main.tupfnstbandsym.main.kwlgcxafter generating indices viamath/rand.Intn^[r2:sym.main.main] ^[ghidra:main.main-0049a590].
Custom In-Memory PE Parser
Function main.immxjegqx (Ghidra, 0x00496fc0) implements an in-memory parser for Microsoft PE headers:
- Validates the MZ magic
0x5a4dat the candidate base ^[ghidra:main.immxjegqx-00496fc0]. - Walks the DOS stub to locate the PE signature (
0x4550) ^[ghidra:main.immxjegqx-00496fc0]. - Checks the optional header magic (
0x10bfor PE32 vs0x20bfor PE32+) and parses section headers accordingly ^[ghidra:main.immxjegqx-00496fc0]. - Returns section count, image base, entry point RVA, and section header array via out-parameters.
This routine is called from main.kwlgcx, suggesting reflective loading or payload mapping — a capability previously attributed to the orderreshop PE64 branch but now confirmed in this PE32 acrstealer.
Multi-Pass String Decoder
Function main.muwjcdzxjhqlde (Ghidra, 0x00496bb0) performs a multi-pass byte-transformation on embedded ciphertext:
- XOR with a runtime-derived byte key ^[ghidra:main.muwjcdzxjhqlde-00496bb0].
- Subtraction of a loop-dependent constant ^[ghidra:main.muwjcdzxjhqlde-00496bb0].
- Bitwise shifting and pairwise byte swaps within 8-byte blocks ^[ghidra:main.muwjcdzxjhqlde-00496bb0].
- The outer loop iterates over the source slice, applying the transformations in sequence before writing the result to a newly allocated Go byte slice.
The decoded output is likely C2 URLs, target paths, or API names. No hardcoded plaintext C2 strings were found in .text or .rdata — consistent with runtime decoding.
Dynamic API Resolution
Function main.howhtpulgjucujl (Ghidra, 0x00496350) wraps syscall_LazyProc_Call, the Go runtime mechanism for resolving Win32 APIs via LoadLibraryExW/GetProcAddress ^[ghidra:main.howhtpulgjucujl-00496350]. Called from main.kwlgcx, it bridges the statically-linked kernel32 IAT to additional APIs needed post-decoding.
C2 Infrastructure
- IP:
5.252.155.72 - Domain:
laserlogdnsop.icu - Label:
flur-constzoo-surf(OpenCTI campaign tag) ^[triage.json]
These IOCs are not present as plaintext strings in the binary. They are extracted from OpenCTI enrichment labels and are consistent across all four siblings, indicating a shared C2 infrastructure.
Interesting Tidbits
- Identical certificate to sibling 16a4344d: CN=
me.muz.li, issuer=R13, 90-day validity window. This is the first time the same cert has been reused across siblings, suggesting either a bulk signing event or a single purchase from a low-reputation CA. ^[pefile.txt] - Custom PE parser is new for this PE32 lineage: Prior acrstealer siblings (
6871848b,c577c6c8) did not surface a reflective-loader routine in static analysis. The presence ofmain.immxjegqxind5655568closes the TTP gap withorderreshopand confirms the two families share tooling beyond the compiler flags. ^[ghidra:main.immxjegqx-00496fc0] ^[/intel/analyses/16a4344dcdb51bd043a360dd954bbee9ed5d497dce177e3114740598cc90d78b.html] - No UPX or external packer:
.textentropy is ~6.19, well below packed thresholds. Obfuscation relies on Go's native mechanisms (-trimpath, randomized names) plus the custom decoder. ^[binwalk.txt] - Same PRNG salt constants: The seeding values
0x3d1a0000and0xa1b203ebare byte-for-byte identical across all four siblings, confirming a shared source template rather than per-build randomisation of the seed algorithm. ^[r2:sym.main.main] ^[/intel/analyses/6871848bb724a184e393a734c9de9c17c41da1f26359755696f0df40685c42f2.html]
Deployable Signatures
YARA
rule ACRStealer_Go126_Signed_PE32_Reflective
{
meta:
description = "ACR Stealer — Go 1.26.2 signed PE32 with custom PE parser and multi-pass decoder"
author = "PacketPursuit"
date = "2026-06-09"
hash1 = "d5655568fee9c610139d41d367afc74e768e1c8baf70e37912e9ebeb27b5d411"
hash2 = "16a4344dcdb51bd043a360dd954bbee9ed5d497dce177e3114740598cc90d78b"
strings:
$go_build = "go1.26.2" ascii wide
$mod_path = /path\t[A-Za-z0-9]{12,20}\r?\n/ ascii
$trimpath = "-trimpath=true" ascii
$cgo_off = "CGO_ENABLED=0" ascii
$mz_check = { 4D 5A } // MZ magic checked in-memory
$pe_magic = { 50 45 00 00 } // PE\0\0 signature
condition:
uint16(0) == 0x5A4D and
$go_build and
$trimpath and
$cgo_off and
#mod_path >= 1 and
pe.number_of_signatures > 0 and
all of ($mz_check, $pe_magic)
}
Behavioral Fingerprint
A signed PE32 executable compiled with Go 1.26 (GOARCH=386, CGO_ENABLED=0, -trimpath=true) whose module path is a random alphanumeric string of 15–20 characters. On execution it seeds a PRNG with the current time using constants 0x3d1a0000 and 0xa1b203eb, then invokes obfuscated main functions that decode strings via XOR-subtraction-shift-swap passes and parse in-memory PE headers for reflective loading. Network IOCs include 5.252.155.72 and laserlogdnsop.icu.
IOC List
| Type | Value | Source |
|---|---|---|
| SHA-256 | d5655568fee9c610139d41d367afc74e768e1c8baf70e37912e9ebeb27b5d411 |
triage.json |
| Filename | hjbk.exe |
metadata.json |
| IP | 5.252.155.72 |
triage.json (OpenCTI label) |
| Domain | laserlogdnsop.icu |
triage.json (OpenCTI label) |
| Cert Subject | CN=me.muz.li |
manual DER extraction ^[pefile.txt] |
| Cert Issuer | CN=R13 |
manual DER extraction ^[pefile.txt] |
| Module path | JPYhJIzovpOdAaG |
strings.txt:1675 |
| Build ID | PSCioB1MKYaFM9sNgZAa/IOMtzCRaKWar5JHR4EqI/OGOaB66ms6QDBBZz9gzL/QM2VFsMEgGnpAVrhLuk7 |
strings.txt:8 |
| PRNG salt 1 | 0x3d1a0000 |
byte at .text+0x8f56f ^[r2] |
| PRNG salt 2 | 0xa1b203eb |
byte at .text+0x8f579 ^[r2] |
| Custom parser | main.immxjegqx @ 0x00496fc0 |
Ghidra decompilation |
| Custom decoder | main.muwjcdzxjhqlde @ 0x00496bb0 |
Ghidra decompilation |
| Dynamic API | main.howhtpulgjucujl @ 0x00496350 |
Ghidra decompilation |
Related
- See acrstealer cluster page for the full family overview and prior siblings.
- See orderreshop for the PE64 branch that shares the custom PE parser and decoder TTPs.
- See golang-stealer-build-pattern for the common Go infostealer build artefacts.