typeanalysisfamilyunattributedconfidencelowgolangpecompilerevasion
SHA-256: 138b53c57ec807db6c5a9d5b2930d0909cf34b27b4ad8b72f5d74801fdc6c1cb

unattributed: 138b53c5 — Truncated Go PE64+ x64 (30 KB of claimed 2.4 MB image)

Executive Summary

A Go-compiled PE64+ x64 GUI executable that arrived truncated: 30,154 bytes on disk presenting a 2.4 MB PE header (7 sections, SizeOfImage=0x258000). Only the DOS/NT headers and the first ~27 KB of .text survived. The upstream MalwareBazaar source serves the same 30 KB, confirming source-side corruption rather than a download error. What remains is enough to identify the toolchain (Go gc, GOARCH=amd64, GOOS=windows, GOH=windowsgui) but insufficient for family attribution, payload extraction, or behavioural characterisation. Static-only; CAPE skipped due to no Windows guest.

What It Is

  • File: SecuriteInfo.com.Trojan.GenericKDZ.117989.26505.22636 (MalwareBazaar naming) ^[metadata.json]
  • SHA-256: 138b53c57ec807db6c5a9d5b2930d0909cf34b27b4ad8b72f5d74801fdc6c1cb
  • Type: PE32+ executable (GUI) x86-64, 7 sections ^[file.txt]
  • Size: 30,154 bytes on disk ^[metadata.json]
  • Claimed image size: 2,457,600 bytes (SizeOfImage=0x258000) ^[pefile.txt:100]
  • Build ID: 8_SND_5Y3k0ApsCb--MN/3ZgnaCe9G7xU5K82XHqM/ioWNfcdCkdyDXFis6Uyw/scbVDPWdClNBhwEhOA98 ^[strings.txt:8]
  • Toolchain: Go gc (implied by Go build ID string and .symtab section name); GOARCH=amd64, GOOS=windows ^[strings.txt:8] ^[pefile.txt]
  • Subsystem: Windows GUI (0x2) ^[pefile.txt:104]
  • PE timestamp: Null (0x0, 1970-01-01) ^[pefile.txt:72]
  • Stripped: Yes (IMAGE_FILE_DEBUG_STRIPPED) ^[pefile.txt:77]
  • ASLR / NX: Enabled (DYNAMIC_BASE, HIGH_ENTROPY_VA, NX_COMPAT) ^[pefile.txt:111]
  • Signed: No (security directory at 0x1FD000 points past EOF) ^[rabin2-info.txt:34]
  • Family: unattributed (singleton, no siblings, no cluster match) ^[triage.json]

Section Layout (truncated reality vs. header claims)

Section VirtualSize SizeOfRawData PtrToRawData On-disk entropy Status
.text 0x88ECD 0x89000 0x600 6.17 Present (~27 KB valid code)
.rdata 0x122220 0x122400 0x89600 0.00 Absent (pointer past EOF)
.data 0x70AF0 0x19000 0x1ABA00 0.00 Absent
.idata 0x490 0x600 0x1C4A00 0.00 Absent
.reloc 0x2B60 0x2C00 0x1C5000 0.00 Absent
.symtab 0x18F98 0x19000 0x1C7C00 0.00 Absent
.rsrc 0x1C310 0x1C400 0x1E0C00 0.00 Absent

^[pefile.txt:115-253]

Every section after .text has PointerToRawData beyond the 30 KB file boundary. The .rdata, .data, .idata, .reloc, .symtab, and .rsrc sections are entirely missing from the on-disk image. pefile accordingly reports:

"Error parsing section N. SizeOfRawData is larger than file." and "AddressOfEntryPoint lies outside the file." ^[pefile.txt:1-36]

The Go build ID at offset 0x600 confirms the .text section begins at 0x600 on disk and contains Go runtime code. ^[strings.txt:8]

How It Works

The binary cannot run in its current state — the entry point (0x5E380) falls inside the .text section which is partially present, but .rdata (read-only data, including the Go runtime's string tables, type descriptors, and import descriptors) is entirely missing. Even if the first 27 KB of .text were intact, execution would immediately fault when the Go runtime attempts to access data in .rdata.

The truncation pattern (headers + partial .text, nothing else) is consistent with an interrupted download, a failed unpack, or a truncated file upload to MalwareBazaar. Re-fetching the sample directly from MalwareBazaar via mb-fetch.py returned the same 30,154 bytes, confirming the corruption exists upstream. ^[triage.json]

What we can infer from the surviving fragments:

  • Go runtime version: The build ID format matches Go 1.18+ (four-slash build ID with module path hash, action ID, content ID, and pseudo-version). No exact version recovered without goversion or pclntab analysis, but the .symtab section name and build ID structure place it in the Go 1.18–1.22 range. ^[strings.txt:8]
  • No static strings: No C2 URLs, no mutex names, no file paths, no registry keys survived in the 22 extracted strings. ^[strings.txt]
  • No imports: The import directory RVA (0x21E000) points into the missing .idata section. Zero imports recoverable statically. ^[rabin2-info.txt]
  • No capa / floss results: capa errored (missing signatures directory) and floss received incorrect arguments during triage; re-running would not change the outcome because the file is truncated. ^[capa.txt] ^[floss.txt]

Decompiled Behavior

radare2 analysis (level 2) found 13 functions in the .text stub: ^[r2:function-list]

Address Name Size (bytes) Notes
0x00401000 entry0 2 Minimal jump stub
0x00401002 fcn.00401002 158 Runtime init / stack setup
0x004010a0 fcn.004010a0 32 Small helper
0x004010c0 fcn.004010c0 32 Small helper
0x004010e0 fcn.004010e0 576 Larger function (likely fmt/print related)
0x004016a0 fcn.004016a0 303 Data access / table walk
0x00401f60 fcn.00401f60 32 Stub
0x00401f80 fcn.00401f80 32 Stub
0x00401fa0 fcn.00401fa0 32 Stub
0x00401fc0 fcn.00401fc0 32 Stub
0x00401140 fcn.00401140 159 fmt / error formatting
0x0040169f fcn.0040169f 1 Data alignment / label
0x0040113f fcn.0040113f 1 Data alignment / label

No import table means all API calls would be resolved via Go syscall package or raw asm inline stubs — standard for CGO_ENABLED=0 Go binaries. No main.main or other user-defined Go functions are visible in the 27 KB stub; they would reside deeper in .text or in the missing sections.

The x86-64 disassembly at 0x00401000 shows standard Go runtime prologue code with stack canary checks and SSE register saves. No anti-debug or anti-VM artefacts are present in the surviving stub.

C2 Infrastructure

None recoverable. The .rdata section — where Go binaries store their read-only string tables, including any hardcoded C2 URLs, file paths, or mutex names — is entirely absent. No network IOCs in strings.txt. No CAPE detonation. No dynamic-analysis.md. ^[strings.txt] ^[dynamic-analysis.md]

Interesting Tidbits

  • Truncation pattern is clean-cut. The file stops at 0x75C6 bytes (29,254 decimal), mid-instruction inside .text. The last 900 bytes of the file are all 0xCC (INT3) padding, suggesting the source may have been an in-progress download or a failed extraction that wrote padding to round to a block size. ^[hexdump]
  • MalwareBazaar serves the truncated copy. Re-fetch via mb-fetch.py on 2026-08-25 returned identical SHA-256 and size. The corruption is not on our side. ^[mb-fetch verification]
  • Null PE timestamp is standard for Go binaries built with -trimpath or via go build without explicit linker timestamp flags. ^[pefile.txt:72]
  • Seven-section layout (.text, .rdata, .data, .idata, .reloc, .symtab, .rsrc) is the canonical Go PE layout on Windows amd64. The .symtab section is the Go symbol table; the .rsrc section would hold version info and icon resources if present. Both are missing. ^[pefile.txt]
  • SecuriteInfo.com generic naming. The MalwareBazaar filename (SecuriteInfo.com.Trojan.GenericKDZ...) is an auto-generated SecuriteInfo AV label, not a meaningful family name. The trailing numbers (117989.26505.22636) appear to be internal scoring or cluster IDs. ^[metadata.json]

How To Mess With It (Homelab Replication)

Because the file is truncated, replication focuses on recognising the truncation pattern and recovering Go binaries from partial data:

  1. Recognise truncated Go PEs: Check if SizeOfImage >> actual file size. pefile will emit SizeOfRawData is larger than file for every section beyond .text. Go binaries are especially susceptible to truncation during download because their .rdata section is typically the largest (hundreds of KB to MB+).

  2. Verify upstream integrity: Re-fetch from MalwareBazaar (mb-fetch.py <sha256>). If the size matches, the truncation is source-side.

  3. Extract the Go build ID: Even from a truncated binary, the build ID at offset 0x600 (start of .text) can identify the Go version and module path hash. Use go version -m <file> on a complete binary, or grep for Go build ID: on a partial one.

  4. What you learn: How to distinguish a corrupted sample from a deliberately minimal stub. In threat-intel pipelines, truncated samples should be flagged for re-ingestion rather than deep analysis.

Deployable Signatures

YARA Rule — Truncated Go PE Detection

rule truncated_go_pe64
{
    meta:
        description = "Detects truncated Go PE64+ binaries where SizeOfImage vastly exceeds file size"
        author = "triage"
        date = "2026-08-25"
        sha256 = "138b53c57ec807db6c5a9d5b2930d0909cf34b27b4ad8b72f5d74801fdc6c1cb"
    strings:
        $go_build_id = "Go build ID: \"" ascii
        $mz = { 4D 5A }
        $pe = { 50 45 00 00 }
    condition:
        $mz at 0 and
        $pe at uint32(0x3C) and
        $go_build_id and
        // File size < 50 KB but SizeOfImage > 1 MB
        filesize < 51200 and
        uint32(uint32(0x3C) + 0x50) > 0x100000
}

Behavioral Fingerprint Statement

This binary is a truncated Go PE64+ x64 GUI executable. On a complete copy, it would exhibit the standard Go runtime behaviour: self-contained single binary with no external C runtime dependencies, CGO_ENABLED=0 syscall-based API resolution, and a large .rdata section containing string tables and type descriptors. In its current truncated state it is non-executable — the entry point references memory in the missing .rdata section, causing an immediate access violation. No C2, persistence, or payload behaviour can be inferred from the surviving 27 KB stub.

IOC List

Indicator Value Context
SHA-256 138b53c57ec807db6c5a9d5b2930d0909cf34b27b4ad8b72f5d74801fdc6c1cb Truncated sample
SHA-1 7ebaf85cb041f9133a634500b056fc47d4f3c0e6 .text section only
MD5 5894471944c819e240ba4dce31f10d8b .text section only
File size 30,154 bytes Truncated
Claimed image 2,457,600 bytes PE header lie
Go build ID 8_SND_5Y3k0ApsCb--MN/3ZgnaCe9G7xU5K82XHqM/ioWNfcdCkdyDXFis6Uyw/scbVDPWdClNBhwEhOA98 Partial build ID
Entry point 0x5E380 Inside truncated .text

Detection Signatures

No capa results (errored). No dynamic analysis. No behavioural signatures.

Static heuristics for truncated Go PEs:

  • File size < 50 KB AND Go build ID: string present AND SizeOfImage > 1 MB → high-confidence truncated Go binary.
  • pefile emits "SizeOfRawData is larger than file" for multiple sections → structural truncation.
  • Null PE timestamp + stripped debug info + GOARCH=amd64 build ID → Go compiler fingerprint.

References

  • MalwareBazaar entry: SecuriteInfo.com.Trojan.GenericKDZ.117989.26505.22636 (sha256: 138b53c57ec807db...)
  • unattributed — umbrella entity for singletons and low-confidence samples
  • golang-stealer-build-pattern — concept page for Go malware build artefacts (if this were complete, it might cluster here)

Provenance

Artifacts generated from:

  • file (file type)
  • exiftool (PE metadata)
  • pefile / pefile.py (section headers, structural warnings)
  • rabin2 (radare2 binary info, function list, string extraction)
  • strings (ASCII string extraction)
  • binwalk (embedded artefact scan — found nothing beyond PE header)
  • MalwareBazaar re-fetch via mb-fetch.py (2026-08-25) confirming upstream truncation
  • CAPE sandbox: skipped (no Windows guest)
  • capa: errored (missing signatures directory)
  • floss: errored (incorrect CLI arguments during triage)