typeanalysisfamilyunclassified-go-pe32confidencelowgolangpeinfostealerevasion
SHA-256: 9f7ee895f02870f62073c267bcb21bd85b063dc51c4c8ae1916d8f49670a7402

unclassified-go-pe32: 9f7ee895 — First 32-bit x86 Go sample in corpus; garbled main.* names, zero static C2

Executive Summary

A PE32 GUI Intel 80386 binary built with the Go compiler. Sixteen garbled main.* function names replace human-readable symbols, consistent with automated build-time obfuscation seen in Go stealer families, but this is the first 32-bit (x86) specimen in the corpus — all prior Go malware here was PE32+ amd64. No C2 URLs, no crypto primitives, no browser/wallet targets, and no persistence strings are recoverable statically. CAPE was skipped (no Windows guest); all behavioural claims are inferred from build artefacts alone.

What It Is

Attribute Value
SHA-256 9f7ee895f02870f62073c267bcb21bd85b063dc51c4c8ae1916d8f49670a7402
Size 571,706 bytes (558 KB)
File type PE32 executable (GUI) Intel 80386, 7 sections ^[file.txt]
Subsystem Windows GUI ^[exiftool.json:26]
Timestamp Null (0x0, 1970-01-01) ^[pefile.txt:66]
Linker Go toolchain (build ID present) ^[strings.txt:8]
Signing Unsigned; security directory RVA 0x22d400 / size 0x880 points beyond EOF ^[pefile.txt] ^[rabin2-info.txt:34]
Packing None observed; standard section names, no UPX/Themida fingerprints ^[binwalk.txt]

Build / RE

Toolchain

  • Go compiler — Go build ID: "uYwrFY7FjV8y2ZWt86gv/..." in .text tail ^[strings.txt:8]. No go version -m metadata recoverable (stripped build info).
  • Architecture — GOARCH=386, GOOS=windows. First 32-bit Go malware in the corpus; all prior Go samples were amd64.
  • Linker flags — -H=windowsgui inferred from subsystem; -trimpath likely (no source paths in strings).
  • CGO — Disabled (no C runtime imports; standard Go syscall DLL loading patterns only) ^[strings.txt:29-43].

Symbol Obfuscation

  • 16 garbled main.* names — Hkcxgdf, zbybmkq, Ivxbhwzc, Ziapjyei, Lrpysvqxuu, Ukxhmbkrga, Zrpxcnepwsi, Oanefuyrrhpt, fkhwedfsljaq, fixzbshklqgie, Ektykxodtnevwv ^[strings.txt:652-900].
  • These are 8–20 character mixed-case alphanumeric strings with zero semantic meaning — the same anti-static pattern documented in go-function-name-randomization, but applied to a 32-bit build.

Section Layout

Standard Go PE32 layout ^[pefile.txt]:

  • .text — VA 0x1000, size 0x81e1e, entropy 6.18 (normal for Go runtime + compiled code)
  • .rdata — VA 0x83000, size 0x15c4b0, entropy 4.71 (read-only data, Go type descriptors, string tables)
  • .data — VA 0x1e0000, size 0x40888 (zero entropy on disk — uninitialized BSS mapped here)
  • .idata — VA 0x221000, size 0x3dc (import descriptor table, empty/corrupt on disk)
  • .reloc — VA 0x222000 (base relocation data)
  • .symtab — VA 0x229000 (Go symbol table — source of garbled names)
  • .rsrc — VA 0x241000, size 0x1a438 (no VS_VERSION_INFO recovered; possibly empty or icon-only)

Anti-Analysis

  • Null PE timestamp — common in Go malware to strip build-time metadata ^[pefile.txt:66].
  • Stripped to external PDB — IMAGE_FILE_DEBUG_STRIPPED set, no debug paths ^[file.txt].
  • No static imports — rabin2 reports static: true, stripped: true ^[rabin2-info.txt:36-37]. API resolution is via Go syscall package runtime DLL loading (LoadLibrary + GetProcAddress) ^[strings.txt:29-43].
  • No VM/debug checks in static strings (no IsDebuggerPresent, CheckRemoteDebuggerPresent, CPUID anti-VM, registry queries).

Notable Functions (Decompiled)

Entry point entry0 at 0x457c30 ^[r2:entry0]:

  • Standard Go runtime bootstrap: checks CPU features (cpuid), sets up fs:[0x14] stack cookie/canary, initialises the Go scheduler (fcn.00440310), and calls runtime.main equivalent.
  • No userland threat logic visible in the decompiled entry — all 16 garbled main.* functions are reached later via runtime indirection.

Deploy / ATT&CK

All claims below are static-only inferences — CAPE was skipped because no Windows guest is available ^[dynamic-analysis.md]. No runtime ground-truth exists.

ID Technique Evidence / Inference
T1027.002 Obfuscated Files or Information Go -trimpath + 16 garbled main.* names strip developer identity ^[strings.txt:652-900]
T1620 Reflective Code Loading (potential) Go binaries often embed encrypted second-stage payloads in .rdata or .data; no static evidence here, but empty .idata suggests runtime-loaded imports
T1071 Application Layer Protocol (potential) ws2_32.dll and winmm.dll referenced in syscall loader fragments ^[strings.txt:40-41]; implies Winsock use, but no C2 endpoint recovered

C2 Infrastructure

None recoverable statically. No hardcoded URLs, IPs, domains, paste IDs, Telegram bot tokens, Discord webhooks, or SMTP credentials are present in the string table. If C2 exists, it is either:

  1. Encrypted/obfuscated inside .data and decoded at runtime (Go byte-slice obfuscation is trivial to implement), or
  2. Delivered by a separate stage/companion file not present in this sample.

Persistence

None observed statically. No schtasks, reg add HKCU\...\Run, Startup paths, or service creation strings.

Attribution

  • Low confidence, unattributed. The 32-bit Go build is unusual for modern crimeware (most Go stealers/RATs target amd64 for larger address spaces and better AV evasion). This could indicate:
    • A builder targeting older 32-bit Windows systems (e.g., embedded/OT environments).
    • An early-stage or test build from a developer still iterating on the toolchain.
    • A deliberate architecture downgrade for compatibility with a specific victim profile.
  • No linguistic clues, no code-reuse overlaps with known families, no certificate artefacts.

Capabilities

  • go-garbled-main-function-names
  • go-386-windows-build
  • null-pe-timestamp
  • runtime-api-resolution-via-syscall
  • static-only-analysis-no-c2-recovered

Interesting Tidbits

  • First 32-bit Go malware in the corpus. All prior Go samples (acrstealer, lummastealer, goloader, 9d2ca3, 54e64e, valetgate, afk-stealer, orderreshop, menomoushop) were PE32+ x64.
  • .data section has zero entropy on disk (0.000000) ^[pefile.txt:164] — this is the Go BSS (uninitialised data) mapped as read/write. It means any runtime-decrypted payload would land in .data in memory but leaves no disk footprint.
  • Security directory is invalid (points past EOF). This is either a truncated file on ingestion or a malformed PE header artefact from the Go linker.
  • capa and floss both errored during triage ^[capa.txt] ^[floss.txt], so no automated capability extraction is available.

How To Mess With It (Homelab Replication)

To reproduce a comparable binary:

# On a Windows or cross-compile Linux host with Go 1.22+
GOOS=windows GOARCH=386 CGO_ENABLED=0 go build -ldflags="-s -w -H=windowsgui" -trimpath -o reproducer.exe main.go

Use a tool like github.com/burrowers/garble to obfuscate main.* names:

garble build -ldflags="-s -w -H=windowsgui" -trimpath -o garbled.exe

Verification: run strings garbled.exe | grep "^main\." — you should see alphanumeric noise instead of main.main, main.init, etc.

Deployable Signatures

YARA Rule

rule go_pe32_garbled_names {
    meta:
        description = "PE32 x86 Go binary with garbled main.* function names"
        author = "PacketPursuit"
        date = "2026-08-25"
        hash = "9f7ee895f02870f62073c267bcb21bd85b063dc51c4c8ae1916d8f49670a7402"
    strings:
        $go_build_id = /Go build ID: "[A-Za-z0-9_\/+-]{40,100}"/
        $main_garbled = /\*main\.[A-Za-z]{8,20}/
        $runtime = "runtime"
        $strconv = "strconv"
        $syscall = "syscall"
    condition:
        uint16(0) == 0x5A4D
        and uint32(uint32(0x3C)+4) == 0x00004550  // PE
        and uint16(uint32(0x3C)+24) == 0x010B      // Optional header magic = PE32
        and $go_build_id
        and #main_garbled >= 10
        and $runtime
        and $strconv
        and $syscall
}

Behavioral Fingerprint

A PE32 x86 GUI binary with null PE timestamp, standard 7-section layout (.text, .rdata, .data, .idata, .reloc, .symtab, .rsrc), and a Go build ID in the .text tail. Contains 10+ garbled main.* function names (8–20 mixed-case alphanumeric characters) in the symbol table. No hardcoded C2, no crypto primitives, no persistence artefacts in static strings. API resolution is via Go syscall package runtime DLL loading rather than static imports. Likely infostealer or downloader given the obfuscation investment, but payload specifics require dynamic analysis.

IOCs

Type Value Notes
SHA-256 9f7ee895f02870f62073c267bcb21bd85b063dc51c4c8ae1916d8f49670a7402 Sample analysed
File size 571,706 bytes
PE type PE32, subsystem GUI, 7 sections
Build ID prefix uYwrFY7FjV8y2ZWt86gv Go build ID fragment

References

Provenance

  • file.txt — file v5.44
  • strings.txt — strings from binutils
  • pefile.txt — pefile Python library
  • rabin2-info.txt — radare2 v5.9.8
  • exiftool.json — ExifTool v12.76
  • binwalk.txt — Binwalk v2.3.3
  • capa.txt — Mandiant capa (errored — signatures missing)
  • floss.txt — FireEye flare-floss (errored — CLI argument parsing)
  • dynamic-analysis.md — CAPE sandbox (skipped — no Windows guest available)
  • Static decompilation — radare2 v5.9.8 (r2 -A level 3, 1536 functions recovered)