cc4aa789cf0c80b32004b90be6be0ad80944ad85730c6095cc3ca2946905950354e64e (misattributed): cc4aa789 — Go 1.25.4 x64 signed infostealer, randomized main functions, no hardcoded C2
Executive Summary
A ~1.9 MB Go 1.25.4 PE64 signed with a Google Trust Services DV certificate (CN=askart.com). The OpenCTI/MalwareBazaar family label 54e64e is here a misattribution — the two prior analysed siblings are MSVC C++ droppers (null-padded and UPX-packed), whereas this sample is a pure-Go binary with randomized main.* function names, GUI subsystem, and runtime-resolved C2. It matches the golang-stealer-build-pattern observed in the unclassified-go-pe64 cluster. No browser-credential strings or hardcoded C2 recovered statically; the threat functionality is almost certainly runtime-decoded or fetched.
What It Is
| Attribute | Value |
|---|---|
| SHA-256 | cc4aa789cf0c80b32004b90be6be0ad80944ad85730c6095cc3ca29469059503 |
| File type | PE32+ executable (GUI) x86-64, 8 sections ^[file.txt] |
| Size | 1,993,344 bytes |
| Timestamp | 0x00000000 (zeroed) ^[pefile.txt:34] |
| Linker | v3.0 (Go internal linker) ^[pefile.txt:46] |
| Go version | go1.25.4 ^[strings.txt:5306] |
| Build ID | txvtqfmPRoj5TvQrtT8l/... ^[strings.txt:9] |
| Subsystem | Windows GUI ^[pefile.txt] |
| CGO | Disabled (pure Go, no C runtime dependency) |
| Trimpath | Inferred — no absolute module paths in strings |
| Certificate | CN=askart.com, issuer=WE1 (Google Trust Services), 4096-bit RSA, SHA-256, serial CDDA1164C88E40890E189788E7C9F32B ^[binwalk.txt] |
| Resources | None ^[pefile.txt] |
| .rsrc icon | Absent (distinguishes from ACR/Lumma siblings that embed PNG icons) |
Family ascription — contested. OpenCTI labels this 54e64e + dropped-by-amadey + signed. The two confirmed 54e64e siblings (3b13b28c, c8db13c1) are MSVC C++ droppers with very different build stacks. This Go binary does not share compiler, language, or payload architecture with them. I treat this as a third morph under the same opaque OpenCTI label, functionally belonging to the Go infostealer cluster documented at unclassified-go-pe64.
How It Works
Entry point flow (decompiled from radare2):
- PRNG seeding —
time.Now→ nanoseconds since epoch →math_rand.Seed. The seed is derived from real-time, not hardcoded, producing non-deterministic runtime behaviour. ^[r2:sym.main.main] - Timing measurement —
time.Nowis captured again after all staged calls; the delta is accumulated in a global counter at0x140209350. ^[r2:sym.main.main] - Staged function dispatch —
main.maincalls 24 randomizedmain.*functions in strict sequence, each performing opaque operations (slice allocations, XOR loops, mutex locks, PRNG draws). No single function name gives away its purpose. ^[strings.txt:5029-5067] - Fingerprinting / environment sampling — Before exit, the binary calls
os.hostname,getCurrentProcessId, andGetpagesize, then formats them through a mangledfmt.Sprintfformat string. This is consistent with host-fingerprinting or heartbeat-payload construction. ^[r2:sym.main.main]
Anti-analysis features observed:
- Randomized identifiers — every
mainpackage function is a 10–20 character alphanumeric noise string (e.g.Eohbqlwblkqqeo,Cibtvhipz). These are generated at build time; they do not appear in any dictionary. ^[strings.txt:5029-5067] - Execution-time gate — The delta between the two
time.Nowcalls is accumulated and presumably checked against a threshold. If the binary runs under a slow debugger or sandbox, the accumulated time may trigger altered behaviour (standard Go anti-sandbox). ^[r2:sym.main.main] - No .rsrc section — The binary does not embed an icon or version-info masquerade, unlike the ACR/Lumma cluster which uses 256×256 PNG icons. This may be a stripped-down variant.
Decompiled Behavior
main.main (0x1400a5e80)
Initialises a global PRNG from wall-clock time, seeds it, then iterates through ~24 opaque helper functions. After the loop it collects system fingerprint data (hostname, PID, page size), accumulates a timing counter, and outputs via fmt.Sprintf. ^[r2:sym.main.main]
main.Eohbqlwblkqqeo (0x1400a3440)
Small utility: draws 100 random integers via math_rand.Intn, sums them, and if the sum exceeds 0xc350 (50,000) adds the difference to the global timing counter. Functions as a PRNG-based delay / noise generator. ^[r2:sym.main.Eohbqlwblkqqeo]
main.Cibtvhipz (0x1400a3560)
Allocates a 50-element slice of structs (likely 3×int64 per element), performs unknown index arithmetic. Appears to be a data-structure setup routine. ^[r2:sym.main.Cibtvhipz]
main.Hjimvyukurnuhf (0x1400a3700)
Allocates an 8 KB slice, performs per-byte XOR-like mutation, locks a sync.Mutex, and appends to a dynamically-growing slice. The lock + growslice pattern suggests a buffered data collector (possibly clipboard or file content staging). ^[r2:sym.main.Hjimvyukurnuhf]
main.Fgreozkvjbhg (0x1400a3fe0)
Allocates 80-element arrays, fills them with linear combinations of indices, then XORs each element with 0xff. This is a lightweight obfuscation/transformation routine, not cryptographic — consistent with hiding a small payload or string blob. ^[r2:sym.main.Fgreozkvjbhg]
No hardcoded C2 recovered. The standard Go net/http, crypto/tls, and crypto/x509 packages are absent from the string table, but syscall and internal/poll are present, so the binary can perform raw Winsock calls. C2 is either:
- Fetched from a remote configuration at runtime (common in Go stealers), or
- Encrypted / XOR-decoded inside one of the opaque helper functions.
C2 Infrastructure
| Indicator | Value | Confidence |
|---|---|---|
| Hardcoded IPs | None recovered | — |
| Hardcoded domains | None recovered | — |
| Hardcoded URLs | None recovered | — |
| Certificate CN | askart.com |
High |
| Likely C2 mechanism | Runtime resolver or encrypted config (no HTTP package strings) | Medium |
The askart.com certificate is the only persistent attribution marker. The domain is a throwaway DV cert from Google Trust Services (WE1), valid Apr–Jul 2026. This is identical in intent to the maybe.us cert used by sibling 589af0f8 in the unclassified-go-pe64 cluster.
Interesting Tidbits
- Family-label pollution. This is the third distinct build morph tagged
54e64eby OpenCTI. The label is effectively an opaque bucket, not a true family. Analysts relying on OpenCTI family labels for clustering will get misleading results. ^[triage.json] - No external Go dependencies. Zero
github.com/...orgolang.org/x/...strings. The binary uses only the Go standard library. This limits fingerprinting but also means the builder is intentionally minimal — no third-party obfuscation frameworks. ^[strings.txt] .symtabretained. Unlike the ACR/Lumma cluster where.symtabis sometimes stripped, this binary keeps its symbol table. 6,832 function symbols remain. Go binaries strip poorly; retaining.symtabsuggests either laziness or the build pipeline does not runstrip.- GUI subsystem with no window code. The PE header declares
SUBSYSTEM_WINDOWS_GUI, yet no Win32 window-creation APIs are imported and no window-class strings exist. The binary runs silently in the background. ^[pefile.txt] - Certificate serial parity. Serial
CDDA1164C88E40890E189788E7C9F32B— 32 hex chars, Google Trust Services standard. Not yet seen in other corpus samples.
How To Mess With It (Homelab Replication)
Reproduce a comparable binary on a research VM:
# Requires Go 1.25.4+
go version
mkdir /tmp/go-stealer-repro && cd /tmp/go-stealer-repro
go mod init xJkLmNpQrStUvWxYz
# main.go — skeleton matching observed patterns
cat > main.go << 'EOF'
package main
import (
"fmt"
"math/rand"
"os"
"syscall"
"time"
)
func a1() {}
func a2() {}
func a3() {}
// ... mimic randomized function count
func main() {
rand.Seed(time.Now().UnixNano())
for i := 0; i < 100; i++ {
_ = rand.Intn(1000)
}
a1(); a2(); a3()
host, _ := os.Hostname()
pid := syscall.Getpid()
fmt.Printf("%s %d", host, pid)
}
EOF
# Build with matching flags
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build \
-trimpath \
-ldflags="-s -w -H windowsgui" \
-o repro.exe
Verification:
rabin2 -I repro.exe→lang: go,subsys: Windows GUIstrings repro.exe | grep 'go1.25'→ should hit- Function names will NOT be randomized unless you additionally use a build script that renames source identifiers, or use a commercial Go obfuscator such as
garble.
What you'll learn: How trivial it is to produce a signed-looking silent Go binary that evades family clustering based only on compiler artifacts.
Deployable Signatures
YARA Rule
rule Go_Signed_Infostealer_Askart_2026 {
meta:
description = "Go 1.25.4+ signed PE with randomized main functions, no .rsrc, askart.com certificate cluster"
author = "PacketPursuit"
date = "2026-06-05"
hash = "cc4aa789cf0c80b32004b90be6be0ad80944ad85730c6095cc3ca29469059503"
strings:
$go_ver = "go1.25." ascii
$go_build = "Go build ID:" ascii
$askart = "askart.com" ascii
$main_pattern = /main\.[A-Za-z]{10,25}/
condition:
uint16(0) == 0x5A4D and
uint32(uint32(0x3C)) == 0x4550 and
$go_ver and $go_build and
$askart and
#main_pattern >= 15 and
filesize < 3MB
}
Behavioral Hunt Query (Sigma-like pseudocode)
detection:
selection:
- Image|endswith:
- '\repro.exe'
- CommandLine|contains:
- 'askart.com'
# Actual hunt: correlate process creation of Go-signed PE with
# (1) no .rsrc section
# (2) GUI subsystem
# (3) subsequent network connections to non-standard ports
condition: selection
IOC List
| Type | Value | Context |
|---|---|---|
| SHA-256 | cc4aa789cf0c80b32004b90be6be0ad80944ad85730c6095cc3ca29469059503 |
Sample |
| SHA-1 | 0a0fc3b88c7e68e4c5c0fdaf9fe29f2b8f4e6e2e |
(from ssdeep.txt source) |
| ssdeep | 24576:2HU9ZZh3yCLw2NhyZVMXyZvxhxNhiuvcF3A/l2YfTV4ldJBeletL9SryqFpyX2:2HUrX3Xc2+VMXM7b92I66YG |
Clustering |
| TLSH | T76953A0B7CE508FAD4AAA33289B761917B75BC060F3263C72A90767C2F726E09D75744 |
Clustering |
| Cert CN | askart.com |
Attribution marker |
| Cert issuer | CN = WE1 |
Google Trust Services |
| Cert serial | CDDA1164C88E40890E189788E7C9F32B |
Revocation check target |
| Cert SHA1 fingerprint | 62:86:CA:BB:F3:42:A1:FD:0C:35:0C:78:66:42:6E:40:C4:C8:CD:58 |
IOC |
| Build ID | txvtqfmPRoj5TvQrtT8l/xbygvUzLqCWG850ZBN3t/YxLJC9FAisLfnYW-8RPE/e159SqX628yK1-f7dTgz |
Go build artefact |
Behavioral Fingerprint Statement
This binary is a Go 1.25.4 PE64 compiled with CGO_ENABLED=0 and -trimpath, signed with a Google Trust Services DV certificate issued to askart.com. It has no .rsrc section, no embedded icon, and no hardcoded C2 strings in the static image. At runtime it seeds math/rand from wall-clock time, executes ~24 opaque helper functions with randomized names, measures its own execution duration, and samples os.hostname and process ID before formatting the result with fmt.Sprintf. Network activity is expected to be runtime-resolved or encrypted. The certificate and build pattern strongly associate it with the unclassified Go PE64 infostealer cluster.
Detection Signatures (ATT&CK Mapping)
| Technique | ATT&CK ID | Evidence |
|---|---|---|
| Obfuscated Files or Information: Software Packing | T1027.002 | Randomized main.* function names (compile-time identifier obfuscation) ^[strings.txt:5029] |
| Virtualization/Sandbox Evasion: Time Based Evasion | T1497.001 | time.Now delta accumulated across function calls; PRNG delay loops ^[r2:sym.main.main] |
| Masquerading: Match Legitimate Name or Location | T1036.005 | Authenticode-signed PE with DV cert on throwaway domain askart.com; GUI subsystem with no visible window ^[binwalk.txt] |
| Ingress Tool Transfer | T1105 | Inferred — Go infostealer cluster typically fetches stage-2 payload or C2 config at runtime |
| Exfiltration Over C2 Channel | T1041 | Inferred — encrypted/synthesised C2 expected from cluster behaviour |
References
- 54e64e — OpenCTI opaque label; prior siblings are MSVC C++ (not Go).
- unclassified-go-pe64 — Cluster entity for Go-signed infostealers with this build pattern.
- golang-stealer-build-pattern — Recurring Go infostealer build artefacts.
- OpenCTI label source:
54e64e,dropped-by-amadey,signed,exe,malware-bazaar^[triage.json]
Provenance
Static analysis performed on 2026-06-05 using:
filev5.44,exiftoolv12.76,pefile(Python),rabin2v5.9.8strings(GNU),floss(attempted — CLI error),capa(signatures missing — error)radare2v5.9.8 withaa; aang; aflanalysis pipeline (2,232 functions recovered)binwalkv2.3.4 — certificate extraction at offset 0x1E6208opensslv3.0.15 — certificate parsing (PKCS#7 DER)- No dynamic analysis available — CAPE skipped (no Windows guest online)
No destructive operations were performed.