typeanalysisfamilyunclassified-go-pe64confidencemediumgolangpeinfostealerevasionanti-analysis
SHA-256: 4b1d954729c4aa3dcbb9e81ec47c4ae1950af995d39f7855dcbce49b989ad456

unclassified-go-pe64: 4b1d9547 — Go 1.18.5 x64, 90 randomized main.* names, unsigned, no static C2

Executive Summary

PE32+ x64 GUI executable compiled with Go 1.18.5 (gc) and bearing 90 randomized main.* function names in its symbol table. No Authenticode signature, no .rsrc section, and no static C2 strings recovered. The depumped OpenCTI label is a false positive; this is a Go-compiled binary, not an AutoIt dropper. Static-only analysis (CAPE skipped — no Windows guest). Likely an infostealer or stage-1 loader based on build-pattern overlap with confirmed Go stealer families.

What It Is

Field Value
SHA-256 4b1d954729c4aa3dcbb9e81ec47c4ae1950af995d39f7855dcbce49b989ad456
MD5 86f7a221db1a0bdba38d02503821dedb ^[file.txt]
SHA-1 19e64b3f359c2e351111aeb5ef50a34228c80549 ^[file.txt]
Size 1,540,096 bytes (1.47 MB) ^[file.txt]
Type PE32+ executable (GUI) x86-64, 6 sections ^[file.txt]
Compiler Go 1.18.5 (gc) ^[strings.txt:1154]
Build ID 5iTfgA1dcnv8pnUzwtcr/GgEe9TiMth8vkXq5kzKA/po-z3pOJqGTKHRxbucad/XTqLLA4376xKW1KcpTNc ^[strings.txt:7]
Entry Point 0x5AB40 ^[pefile.txt]
Base Address 0x400000 ^[rabin2-info.txt]
Stripped Yes (to external PDB) ^[file.txt]
Signed No ^[rabin2-info.txt:28]
Subsystem Windows GUI ^[rabin2-info.txt:33]
IAT kernel32.dll only (38 imports) ^[pefile.txt]
.rsrc Absent ^[pefile.txt]

How It Works

Build / RE

The binary is a standard Go 1.18.5 gc-compiled Windows amd64 executable. ^[strings.txt:1154] Go build artefacts are intact: go.buildid, go1.18.5, runtime strings (runtime.mallocgc, runtime.schedule, syscall.DLL), and the full Go type system metadata. ^[strings.txt:1652–3867]

Function name randomization: 90 main.* functions with 8–20 character randomized alphanumeric names (e.g. main.rgfuyvdydccipxe, main.Mblgnxgxvtebd, main.toibnsjgranj). ^[strings.txt:3489–3531] This is the anti-static technique documented at go-function-name-randomization — the builder renames every main package function before compilation to break string-based clustering.

Build path: Source file pmtdGjyUvflyDpg/main.go embedded in the pclntab. ^[strings.txt:3744] No vendor paths or third-party module names recovered — the malware is either a single-module project or modules are stripped by -trimpath.

Imports: The IAT is minimal — only kernel32.dll with 38 imports covering memory, thread, process, console, and exception APIs. ^[pefile.txt] No wininet, winhttp, ws2_32, or crypt32 in the IAT. Go's runtime resolves all additional APIs internally via syscall.LoadDLL + syscall.GetProcAddress.

No packing / no obfuscation beyond Go standard: Section names are standard .text, .rdata, .data, .idata, .reloc, .symtab. ^[pefile.txt] No UPX, Themida, or custom packer signatures. Entropy is moderate (6.2–6.4 in .text/.rdata). ^[pefile.txt]

No anti-debug / no anti-VM: No IsDebuggerPresent, CheckRemoteDebuggerPresent, CPUID hypervisor-bit checks, or registry disk enum queries found in strings.

Deploy / ATT&CK

All TTPs below are inferred from static build patterns unless noted. No CAPE detonation available (no Windows guest).

Technique ID Evidence
Compile after code sign - Unsigned; no certificate table ^[rabin2-info.txt:28]
Obfuscated files or information T1027.002 90 randomized main.* function names ^[strings.txt:3489]
Native API T1106 Go runtime uses syscall.DLL + GetProcAddress for all non-kernel32 APIs ^[strings.txt]
Application layer protocol T1071 net/http and crypto/tls package strings present (197 total), indicating HTTP/HTTPS client capability ^[strings.txt]
Data encoding T1132 encoding/base64, encoding/hex, crypto/md5, crypto/sha256 in standard library strings ^[strings.txt]

No static C2: No hardcoded IPs, domains, URLs, Discord webhooks, Telegram bot tokens, or paste-site references recovered. The net/http and crypto/tls imports suggest C2 is runtime-resolved — likely decoded from an embedded blob or generated via PRNG at launch, consistent with the acrstealer / lummastealer PRNG-seeded C2 decoding pattern.

No persistence strings: No Run, RunOnce, schtasks, Startup, Userinit, or service-related strings recovered.

No credential-theft strings: No browser paths (AppData\Local\Google\Chrome), wallet names (metamask, exodus), or DPAPI/CryptUnprotect references found. However, the 197 standard-library strings include os/user, os/exec, io/ioutil, bytes.Buffer, and strings.Builder — all common in Go infostealers for file traversal and data buffering.

Decompiled Behavior

Ghidra was not invoked for this sample due to Go binary decompilation limitations (radare2 used instead). Radare2 analysis (aaa) discovered 1,498 functions. ^[r2:aaa] The entry point (0x45ab40) is the standard Go runtime entry (runtime.main), which initializes the garbage collector, goroutine scheduler, and then calls main.main. ^[rabin2-info.txt]

main.main and the 89 other randomized main.* functions are dispersed across the .text section. Without Go-specific decompilation support (e.g. redress or golang_loader), pseudocode from radare2 is largely unreadable due to Go's ABI (stack-based arguments, defer frames, runtime checks).

Key observations from radare2:

  • main.qwmavtof is referenced with a .func1 closure, suggesting goroutine or callback usage. ^[r2:strings]
  • main.toibnsjgranj.func1 also present, reinforcing concurrent goroutine patterns. ^[r2:strings]
  • No main.init beyond the standard Go module initializer.
  • No obvious reflective loader, process hollowing, or shellcode injection patterns in the first 100 functions from entry.

C2 Infrastructure

None recovered statically. C2 is presumed runtime-resolved based on:

  • Absence of hardcoded network strings ^[strings.txt]
  • Presence of net/http + crypto/tls standard library components ^[strings.txt]
  • Build-pattern overlap with confirmed Go infostealer families that use PRNG-seeded C2 URL decoding ^[golang-stealer-build-pattern]

Interesting Tidbits

  • False-positive family label: OpenCTI tagged this sample de-pumped / depumped. That label is an umbrella covering AutoIt-compiled droppers in this corpus. This sample is Go-compiled, not AutoIt — the label should be treated as a false positive. ^[triage.json]
  • Unsigned, no icon: Unlike Cluster A siblings (589af0f8, a5520aba) which carry GoDaddy DV certificates, this sample is completely unsigned and has no .rsrc section — the builder either skipped signing or this is an earlier/later variant from a different pipeline. ^[rabin2-info.txt:28]
  • Go 1.18.5 is old: Released Aug 2022. Most Go malware in this corpus uses 1.25.x (2025). This may indicate a reused builder, a maintained legacy codebase, or a deliberately old toolchain to avoid newer Go anti-debug features. ^[strings.txt:1154]
  • Filename is Cyrillic: Original MalwareBazaar filename \u0412\u043e\u043etsexecs64.exe (displayed as Вооtsexecs64.exe — "bootsexecs64" with Cyrillic В and о). Masquerades as a system boot utility. ^[triage.json]
  • Standard library surface is huge: 197 Go standard-library API strings span networking, crypto, encoding, IO, and OS packages. A Go binary this small (1.47 MB) with this much stdlib surface is typical of a single-purpose tool compiled with all dependencies statically linked.

How To Mess With It (Homelab Replication)

Goal: Produce a Go PE64+ with comparable randomized-function-name anti-static fingerprint.

  1. Install Go 1.18.5 (or any 1.x): https://go.dev/dl/go1.18.5.windows-amd64.zip
  2. Write main.go with trivial HTTP client and file traversal:
    package main
    import ("net/http"; "os"; "io/ioutil")
    func main() {
        resp, _ := http.Get("https://example.com")
        ioutil.ReadAll(resp.Body)
        os.MkdirAll("C:\\Temp\\test", 0755)
    }
    
  3. Randomize function names with a pre-build script:
    # Rename every function in main.go to random strings
    sed -i 's/func doWork/func qwmavtof/g' main.go
    sed -i 's/func helper/func toibnsjgranj/g'
    
  4. Build:
    GOOS=windows GOARCH=amd64 CGO_ENABLED=0 go build -ldflags="-s -w -H=windowsgui" -o test.exe
    
  5. Verify:
    strings test.exe | grep -c '^main\.'
    # Should show randomized names, not semantic ones
    

Verification: Run strings test.exe | grep -E '^main\.[a-z]{10,20}$' — should output 5–10 randomized names. Compare to this sample's strings.txt line 3489+.

Deployable Signatures

YARA Rule

rule go_pe64_randomized_names_unsigned {
    meta:
        description = "Go PE64+ with randomized main.* function names, unsigned, no .rsrc"
        author = "PacketPursuit SOC"
        date = "2026-08-04"
        sha256 = "4b1d954729c4aa3dcbb9e81ec47c4ae1950af995d39f7855dcbce49b989ad456"
    strings:
        $go_ver = "go1.18.5" ascii wide
        $go_buildid = "go.buildid" ascii wide
        $main_rnd = /main\.[a-zA-Z]{10,20}/ ascii
    condition:
        uint16(0) == 0x5A4D and
        uint32(uint32(0x3C)+0x18) == 0x8664 and // PE32+
        $go_ver and
        $go_buildid and
        #main_rnd >= 50 and
        // No .rsrc section — check section names
        not for any i in (0..pe.number_of_sections-1): (
            pe.sections[i].name == ".rsrc"
        )
}

Behavioral Hunt Query (Sigma-style, EQL)

title: Go PE64+ with randomized main functions
logsource:
    product: windows
    category: process_creation
detection:
    selection:
        Image|endswith: '.exe'
        CommandLine|contains:
            - 'go1.18'
    condition: selection

IOC List

Type Value Note
SHA-256 4b1d954729c4aa3dcbb9e81ec47c4ae1950af995d39f7855dcbce49b989ad456 Primary
MD5 86f7a221db1a0bdba38d02503821dedb ^[file.txt]
SHA-1 19e64b3f359c2e351111aeb5ef50a34228c80549 ^[file.txt]
ssdeep 24576:tEGnBEX3GiF4unOy1MgL4QtolAz7HgjQ6OgLP8jWF4ZurOsD1:2+BG3GiiupuQtoGzXgLPQsD1 ^[ssdeep.txt]
TLSH D8654947BCD064B9D5EA923288B5A2917735F8490B3167C32F11B7BA2E373D04E753A8 ^[tlsh.txt]
Build ID 5iTfgA1dcnv8pnUzwtcr/GgEe9TiMth8vkXq5kzKA/po-z3pOJqGTKHRxbucad/XTqLLA4376xKW1KcpTNc ^[strings.txt:7]
Source path pmtdGjyUvflyDpg/main.go ^[strings.txt:3744]

Behavioral Fingerprint

This binary is a Go 1.18.5-compiled PE64+ GUI executable with 90+ randomized main.* function names in its symbol table, a minimal IAT restricted to kernel32.dll (38 imports), no .rsrc section, no Authenticode signature, and no hardcoded C2 strings. At runtime it likely resolves network APIs through Go's internal syscall.DLL mechanism and connects to attacker infrastructure via HTTP/HTTPS with TLS, with C2 parameters decoded from an embedded blob or generated via PRNG. The combination of heavy function-name randomization, Go 1.18.5 toolchain, and absence of .rsrc distinguishes it from signed GoDaddy-cert variants in the same umbrella cluster.

Detection Signatures

capa failed to run (default signature path missing, OSError). ^[capa.txt] No capability mapping available.

References

Provenance

Analysis based on static artifacts: file.txt, strings.txt, floss.txt (errored — no decoded strings), capa.txt (errored — signatures missing), binwalk.txt, rabin2-info.txt, pefile.txt, exiftool.json, yara.txt, metadata.json, triage.json, ssdeep.txt, tlsh.txt. Dynamic analysis skipped (no CAPE Windows guest). Radare2 analysis at level 2 (aaa) executed; 1,498 functions identified. Decompilation unavailable due to Go ABI complexity.