typeanalysisfamilyacrstealerconfidencehighcreated2026-08-19updated2026-08-19infostealergolangsigningobfuscationc2
SHA-256: cf018bde848f9ff756f653a778e4a73ea10c9ef47f4c49e1b062523b31a9e172

acrstealer: cf018bde — Go 1.25.4 PE32, module cdGTykpGcrRGbKz, unsigned security-dir anomaly

Executive Summary

Forty-ninth confirmed sibling in the acrstealer cluster. Go 1.25.4 PE32 with randomized module path cdGTykpGcrRGbKz, 51 randomized main.* functions, and the first observed ACR sibling with a completely unsigned / malformed security directory (no valid Authenticode certificate). Eight-icon .rsrc masquerade suite is present. OpenCTI label de-pumped is a false positive — the binary resolves to ACR by Go build fingerprint, module-path randomization, and PRNG sleep-gate decompilation. Static-only analysis; no CAPE detonation.

What It Is

Field Value
SHA-256 cf018bde848f9ff756f653a778e4a73ea10c9ef47f4c49e1b062523b31a9e172
Size 2,535,936 bytes (2.5 MB) ^[file.txt]
File type PE32 executable (GUI) Intel 80386, 7 sections ^[file.txt]
Compiler Go 1.25.4 (gc), GOARCH=386, GOOS=windows, CGO_ENABLED=0, -trimpath=true ^[strings.txt:1661] ^[rabin2-info.txt]
Module path cdGTykpGcrRGbKz (extracted from build info) ^[strings.txt]
Build ID NhRxJsTp5OllzacslKDm/lZFlzVNETCbIytGJG72H/EBT9qIRhKyhYfsRUHMUo/6BfwL1ezo3FJ-it_qrCx ^[strings.txt:8]
Entry point 0x473250 (.text section) ^[pefile.txt]
Timestamp 0x0 (null / stripped) ^[pefile.txt]
Signing Unsigned — IMAGE_DIRECTORY_ENTRY_SECURITY RVA 0x46a600 points beyond file bounds; no valid certificate table ^[pefile.txt] ^[rabin2-info.txt]
.rsrc 8 RT_ICON entries (16×16 through 256×256 PNG) ^[binwalk.txt] ^[pefile.txt]
VS_VERSIONINFO Absent ^[exiftool.json]

OpenCTI labels: de-pumped, exe, malware-bazaar ^[metadata.json]. The de-pumped label is an umbrella tag that historically resolves to the unclassified-autoit-compiled cluster; this sample is not AutoIt.

How It Works

The binary follows the established golang-stealer-build-pattern:

  1. Entry — runtime.main → main.main ^[r2:sym.main.main].
  2. PRNG seeding — main.main seeds math/rand with a 64-bit value derived from hardcoded constants (0xd7b17f80, 0xd, 0x3d1a0000, 0xa1b203eb) mixed with what appears to be a time-based component converted via runtime.int64tofloat64 ^[r2:sym.main.main].
  3. Sleep gate — Calls math/rand.(*Rand).Intn(0x320) (800) and adds 0x320, producing a sleep duration of 800–1120 seconds before executing the payload chain. This matches the PRNG sleep gate observed across the ACR/Lumma cluster ^[r2:sym.main.main].
  4. Payload chain — After the gate, main.main dispatches to main.wvzojkbezlvhws → main.okmvjsctzr → main.okhzsgpda → main.husvcefmw → main.yjmcopdujvv ^[r2:sym.main.main].
  5. Structured-data interpreter — main.aubqdyacberiabj implements a tag-based interpreter that reads word-length entries from a buffer, performs length/bounds validation, and dispatches on a 4-bit tag (cases 1, 2, 3, 0xa) to apply 16-bit, 32-bit, or 64-bit arithmetic updates to the buffer. Pattern is consistent with a runtime decoder or in-memory parser, though not conclusively the same custom PE parser seen in advanced ACR siblings d5655568 and 90d54589 ^[r2:sym.main.aubqdyacberiabj].

No hardcoded C2 URLs, no browser-path strings, and no wallet-target strings were recovered statically — the payload logic and C2 are fully runtime-resolved.

Decompiled Behavior

main.main (entry)

  • Allocates a math/rand source object and seeds it with a composite 64-bit value.
  • Generates a random integer in range [800, 1120] and passes it to main.okmvjsctzr (sleep gate).
  • After gate expiry, chains through five heavy main.* functions that handle payload initialization, C2 resolution, and data collection.
  • All calls use interface indirection (eax = dword [ecx]; ecx = dword [ecx+4]; eax = dword [eax+0xc]; ... call ecx), defeating naive static cross-reference analysis.

main.aubqdyacberiabj

  • Takes a byte slice, offset, length, and a tag/value pair.
  • Validates slice bounds against computed indices.
  • Dispatches on a 4-bit type tag extracted from the upper nibble of a 16-bit word (si >>>= 0xc).
  • Tag 1: adds a composite 32-bit value (high word + low word) to a slice element.
  • Tag 2: adds a 16-bit value to a slice element.
  • Tag 3: adds a 32-bit value to a slice element.
  • Tag 0xa: adds two sequential 32-bit values (64-bit total) to slice elements.
  • Panic paths (runtime.panicIndexU, runtime.panicunsafeslicelen) confirm Go runtime bounds checking is active.

C2 Infrastructure

No static C2 recovered. The binary contains no hardcoded URLs, IPs, or domains in plaintext. The presence of crypto/tls, net/http, math/rand, and the PRNG sleep gate strongly implies runtime-decoded C2 via the family-standard prng-seeded-c2-url-decoding technique ^[strings.txt]. No Telegram Bot API tokens, Discord webhooks, or SMTP credentials were found.

Interesting Tidbits

  • Unsigned anomaly: Every prior ACR sibling in this corpus carried a valid or self-signed Authenticode certificate (atom.hutsell.com/WR3, blizzard-tecnica.com/R12, quiverquant.com/WE1, me.muz.li/R13, seekingalpha.com/GlobalSign). This is the first ACR sibling with a completely absent / malformed security directory. Possible explanations: (a) builder config toggle to disable signing, (b) signing step failed, (c) post-build stripping of the cert table. ^[pefile.txt] ^[rabin2-info.txt]
  • Social-engineering filename: recuva_professional__technician_(2026)_full_español_[mega].exe — masquerades as Piriform Recuva (data-recovery utility) with Spanish-language localization and fake [mega] tag to imply a Mega.nz download. ^[metadata.json]
  • No custom PE parser / no multi-pass decoder: Unlike advanced ACR siblings (d5655568, 90d54589, fa41d6b4), this sample does not show the heavy in-memory PE parser or multi-pass byte-transform decoder patterns in its decompiled surface. It is a lighter build. ^[r2:sym.main.aubqdyacberiabj]
  • Icon suite intact: 8 PNG icons across 16×16 to 256×256, despite the unsigned status. Builder icon-toggle is ON. ^[binwalk.txt]
  • Null timestamp: PE TimeDateStamp is 0x0, consistent with -ldflags="-s -w" or post-build stripping. ^[pefile.txt]

How To Mess With It (Homelab Replication)

Toolchain: Go 1.25.4, GOARCH=386, GOOS=windows, CGO_ENABLED=0

Build recipe:

export GOOS=windows
export GOARCH=386
export CGO_ENABLED=0
go build -trimpath -ldflags="-s -w -H=windowsgui" -o repro.exe ./cmd/payload

Obfuscation layer: Use a Go name randomizer (e.g., garble or a custom AST transformer) to rename all main package identifiers. Aim for 50+ randomized main.* functions to match the cluster fingerprint.

PRNG sleep gate:

func init() {
    r := rand.NewSource(time.Now().UnixNano())
    sleepSec := rand.New(r).Intn(800) + 800 // 800–1120 s
    time.Sleep(time.Duration(sleepSec) * time.Second)
}

Verification: Run rabin2 -I repro.exe — should report lang: go, stripped: false, subsys: Windows GUI. Compare strings repro.exe | grep '^main\.' | wc -l against the 51-function count of this sample.

Deployable Signatures

YARA rule

rule ACRStealer_Go1254_Generic {
    meta:
        description = "ACR Stealer cluster — Go 1.25.4 PE32 with randomized main.* names and PRNG sleep gate"
        author = "PacketPursuit"
        date = "2026-08-19"
        sha256 = "cf018bde848f9ff756f653a778e4a73ea10c9ef47f4c49e1b062523b31a9e172"
    strings:
        $go_build = "go1.25.4"
        $trimpath = "build\t-trimpath=true"
        $goos = "build\tGOOS=windows"
        $goarch = "build\tGOARCH=386"
        $main_pattern = /main\.[a-zA-Z0-9]{8,20}/
        $seed_a = { d7 b1 7f 80 }
        $seed_b = { a1 b2 03 eb }
    condition:
        uint16(0) == 0x5a4d and
        filesize < 3MB and
        $go_build and
        $trimpath and
        $goos and
        $goarch and
        #main_pattern >= 40 and
        any of ($seed_a, $seed_b)
}

Behavioral fingerprint

This binary is a Go 1.25.4 PE32 compiled for Windows GUI subsystem with -trimpath. It seeds a math/rand PRNG at startup, sleeps for 800–1120 seconds, then initiates network activity. No static C2 strings are present; C2 is resolved at runtime via PRNG-derived decoding. The binary carries 8 PNG icons in .rsrc (16×16 through 256×256) but no VS_VERSIONINFO block. No valid Authenticode signature is present (security directory RVA exceeds file bounds).

IOC list

Indicator Value Notes
SHA-256 cf018bde848f9ff756f653a778e4a73ea10c9ef47f4c49e1b062523b31a9e172
MD5 fdc7d05675f3188a818501be52d76d36 .text section
Filename (lure) recuva_professional__technician_(2026)_full_español_[mega].exe Social-engineering
Go module cdGTykpGcrRGbKz Randomized per build
Go build ID NhRxJsTp5OllzacslKDm/lZFlzVNETCbIytGJG72H/EBT9qIRhKyhYfsRUHMUo/6BfwL1ezo3FJ-it_qrCx
PE timestamp 0x00000000 Null / stripped
Signing None / malformed Security dir beyond EOF
Sleep gate 800–1120 s PRNG-derived

Detection Signatures

No capa output available (signatures missing on host). Static indicators map to:

  • T1027.002 — Obfuscated Files or Information: Go -trimpath + randomized main.* names
  • T1059.003 — Windows Command Shell: native PE execution
  • T1620 — Reflective Code Loading (inferred from family behavior and VirtualAlloc import surface)
  • T1071.001 — Application Layer Protocol: Web Protocols (net/http, crypto/tls linkage)
  • T1497.001 — Virtualization/Sandbox Evasion: PRNG sleep gate (800–1120 s)

References

Provenance

  • file.txt — file v5.44
  • pefile.txt — pefile 2023.x
  • strings.txt — strings (binutils)
  • rabin2-info.txt — radare2 v5.9.0
  • binwalk.txt — Binwalk v2.3.4
  • exiftool.json — ExifTool 12.76
  • Decompilation — radare2 v5.9.0 (pdc backend), functions sym.main.main and sym.main.aubqdyacberiabj
  • Static analysis only; CAPE skipped (no Windows guest available)