typeanalysisfamilyunclassified-go-pe64confidencemediumcreated2026-06-07updated2026-06-07pegolangcompilersigningevasioncode-injectionc2
SHA-256: 82ee3cddf123a959a53832e969045f5552dee6867fb7d359fe766b37e8479bae

unclassified-go-pe64: 82ee3cdd — Go 1.25.4 signed PE64 with multi-pass payload decryption and in-memory PE loader

Executive Summary

Signed Go 1.25.4 PE64 dropper/loader. The outer binary decrypts a ~744 KB embedded payload in-place via a four-pass custom algorithm, performs PE relocation fixups, and executes it in RWX memory. No C2 strings, browser-targeting strings, or stealer indicators survive statically — they live inside the decrypted second stage. Shares a GoDaddy DV certificate and build pattern with the 589af0f8 sibling already catalogued under unclassified-go-pe64.

What It Is

Field Value Provenance
SHA-256 82ee3cddf123a959a53832e969045f5552dee6867fb7d359fe766b37e8479bae ^[metadata.json]
Size 2.4 MB (2,443,448 bytes) ^[metadata.json]
File type PE32+ executable (GUI) x86-64, 8 sections ^[file.txt]
Go version go1.25.4 ^[strings.txt] (buildinfo at offset 0x222200)
Build GOOS=windows GOARCH=amd64 GOAMD64=v1 CGO_ENABLED=0 -trimpath ^[strings.txt]
Module path ufyMQEPaAMBKqYk (randomized 15-char alpha) ^[strings.txt]
TimeDateStamp 0x0 (fabricated/stripped) ^[pefile.txt]
Authenticode GoDaddy G2 DV, CN=maybe.us, serial 86:ee:39:e0:b3:fd:88:5f, 4096-bit RSA, SHA-256, valid Jun 2025–Jun 2026 ^[binwalk.txt] + openssl extraction
Signed Yes (overlay PKCS #7 at file offset 0x254000) ^[pefile.txt]
Stripped No — .symtab retained with 2,540 symbols ^[pefile.txt]
.rsrc Absent (no icon masquerade) ^[pefile.txt]
YARA match PE_File_Generic only ^[yara.txt]
CAPE Skipped — no Windows guest available ^[dynamic-analysis.md]

The binary is entirely standard-library Go; no third-party dependency paths appear in strings because -trimpath was used.^[strings.txt]

How It Works

Entry point (main.main) calls three helper functions in sequence:

  1. main.rwpabdjnjvkz — allocates a 256-byte buffer, fills it with sequential bytes 0x00–0xff, computes crypto/md5.Sum over the buffer, and stores the 16-byte digest into a global.^[r2:sym.main.rwpabdjnjvkz] This digest becomes a keying material source for later stages.

  2. main.xbgysp — seeds the Go math/rand generator with time.Now().UnixNano(), fills a 512-byte buffer with math/rand.Intn(256), computes crypto/sha256.Sum256 over that buffer, then sums the 32 bytes into a 64-bit integer stored to the same global.^[r2:sym.main.xbgysp] This produces a second key derivation path.

  3. main.bivfnuttklixoi — the orchestrator. It builds a 100-element slice of sequential multiples-of-three integers, calls main.pzkkljvngbdx (the heavy lifter), then sums the slice elements and stores the result.^[r2:sym.main.bivfnuttklixoi]

The Heavy Lifter: main.pzkkljvngbdx

This ~3,700-line function (decompiled) performs the full reflective-loading pipeline:

  1. API resolution via fused-string concatenation. It constructs Go string objects by slicing long concatenated blobs where Win32 API names are fused with Go runtime strings:

    • "advapi32.dllGetUserNameAVirtualAllocrandautoseedsweepWaiterscleanupQueuetraceStringsspanSetSpinemspanSpecialtraceTypeTabgcBitsA"^[r2:sym.main.pzkkljvngbdx]
    • "VirtualProtectuserArenaStateGC__dedicated_read_mem_statsupdatemaxprocsasynctimerchangcstoptheworldprofstackdepthtraceallocfreeG"^[r2:sym.main.pzkkljvngbdx] It instantiates syscall.NewCallback and syscall._LazyProc_, then calls VirtualProtect to mark the target region executable.^[r2:sym.main.pzkkljvngbdx]
  2. Payload extraction. Copies 0xb5c00 (744,448) bytes from a hardcoded .rdata blob via main.pyoeursboua.^[r2:sym.main.pzkkljvngbdx]

  3. Decryption. Invokes main.sysyjbbndnbs to decrypt the copied payload in-place. The decryption algorithm is a custom four-pass stream:

    • Pass 1: modular subtraction using constants 0x4d4873ecade304d5 and 0xa8e83f5717c0a8e9.^[r2:sym.main.pyoeursboua]
    • Pass 2: in-place byte shuffle (swap pairs, then iterate with stride-2 XOR/replace).^[r2:sym.main.pyoeursboua]
    • Pass 3: subtract a rolling 8-bit value shifted right by eight.^[r2:sym.main.pyoeursboua]
    • Pass 4: XOR each byte with its index and a derived 8-bit key.^[r2:sym.main.pyoeursboua]
  4. Memory allocation. Calls main.cfgwqj to allocate an RWX (PAGE_EXECUTE_READWRITE, 0x40) region of size 0x3000 or larger via VirtualAlloc.^[r2:sym.main.pzkkljvngbdx]

  5. Relocation fixups. If the decrypted payload’s IMAGE_FILE_HEADER.Characteristics indicate it requires relocation (or if a flag is set), calls main.lckgmwhkh to apply base-relocation fixups. The function walks the .reloc directory, handling IMAGE_REL_BASED_DIR64 (type 10), IMAGE_REL_BASED_HIGHLOW (type 3), IMAGE_REL_BASED_HIGHADJ (type 4), and IMAGE_REL_BASED_LOW (type 2).^[r2:sym.main.lckgmwhkh]

  6. Execution. Calls main.fbmzdfrtddz to parse the decrypted PE’s export table, resolve APIs via GetProcAddress, then main.zotyvx transfers control to the decrypted entry point.^[r2:sym.main.pzkkljvngbdx]

Because the payload is encrypted in the .rdata section and only decrypted at runtime, static extraction of C2, browser paths, or stealer strings is impossible without reimplementing the cipher.

C2 Infrastructure

None recovered statically. All network, browser-targeting, and exfiltration indicators live inside the encrypted second-stage payload. The outer Go wrapper provides pure loader functionality. The decrypted payload (~744 KB) is likely a commodity infostealer (historically Lumma/ACR/Meno in this cluster), but that is an inference, not a proven fact for this SHA-256.

Interesting Tidbits

  • The main.pyoeursboua (decryptor) function name and the main.sysyjbbndnbs (pre-processor) name are 15-character randomized strings, matching the module path length — the builder uses a uniform random-naming scheme for everything.^[r2:sym.main.pyoeursboua]
  • The fused strings in .rdata are not obfuscated with XOR or encryption; they are simply concatenated end-to-end, relying on Go’s slice-bounds slicing to extract substrings at runtime. This defeats naive strings-based IOC extraction but is trivially recoverable with Ghidra or floss.^[r2:sym.main.pzkkljvngbdx]
  • Certificate CN=maybe.us is a throwaway domain parked with GoDaddy. It has been observed on at least one prior sibling (589af0f8). The serial number (86:ee:39:e0:b3:fd:88:5f) is identical between those two samples, confirming certificate reuse across builds.

How To Mess With It (Homelab Replication)

Toolchain: Go 1.25.4 windows/amd64, CGO_ENABLED=0.

Compiler flags:

go build -ldflags="-H windowsgui -s" -trimpath

Replication sketch:

  1. Embed a PE payload as a //go:embed payload.bin resource.
  2. Implement the four-pass decryptor in Go (see main.pyoeursboua for constants).
  3. Use syscall.VirtualProtect (via syscall.NewLazyDLL + NewProc) to mark memory RWX.
  4. Use reflect.SliceHeader or unsafe.Pointer to cast the decrypted blob to a function pointer and call it.
  5. Add runtime.ReadMemStats and time.Sleep(0x989680) (10s) loops to match the vzcegglcftbzfko telemetry pattern observed in this cluster.

Verification: Compile, run strings on the output, and confirm the presence of build\tGOOS=windows, path\t<random>, and no absolute module paths.

Deployable Signatures

YARA Rule

rule UnclassifiedGoPE64_Loader_MaybeUS {
    meta:
        description = "Go 1.25.4 PE64 signed dropper/loader cluster, CN=maybe.us"
        author = "PacketPursuit"
        date = "2026-06-07"
        sha256 = "82ee3cddf123a959a53832e969045f5552dee6867fb7d359fe766b37e8479bae"
        family = "unclassified-go-pe64"
    strings:
        $go_build = "go1.25.4"
        $go_os = "build\tGOOS=windows"
        $go_arch = "build\tGOARCH=amd64"
        $mod_path = /path\t[a-zA-Z]{12,20}/
        $mod_dev = /mod\t[a-zA-Z]{12,20}\t\(devel\)/
        $advapi_fused = "advapi32.dllGetUserNameAVirtualAllocrandautoseedsweepWaiterscleanupQueuetraceStringsspanSetSpinemspanSpecialtraceTypeTabgcBitsA"
        $vp_fused = "VirtualProtectuserArenaStateGC (dedicated)read mem statsupdatemaxprocsasynctimerchangcstoptheworldprofstackdepthtraceallocfreeG"
    condition:
        uint16(0) == 0x5a4d and
        filesize > 2MB and filesize < 5MB and
        $go_build and $go_os and $go_arch and
        ($mod_path or $mod_dev) and
        ($advapi_fused or $vp_fused)
}

Sigma Rule

title: Go PE64 Signed Loader Process Creation with RWX Allocation
logsource:
    category: process_creation
    product: windows
detection:
    selection:
        - Image|endswith:
            - '.exe'
        - CommandLine|contains:
            - 'VirtualProtect'
            - 'VirtualAlloc'
    condition: selection
    # Operationalized: hunt for Go-compiled executables (Go build ID in .text) that call VirtualAlloc
    # with PAGE_EXECUTE_READWRITE (0x40) within 5 seconds of process start.

IOC List

Type Value Note
SHA-256 (outer) 82ee3cddf123a959a53832e969045f5552dee6867fb7d359fe766b37e8479bae Loader
SHA-256 (payload) Unknown In-memory only
Certificate CN maybe.us GoDaddy G2 DV
Certificate serial 86:ee:39:e0:b3:fd:88:5f Reused from 589af0f8 sibling
Module path ufyMQEPaAMBKqYk Randomized per build
Function names rwpabdjnjvkz, xbgysp, bivfnuttklixoi, pzkkljvngbdx, pyoeursboua, sysyjbbndnbs, cfgwqj, lckgmwhkh, fbmzdfrtddz, zotyvx, hidyepfce, lxmoxfslpsjdnk, Ecmeqfevvyhfkf, imvehatitmen, ykjbzfootuzxk, arxsco, cfgwqj, gogwakcldizwvj, ihwljw, wmsqgyj, vzcegglcftbzfko 23 randomized main.* identifiers
Payload size 0xb5c00 (744,448 bytes) Embedded in .rdata
Memory permission PAGE_EXECUTE_READWRITE (0x40) Via VirtualProtect

Behavioral Fingerprint

This binary is a Go 1.25.4 PE64 with a GUI subsystem and Authenticode signature. On launch it seeds the PRNG with wall-clock time, performs two hash-based key derivations (MD5 and SHA-256), allocates a scratch buffer, decrypts a ~744 KB embedded payload using a four-pass custom stream cipher (modular subtraction, byte shuffle, rolling subtraction, index-XOR), parses the decrypted blob as a PE image, applies relocation fixups if required, marks the target region RWX via VirtualProtect, and transfers execution to the decrypted entry point. No C2 strings are present in the outer binary; all network behavior is expected to reside in the decrypted second stage.

Detection Signatures

Technique ATT&CK ID Evidence
Reflective code loading T1620 Decrypted PE executed from RWX memory without touching disk
Process injection via RWX allocation T1055 VirtualAlloc with PAGE_EXECUTE_READWRITE + memcpy + transfer of control
Native API loading T1106 LoadLibraryW + GetProcAddress via syscall._LazyProc_
Code signing T1553.002 Authenticode signature (GoDaddy DV, CN=maybe.us) to evade ML-based and trust-based defenses
Data obfuscation: custom payload encryption T1027.002 Four-pass custom stream cipher over embedded .rdata payload
Runtime API resolution T1106 GetProcAddress for VirtualProtect and other Win32 APIs
Timestamp manipulation T1070.006 TimeDateStamp=0x0 in PE header

References

  • unclassified-go-pe64 — Parent cluster entity page (siblings 589af0f8, cc4aa789).
  • golang-stealer-build-pattern — Shared build artefacts across this cluster.
  • raw/analyses/589af0f87f4087f34750995ce679024df4e04acd0d096fe49e7f1223cb5905ae — First sibling with identical certificate.

Provenance

Artifacts consumed: file.txt, exiftool.json, pefile.txt, strings.txt, ssdeep.txt, tlsh.txt, yara.txt, metadata.json, triage.json, rabin2-info.txt, binwalk.txt, dynamic-analysis.md. Tools: radare2 (analysis level 3, aang Go recovery), openssl (PKCS #7 cert extraction), Python 3 (string scraping, buildinfo parsing), custom scripts. Capa and floss failed: capa signatures path missing; floss CLI parse error on arguments.