typeanalysisfamily54e64econfidencehighcreated2026-09-07updated2026-09-07malware-familyloaderdefense-evasionc2evasiongoreflective-code-loadingprng-decryptorself-signed-cert
SHA-256: d8a6366c9fbf5a41c82774f1e499aebe1a9bf9b078331f5a2c174ca0785c3b92

54e64e: d8a6366c — Go 1.25.9 reflective PE loader, self-signed unscramblex.com, 13-function PRNG decryptor

Executive Summary

Go 1.25.9 PE64+ reflective loader with a PRNG-driven multi-stage payload decryptor. Self-signed Authenticode certificate CN=unscramblex.com. Thirteen randomized main.* functions — a stripped-down variant of the Go loader morph first seen in 018ef44b. No infostealer surface; no browser, crypto, or exfiltration strings. Static-only (CAPE skipped — no Windows guest).

What It Is

  • File: PE32+ executable (GUI) x86-64, 8 sections, 1.93 MB ^[file.txt]
  • Compiler: Go 1.25.9, CGO_ENABLED=0, trimpath=true, GOOS=windows, GOARCH=amd64, GOAMD64=v1 ^[strings.txt:1510-1520]
  • Build ID: YPlgVebmwN1vrIfko_PW/L5EZKau57xXoiFJs7kxb/DaomgXQ-haVMc8iRHmEz/O9M77OW2iEhlXOoJrbzv ^[strings.txt:9]
  • Module path: fkfcQPBhFOUhPHI (randomized) ^[strings.txt:1512]
  • Signing: Self-signed Authenticode, 4096-bit RSA. Subject CN=unscramblex.com, issuer CN=E7, validity 2026-04-06 to 2026-07-05. ^[binwalk.txt:4-5] ^[pefile.txt:252-254]
  • IAT: 44 kernel32.dll imports only — LoadLibraryW, GetProcAddress, VirtualAlloc, CreateThread, etc. No ws2_32, winhttp, or crypt32 in static IAT. ^[pefile.txt:288-344]
  • Stripping: Not stripped; .symtab section present (95,316 bytes) with 2,219 symbols. Unusual for Go malware — suggests builder does not run strip or go build -ldflags="-s -w". ^[pefile.txt:218-235]
  • Packing: None. No UPX, no outer crypter. ^[yara.txt]
  • Resources: No .rsrc section; no version info, no icon, no masquerade. ^[pefile.txt:245-248]
  • Timestamp: Zeroed (Thu Jan 1 00:00:00 1970). ^[pefile.txt:34]

How It Works

This sample is a fourteenth confirmed build morph under the 54e64e OpenCTI umbrella. It belongs to the Go reflective PE loader lineage (Morph 12, first seen in 018ef44b), but uses a newer Go toolchain (1.25.9 vs 1.25.4) and a significantly reduced function count (13 randomized main.* functions vs 55 in the prior sibling). The reduced surface suggests either a stripped-down builder configuration or compiler optimization / inlining that collapsed the earlier multi-stage pipeline into fewer functions.

Entry-Point Behavior (static inference from decompilation)

main.main ^[r2:sym.main.main] performs the following:

  1. PRNG seeding: Computes a seed value from a constant base (0xdd7b17f80) mixed with time.Now().UnixNano() via math_rand._rngSource_.Seed.
  2. Delay gates: Calls math_rand._Rand_.Intn and math_rand._Rand_.Float64 in loop structures gated by ucomisd (floating-point comparison) against hardcoded constants (e.g., 0x3ff0000000000000 = 1.0, 0x4020000000000000 = 8.0). These are time-delay or entropy-accumulation loops. ^[r2:sym.main.main]
  3. Payload decryption: Calls sym.main.efvsjgrpysok ^[r2:sym.main.efvsjgrpysok], the primary decryptor/loader function. This function:
    • Allocates a large stack frame (0x71a30 bytes).
    • Copies 0xe200 quadwords (≈ 455 KB) from a fixed .rdata offset (rip + 0x48d10) into the stack buffer — this is the encrypted payload. ^[r2:sym.main.efvsjgrpysok]
    • Calls sym.main.ifzkoja and sym.main.pjceupx — likely key-schedule or initialization routines.
    • Calls sym.main.gibxwporkamofsc with arguments 0x40 (PAGE_EXECUTE_READWRITE) and 0x3000 (MEM_COMMIT | MEM_RESERVE) — a VirtualAlloc wrapper. ^[r2:sym.main.efvsjgrpysok]
    • Calls sym.main.wmisltgay and sym.main.jzvghmcfnazgg — data-transform routines that operate on the copied payload. wmisltgay contains word-level XOR/ADD logic with 0xfff masks and shift operations consistent with a stream-cipher or block-cipher round. ^[r2:sym.main.wmisltgay]
    • Calls sym.syscall.Syscall with five arguments — direct Windows native API invocation. ^[r2:sym.main.efvsjgrpysok]
    • Re-seeds the PRNG with time.Now().Unix() and enters nested loops that call math_rand._Rand_.Float64 and math_rand._Rand_.Intn with constants (e.g., 0x4034000000000000 = 20.0, 0x402e0000000000000 = 15.0) to build or modify the decoded payload structure. ^[r2:sym.main.efvsjgrpysok]
    • Calls sym.runtime.growslice repeatedly — the decrypted payload is being parsed into a Go slice structure, likely a PE header walk or import table rebuild.
  4. Execution transfer: Not directly visible in the decompiled main.main (the function is truncated), but the pattern matches the Morph 12 sequence: decoded payload parsed as a PE image, mapped into RWX memory, and execution transferred via syscall.Syscall or a Go function pointer call.

Notable Functions

Function Role (inferred)
main.main Entry point; PRNG seeding, delay gates, orchestrates decryptor
main.efvsjgrpysok Primary decryptor/loader; copies payload, allocates RWX, transforms data, syscall dispatch
main.wmisltgay Word-level payload transformation (XOR/ADD/SHIFT with 0xfff masks)
main.jzvghmcfnazgg Secondary payload transformation (called after wmisltgay)
main.ifzkoja Key-schedule / decryptor initialization (called before alloc)
main.pjceupx Secondary decryptor initialization (called after ifzkoja)
main.gibxwporkamofsc VirtualAlloc wrapper (0x40, 0x3000 arguments)
main.xqfxklpdi Float arithmetic helper (used in delay gate)
main.awyhoepgiwsu Float arithmetic helper (used in delay gate)
main.hsksieodze String parsing helper (strings.SplitN, strings.TrimSpace, strconv.ParseFloat)
main.uwzhxrbzqeselt Floating-point summation loop (entropy accumulator)

C2 Infrastructure

No hardcoded network IOCs recovered statically. The payload is decrypted at runtime; any C2 configuration lives inside the encrypted blob. The static IAT contains no Winsock, WinHTTP, or WinInet imports, but the runtime syscall.Syscall surface can resolve any API dynamically. No domains, IPs, URLs, or mutex names found in cleartext. ^[strings.txt]

Interesting Tidbits

  • Reduced function count: Only 13 main.* functions vs 55 in 018ef44b (Morph 12). This is the smallest-function-count Go loader seen in the 54e64e cluster. Likely caused by Go compiler inlining or a stripped-down builder template. ^[strings.txt]
  • .symtab preserved: The binary retains a full symbol table (95 KB). Most Go malware strips with -ldflags="-s -w". This suggests the builder is either misconfigured or intentionally left symbols to aid debugging/repacking. ^[pefile.txt:218-235]
  • Certificate CN: unscramblex.com is a new masquerade domain not seen in prior siblings (previous CNs: WE1, godaddy.com, askart.com, seekingalpha.com, xxx.com). The issuer is bare E7 — minimal self-signing template. ^[binwalk.txt]
  • No infostealer strings: Zero evidence of browser credential theft, cryptocurrency wallet extraction, clipboard hijacking, or Telegram/Discord exfiltration. This is a pure loader, not a stealer. Contrast with Morphs 3, 6, and 9 which are Go infostealers. ^[strings.txt]
  • Go 1.25.9: Newer than the 1.25.4 used in Morph 12. The runtime strings contain updated Go 1.25 standard-library artifacts (e.g., internal/runtime/atomic generics, fips140 indicators). ^[strings.txt:1510]
  • capa/floss failures: capa failed due to missing signatures directory. floss failed with argument-parsing error. Both tools require manual re-run with corrected paths. ^[capa.txt] ^[floss.txt]

How To Mess With It (Homelab Replication)

Toolchain: Go 1.25.9, Windows amd64 target, CGO_ENABLED=0, trimpath=true.

Build recipe:

go mod init fkfcQPBhFOUhPHI
go build -ldflags="-H=windowsgui" -o loader.exe main.go

To reproduce the PRNG-driven decryptor pattern:

  1. Embed a PE payload as a byte slice in main.go.
  2. Seed math/rand with time.Now().UnixNano() mixed with a constant.
  3. Implement a delay gate: loop rand.Float64() until the value exceeds a threshold (e.g., 0.5).
  4. Implement a word-wise transform: for each 16-bit word, XOR with rand.Intn(0xfff) and ADD a rand.Float64()-derived offset.
  5. Allocate RWX memory with VirtualAlloc via syscall.Syscall (or golang.org/x/sys/windows).
  6. Copy decoded payload and transfer execution with syscall.Syscall to the entry point.

Verification: Run capa on the reproducer — should hit T1620 (reflective code loading) if signatures are installed. Compare strings output to this sample: expect go1.25.9, math/rand, syscall.Syscall, time.Now, and randomized main.* function names.

Deployable Signatures

YARA Rule

rule Go_Reflective_Loader_54e64e_D8A6366C
{
    meta:
        description = "Go 1.25.x reflective PE loader with PRNG-driven decryptor (54e64e cluster)"
        author = "Titus"
        date = "2026-09-07"
        sha256 = "d8a6366c9fbf5a41c82774f1e499aebe1a9bf9b078331f5a2c174ca0785c3b92"
        reference = "raw/analyses/d8a6366c9fbf5a41c82774f1e499aebe1a9bf9b078331f5a2c174ca0785c3b92"
    strings:
        $go_ver = "go1.25." ascii
        $build_id = "Go build ID:" ascii
        $trimpath = "build\t-trimpath=true" ascii
        $cgo_disabled = "build\tCGO_ENABLED=0" ascii
        $mod_rand = "math/rand" ascii
        $mod_syscall = "syscall.Syscall" ascii
        $mod_time = "time.Now" ascii
        $mod_unix = "time.Time.UnixNano" ascii
        $main_prefix = "*main." ascii
        $runtime_newobj = "sym.runtime.newobject" ascii
    condition:
        uint16(0) == 0x5a4d and
        $go_ver and
        $build_id and
        $trimpath and
        $cgo_disabled and
        $mod_rand and
        $mod_syscall and
        $mod_time and
        $mod_unix and
        #main_prefix >= 10 and
        filesize < 3MB
}

Behavioral Hunt Query (Sigma-like)

title: Go Reflective PE Loader PRNG Decryptor
detection:
  selection_pe:
    - FileType: PE32+
    - Image: '*.exe'
  selection_go:
    - Strings|contains:
      - 'go1.25.'
      - 'math/rand'
      - 'syscall.Syscall'
      - 'time.Now'
      - 'Go build ID'
  selection_behavior:
    - ProcessCommandLine|contains:
      - 'VirtualAlloc'
    - LoadedDlls:
      - 'kernel32.dll'
  condition: selection_pe and selection_go and selection_behavior

IOC List

  • SHA-256: d8a6366c9fbf5a41c82774f1e499aebe1a9bf9b078331f5a2c174ca0785c3b92
  • SHA-1: 406d1405171e191239d6ffa67218c46181463c17 (from .text section) ^[pefile.txt:94]
  • MD5: 4c28afc6c382d0c3f93ad55feb9aa5be (from .data section) ^[pefile.txt:133]
  • SSDEEP: 24576:gc58li5AOmBOa3nqfiGe0TOHF7WwG0cljYMxwELfLBele5ZK2h48YT:gc2liyOmBJXqfiyTOHxLaQeHA ^[ssdeep.txt]
  • TLSH: 1D955B1BACA109E6C49A63338DB762817BB5B8480F3223C72E50B6783F767D45D3A754 ^[tlsh.txt]
  • Certificate CN: unscramblex.com
  • Certificate Issuer: E7
  • Certificate Validity: 2026-04-06 to 2026-07-05
  • Build ID: YPlgVebmwN1vrIfko_PW/L5EZKau57xXoiFJs7kxb/DaomgXQ-haVMc8iRHmEz/O9M77OW2iEhlXOoJrbzv
  • Module Path: fkfcQPBhFOUhPHI
  • Entry Point: 0x71540 (RVA) ^[pefile.txt:50]

Behavioral Fingerprint

This binary is a Go 1.25.x PE64+ executable with a Windows GUI subsystem and no visible window code. It imports only kernel32.dll statically (LoadLibraryW, GetProcAddress, VirtualAlloc, CreateThread). On launch, it seeds a math/rand PRNG with a time-derived value, enters floating-point comparison delay loops, copies an embedded encrypted payload from .rdata into a large stack-allocated buffer, applies word-wise XOR/ADD transformations, allocates RWX memory via a VirtualAlloc wrapper, and transfers execution to the decoded payload through a syscall.Syscall direct native API call. The binary retains a full .symtab symbol table and carries a self-signed Authenticode certificate with a randomized CN.

Detection Signatures

Capability ATT&CK ID Evidence
Reflective Code Loading T1620 Go-based PRNG decryptor → RWX VirtualAlloc → execution transfer ^[r2:sym.main.efvsjgrpysok]
Native API T1106 syscall.Syscall direct Windows API invocation ^[r2:sym.main.efvsjgrpysok]
Deobfuscate/Decode Files or Information T1027 math/rand-driven custom decryptor with word-wise transforms ^[r2:sym.main.wmisltgay]
Process Injection T1055 Reflective PE loader pattern; payload mapped into RWX region and executed ^[r2:sym.main.efvsjgrpysok]
Virtualization/Sandbox Evasion T1497.001 PRNG seeded with time.Now().UnixNano() acts as time-based gate ^[r2:sym.main.main]
Masquerading T1036.005 Self-signed Authenticode cert CN=unscramblex.com masquerades as legitimate software ^[binwalk.txt]

References

  • 54e64e — Family entity page with full cluster analysis and prior morphs
  • raw/analyses/018ef44b2d71de8d1bfb768592daa406a91a6187bc87a74dee67cb2a0d344f0a — Morph 12 (Go 1.25.4 reflective PE loader, 55 functions, CN=xxx.com)
  • raw/analyses/8017acd59116f1a84c43953daa1fc856afb65f34b72f438710fcd6094ac9486b — Morph 3 (Go 1.25.4 infostealer, CN=WE1)
  • raw/analyses/2f23087fd9b9804115c782d2d0f88046d370162b5b982299ae0a518ade9664b5 — Morph 6 (Go 1.20.6 infostealer, GlobalSign cert)
  • raw/analyses/0b6c65cde50cae62eb3e15a9857193abd2ed130f8d73de6afc3e58ac2397c49a — Morph 9 (Go 1.24.0 AFK Stealer, UPX-packed)

Provenance

  • file.txt — file command output (PE32+ x86-64, 8 sections)
  • exiftool.json — PE header metadata (Win64 EXE, GUI subsystem, zero timestamp)
  • pefile.txt — pefile full dump (sections, imports, directories, hashes per section)
  • strings.txt — strings -n 6 output (7,743 lines, Go runtime, main.* symbols, build info)
  • rabin2-info.txt — radare2 binary header (lang=go, signed=true, canary=true, nx=true)
  • binwalk.txt — Embedded signature scan (PKCS#7 cert at 0x1E2A08)
  • ssdeep.txt / tlsh.txt — Fuzzy hashes
  • capa.txt — capa failure log (missing signatures)
  • floss.txt — floss failure log (argument parsing error)
  • yara.txt — YARA match: PE_File_Generic only
  • Radare2 analysis (level 2, 1,925 functions) — decompilation of sym.main.main, sym.main.efvsjgrpysok, sym.main.wmisltgay, sym.main.hsksieodze, sym.main.awyhoepgiwsu, sym.main.xqfxklpdi
  • dynamic-analysis.md — CAPE skipped (no Windows guest available)
  • OpenCTI labels: 54e64e, dropped-by-amadey, exe, malware-bazaar, signed ^[triage.json]