typeanalysisfamilycoinminerconfidencemediumcreated2026-07-31updated2026-07-31compilerpemalware-familycryptominerdefense-evasionpython-pyinstallerobfuscation
SHA-256: af7aebb9817900fca79fc4d193f61b7f1c7550cf4cdd8bd6beed53f0ba023043

coinminer: af7aebb9 — PyInstaller bootloader, Sep 2018 MSVC build, 2.0 MB AES-encrypted overlay

Executive Summary

PyInstaller single-file PE32 dropper, fifteenth confirmed sibling in the September 2018 MSVC 2015 coinminer cluster. Shares the identical compilation timestamp, linker version, and bootloader behaviour with siblings 801fbba1 through 6b2591e40fbb. The 2.0 MB overlay (88.9% of the file) is a zlib-compressed PyInstaller CFFI archive with AES encryption — same --key campaign pattern as 359fcf01, 058ab625, 983d2606, f7abdaf8, fa98331d, f284c9aa, and 6b2591e40fbb. No mining pool strings recoverable from the outer binary; all threat logic lives inside the encrypted overlay.

What It Is

  • File: PE32 executable (GUI) Intel 80386, 6 sections ^[file.txt]
  • Size: 2,252,525 bytes (2.25 MB) ^[rabin2-info.txt]
  • Compiled: Tue Sep 4 14:43:33 2018 UTC ^[pefile.txt:34] ^[rabin2-info.txt]
  • Linker: MSVC 14.0 (Visual Studio 2015 RTM) ^[exiftool.json:18]
  • Signed: false; checksum 0x00000000 ^[rabin2-info.txt]
  • ASLR / DEP: enabled (DllCharacteristics: 0x8140) ^[pefile.txt:74]
  • Subsystem: Windows GUI ^[file.txt]
  • Overlay: 2,003,181 bytes starting at raw offset 0x3CE00, zlib-compressed CFFI archive with AES encryption ^[binwalk.txt] ^[manual_overlay_analysis]
  • Family: coinminer (OpenCTI label) ^[triage.json]

How It Works

Stock PyInstaller single-file bootloader circa 2018. Runtime sequence is identical to the cluster documented at coinminer and pyinstaller-bootloader:

  1. CRT initialisation — MSVC entry0 → main() → PyInstaller bootstrap core ^[r2:entry0]
  2. Archive resolution — locates the CFFI archive appended past the PE sections (overlay at 0x3CE00) ^[binwalk.txt]
  3. Extraction — decompresses 85 zlib blocks and decrypts AES-encrypted entries to %TEMP%\_MEI<XXXX> ^[manual_overlay_analysis]
  4. Python runtime bootstrap — loads the Python DLL, resolves CPython API procs (Py_Initialize, PyMarshal_ReadObjectFromString, etc.) ^[strings.txt:119-212]
  5. Script execution — unmarshals the embedded code object and runs __main__.py ^[strings.txt:104-111]
  6. Cleanup — deletes the temp directory on exit unless _MEIPASS2 is set ^[strings.txt:115]

AES encryption

Overlay entropy is 8.0/8.0 ^[manual_overlay_analysis], indicating the payload is encrypted rather than plaintext zlib. The 85 zlib headers in the overlay are decompressing individual AES-encrypted entries (the PyInstaller CFFI --key pattern). Based on cluster attribution, the encryption key is presumed to be the same weak QWERTY-derived string 1qazxsw23edcvfrN observed in siblings 359fcf01, 058ab625, 983d2606, f7abdaf8, fa98331d, f284c9aa, and 6b2591e40fbb, but the key module is not recoverable without decrypting the overlay first.

Cluster delta

Sibling Size Overlay Encryption Zlib blocks
801fbba1 799 KB ~570 KB None 15
39b67a79 4.3 MB ~4.2 MB None N/A
5047235c 1.75 MB ~1.6 MB None N/A
640ed5b5 735 KB ~640 KB None N/A
fbfd2d94 2.37 MB ~2.1 MB (89%) None 30+
b4cc27e3 630 KB ~380 KB (60%) None N/A
af7aebb9 2.25 MB ~2.0 MB (88.9%) AES 85
359fcf01 4.35 MB ~4.3 MB AES (known key) N/A
058ab625 2.76 MB ~2.5 MB AES (known key) N/A
983d2606 2.43 MB ~2.2 MB AES (known key) N/A
f7abdaf8 1.96 MB ~1.7 MB AES (known key) 29
fa98331d 4.07 MB ~3.8 MB AES (known key) 29
f284c9aa 6.1 MB ~5.8 MB AES (known key) 63
6b2591e40fbb 5.34 MB ~5.1 MB AES (known key) 285

Same compilation timestamp and bootloader across all fifteen siblings. This is the same build campaign with varying payload sizes and encryption state.

Decompiled Behaviour

  • entry0 (0x004079d3): MSVC CRT entry. Calls initialisers, then main(). No anti-debug or VM checks. ^[r2:entry0]
  • main (0x00401000): Three calls — archive status resolution, UTF-8 argv conversion, then fcn.00402520 (PyInstaller bootstrap core). ^[r2:main]
  • Imports are limited to standard Win32 + WS2_32.dll.ntohl (CRT artifact, not actively used). ^[pefile.txt:249-373]
  • .rsrc section contains 7 icon groups (PyInstaller default icon inheritance). ^[pefile.txt:159-492]
  • No appended secondary PE in the overlay (unlike sibling 5047235c). ^[manual_overlay_analysis]

C2 Infrastructure

Not statically observable. The outer binary contains only generic PyInstaller error strings and MSVC CRT locale strings. No hardcoded IPs, domains, pool URLs, or wallet addresses are recoverable without decrypting the overlay. Pool/C2 configuration is presumed to reside inside the AES-encrypted Python payload. ^[strings.txt]

Interesting Tidbits

  1. 85 zlib blocks — the highest block count in the cluster (previous record was 6b2591e40fbb with 285). This suggests a denser or more fragmented embedded Python runtime / payload structure. ^[binwalk.txt]
  2. No appended PE — unlike sibling 5047235c, there is no secondary PE executable appended at the end of the overlay. ^[manual_overlay_analysis]
  3. floss.txt and capa.txt failures — same recurring tool issues as the rest of the cluster: floss received a bad argument, capa lacks signatures. ^[floss.txt] ^[capa.txt]
  4. No YARA matches beyond generic PE — confirms no known mining-family signatures cover the outer bootloader shell. ^[triage.json]
  5. Overlay entropy 8.0 — the theoretical maximum for uniformly random data, confirming AES encryption rather than plaintext zlib compression. ^[manual_overlay_analysis]

How To Mess With It (Homelab Replication)

  • Toolchain: Install Python 2.7 + PyInstaller 3.4 on a Windows research VM.
  • Build an AES-encrypted onefile payload: pyinstaller --onefile --windowed --key '1qazxsw23edcvfrN' your_script.py
  • Verify: Overlay should show 80+ zlib headers with entropy near 8.0. strings should show _MEIPASS, PyInstaller, and inflate 1.2.8.
  • Decrypt: Recover the AES key from a known sibling (359fcf01), patch pyi-archive_viewer to use it, and dump the decrypted entries.
  • Learning outcome: Recognising that high-entropy overlays in PyInstaller binaries indicate --key encryption, which blocks simple static extraction and forces runtime or key-recovery approaches.

Deployable Signatures

YARA rule

rule PyInstallerBootloader_AESCoinminer_2018_af7aebb9 {
    meta:
        description = "PyInstaller single-file bootloader with AES-encrypted coinminer payload (2018 cluster, sibling af7aebb9)"
        author = "Titus"
        date = "2026-07-31"
        sha256 = "af7aebb9817900fca79fc4d193f61b7f1c7550cf4cdd8bd6beed53f0ba023043"
    strings:
        $pyi1 = "PyInstaller: FormatMessageW failed." ascii wide
        $pyi2 = "_MEIPASS2" ascii wide
        $pyi3 = "Failed to execute script %s" ascii wide
        $pyi4 = "pyi-runtime-tmpdir" ascii wide
        $pyi5 = "Installing PYZ: Could not get sys.path" ascii wide
        $inflate = "inflate 1.2.8 Copyright 1995-2013 Mark Adler" ascii wide
    condition:
        uint16(0) == 0x5a4d and
        3 of ($pyi*) and
        $inflate and
        filesize > 1MB and filesize < 3MB
}

Sigma rule

Not suitable for the outer binary — the thin bootloader exhibits no unique process-level behaviour. Sigma should target the child process spawned from %TEMP%\_MEI* (python.exe or renamed miner) within seconds of parent launch, combined with Stratum pool network connections (ports 3333, 4444, 45700).

IOC list

  • SHA-256: af7aebb9817900fca79fc4d193f61b7f1c7550cf4cdd8bd6beed53f0ba023043
  • Temp path pattern: %TEMP%\_MEI*\* (PyInstaller extraction directory)
  • Presumed AES key: 1qazxsw23edcvfrN (weak QWERTY pattern, inherited from cluster siblings)
  • Mutex / named pipe: not observed in outer binary
  • Registry: not observed in outer binary

Behavioural fingerprint

PE32 GUI executable compiled with MSVC 2015, containing a ~2 MB zlib-compressed overlay with AES encryption (PyInstaller --key). At runtime extracts the decrypted payload to a _MEI-prefixed temp directory, loads the Python DLL, and executes embedded Python bytecode. The outer binary carries no mining-specific imports or strings; all threat behaviour manifests inside the encrypted overlay and in spawned child processes. Eighty-five zlib blocks in the overlay distinguish this sibling from others in the cluster.

Detection Signatures

  • MITRE ATT&CK
    • T1059.006 (Python) — execution via embedded Python interpreter
    • T1074.001 (Data Staged: Local Data Staging) — extraction to temp directory
    • T1105 (Ingress Tool Transfer) — self-contained payload delivery
    • T1574.002 (DLL Side-Loading) — loading Python DLL from _MEI path
    • T1027 (Obfuscated Files or Information) — AES-encrypted overlay
  • Capa: non-functional (missing signatures). No ATT&CK mapping available. ^[capa.txt]

References

  • Artifact ID: 2062820f-c7b6-4a39-8bab-ab5458ea91a4 ^[metadata.json]
  • OpenCTI labels: coinminer, exe, urlhaus ^[triage.json]
  • Cluster sibling: /intel/analyses/801fbba19b4d4828191e87e7311480deaf81e84482dab70adf38d61afd01c1fa.html
  • Cluster sibling: /intel/analyses/359fcf01a54b89eabcbfcecd734e2af60b6bfa19ffd7fcdd87b1e4ed15db599c.html
  • Cluster sibling: /intel/analyses/f284c9aa10c186c297c5da17ee08d3b1c44be26b0623e305bb6826c9ebf9a40e.html
  • Cluster sibling: /intel/analyses/6b2591e40fbba62b96e76a515e426248ac0d9dc5d488054d143ea2e62610bc6a.html
  • Entity page: coinminer
  • Concept page: python-packed-payload
  • Concept page: pyinstaller-bootloader

Provenance

  • file.txt — file command (PE32 executable)
  • strings.txt — strings (4,287 lines)
  • pefile.txt — pefile Python module (sections, imports, resources)
  • binwalk.txt — binwalk (embedded artefacts / zlib blocks)
  • rabin2-info.txt — radare2 rabin2 -I (binary metadata)
  • exiftool.json — ExifTool PE metadata
  • triage.json — triage tier assignment
  • metadata.json — artifact metadata from OpenCTI
  • floss.txt — flare-floss (tool argument error, no decoded output)
  • capa.txt — flare-capa (signature path error, no output)
  • Manual overlay analysis — Python zlib header scan, entropy calculation, appended-PE search
  • R2 decompilation — radare2 via MCP (pdg at entry0, main)