typeanalysisfamilycoinminerconfidencemediumcreated2026-06-06updated2026-06-06compilerpemalware-familycryptominerdefense-evasionpython-pyinstallerobfuscation
SHA-256: 359fcf01a54b89eabcbfcecd734e2af60b6bfa19ffd7fcdd87b1e4ed15db599c

coinminer: 359fcf01 — PyInstaller bootloader sibling, Sep 2018 MSVC build, AES-encrypted overlay with weak QWERTY key

Executive Summary

PyInstaller single-file PE32 dropper, fifth observed sibling in the September 2018 MSVC 2015 cluster. Shares an identical compilation timestamp, linker version, and bootloader behaviour with 801fbba1, 39b67a79, 5047235c, and 640ed5b5. The ~4.3 MB overlay is a zlib-compressed PyInstaller CFFI archive with an AES-encrypted payload (PyInstaller --key option), using the hardcoded key 1qazxsw23edcvfrN — a QWERTY-keyboard walking pattern with a trailing N. Build metadata reveals the author's local project path: F:\files\ftp\crack\exe\build\ftpcrack\. No mining pool strings are recoverable from the outer binary; threat logic is entirely contained inside the encrypted overlay.

What It Is

  • File: PE32 executable (GUI) Intel 80386, 6 sections ^[file.txt]
  • Size: 4,570,578 bytes (4.35 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) ^[exiftool.json:18]
  • Signed: false ^[rabin2-info.txt]
  • ASLR / DEP: enabled (DllCharacteristics: 0x8140) ^[pefile.txt:74]
  • Subsystem: Windows GUI ^[file.txt]
  • Overlay: 4,321,234 bytes starting at raw offset 0x3CE00, zlib-compressed CFFI archive with AES encryption ^[binwalk.txt] ^[manual_analysis]
  • Family: coinminer (OpenCTI label) ^[triage.json]

How It Works

This binary is a PyInstaller single-file bootloader that performs the same runtime sequence documented at pyinstaller-bootloader and in the cluster page coinminer:

  1. CRT initialisation — MSVC entry0main() → 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 zlib blocks and decrypts AES-encrypted entries to %TEMP%\_MEI<XXXX> ^[manual_analysis]
  4. Python runtime bootstrap — loads the Python DLL, resolves CPython API procs (Py_Initialize, PyMarshal_ReadObjectFromString, PyEval_EvalCode, 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

Unlike the earlier 801fbba1 sibling (no encryption), this sample was built with the PyInstaller --key option. The first overlay zlib chunk decompresses to reveal a pyimod00_crypto_key module containing a hardcoded AES key: ^[manual_analysis]

`1qazxsw23edcvfrN(
F:\files\ftp\crack\exe\build\ftpcrack\pyimod00_crypto_key.pyt
<module>

The key 1qazxsw23edcvfrN follows a QWERTY-keyboard diagonal walking pattern (1qazxsw23edcvfr) with a trailing N, a textbook example of weak, predictable key material. Because the archive is AES-encrypted, the remaining overlay entries cannot be decompressed statically without re-implementing PyInstaller's AES decryption loop, which is why no pool or miner strings are visible.

Cluster delta

Sibling Size Overlay Encryption Key visible? Build path
801fbba1 799 KB ~570 KB None N/A Not recovered
39b67a79 4.3 MB ~4.2 MB None N/A Not recovered
5047235c 1.75 MB ~1.6 MB None N/A Not recovered
640ed5b5 735 KB ~640 KB None N/A Not recovered
359fcf01 4.35 MB ~4.3 MB AES Yes (QWERTY key) F:\files\ftp\crack\exe\build\ftpcrack\

The compilation timestamp, linker version, and bootloader strings are identical across all five siblings — this is the same build campaign, merely varying payload size and (in this case) adding AES encryption.

Decompiled Behaviour

  • entry0 (0x004079d3): MSVC CRT entry. Calls initialisers, then main(). No anti-debug or VM checks. ^[r2:entry0]
  • Imports are limited to standard Win32 + WS2_32.dll.ntohl (likely pulled in by the CRT, not actively used by the thin bootloader) ^[pefile.txt:249-373]
  • The .rsrc section contains 7 icon groups (PyInstaller default icon inheritance) ^[pefile.txt:159-492]
  • Entropy of .text is 6.65, .rsrc is 7.26 — neither is packed; the heavy entropy lives in the encrypted overlay. ^[pefile.txt:91-172]

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]

Known overlay artefacts (pre-decryption):

  • pyimod00_crypto_key — AES key provider module
  • pyimod01_os_path — PyInstaller runtime path shim (Python 2.7 path: C:\Python27\Lib\site-packages\PyInstaller\loader\) ^[manual_analysis]
  • pyiboot01_bootstrap — PyInstaller bootstrap entry point ^[manual_analysis]

Interesting Tidbits

  1. Weak AES key1qazxsw23edcvfrN is a left-hand QWERTY zig-zag (1qaz, xsw2, 3edc, vfr) plus a trailing N. Any analyst who recovers the key from this sample can decrypt all other payloads built with the same key by the same actor. ^[manual_analysis]
  2. Author opsec failure — The build path F:\files\ftp\crack\exe\build\ftpcrack\ exposes the project name ftpcrack, suggesting this actor either masquerades as an FTP cracker tool or uses that as a working directory name. The exe\build\ftpcrack subdirectory structure matches PyInstaller's default --onefile build output. ^[manual_analysis]
  3. Python 2.7 runtime — Loader paths reference C:\Python27\Lib\site-packages\PyInstaller\loader\, placing the build in the Python 2.x / PyInstaller 3.x era (consistent with Sep 2018). ^[manual_analysis]
  4. pyinstxtractor failure — Both classic and ng extractors failed because they read the CArchive cookie from the first MEI magic occurrence (at 0x1f330, inside a decompressed entry name) rather than the actual cookie near the end of the file. This is a known limitation when the overlay contains the string MEI by chance. Manual zlib-decompression of the overlay was required. ^[manual_analysis]
  5. floss.txt was a tool mis-invocation — the triage script passed the binary path to --no instead of the sample positional argument. ^[floss.txt]
  6. capa.txt failed — default signature path missing on station. ^[capa.txt]
  7. No YARA matches beyond generic PE — confirms no known mining-family signatures cover the outer bootloader shell. ^[triage.json]

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: strings on the output EXE should show pyimod00_crypto_key.pyt. The overlay zlib chunks will decompress to AES key modules rather than plaintext Python.
  • Decrypt: Patch pyi-archive_viewer to use the recovered key, or modify PyInstaller's archive.py to skip the decryption loop and dump decrypted entries.
  • Learning outcome: Understanding the --key option means analysts cannot rely on simple zlib decompression; extraction requires the AES key or a runtime detonation with process-memory dumps.

Deployable Signatures

YARA rule

rule PyInstallerBootloader_AESCoinminer_2018 {
    meta:
        description = "PyInstaller single-file bootloader with AES-encrypted coinminer payload (2018 cluster, weak QWERTY key)"
        author = "Titus"
        date = "2026-06-06"
        sha256 = "359fcf01a54b89eabcbfcecd734e2af60b6bfa19ffd7fcdd87b1e4ed15db599c"
    strings:
        $pyi1 = "pyimod00_crypto_key" ascii wide
        $pyi2 = "PyInstaller: FormatMessageW failed." ascii wide
        $pyi3 = "_MEIPASS2" ascii wide
        $pyi4 = "Failed to execute script %s" ascii wide
        $pyi5 = "pyi-runtime-tmpdir" ascii wide
        $inflate = "inflate 1.2.8 Copyright 1995-2013 Mark Adler" ascii wide
    condition:
        uint16(0) == 0x5a4d and
        $pyi1 and
        3 of ($pyi2, $pyi3, $pyi4, $pyi5) and
        $inflate and
        filesize > 2MB
}

Sigma rule

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

IOC list

  • SHA-256: 359fcf01a54b89eabcbfcecd734e2af60b6bfa19ffd7fcdd87b1e4ed15db599c
  • Temp path pattern: %TEMP%\_MEI*\* (PyInstaller extraction directory)
  • AES key: 1qazxsw23edcvfrN (weak QWERTY pattern)
  • Build path artefact: F:\files\ftp\crack\exe\build\ftpcrack\pyimod00_crypto_key.pyt
  • 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 >4 MB zlib-compressed overlay encrypted with AES-CBC via PyInstaller's --key option. At runtime it extracts the decrypted payload to a _MEI-prefixed temp directory, loads python27.dll, and executes the 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.

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: 4b4cf3bd-e051-456f-baf7-b8f5674ebf92 ^[metadata.json]
  • OpenCTI labels: coinminer, exe, urlhaus ^[triage.json]
  • Cluster sibling: /intel/analyses/801fbba19b4d4828191e87e7311480deaf81e84482dab70adf38d61afd01c1fa.html
  • Cluster sibling: /intel/analyses/39b67a790b89fc8170703baaa98b29e1453a63416f0320bb3ae0f2936306f184.html
  • Cluster sibling: /intel/analyses/5047235c1d599c8a4e39a073c8c71e6ac6579da3f03606f51cae9b17fe971858.html
  • Cluster sibling: /intel/analyses/640ed5b536824541112a8b54488353d2938b4d0368a3ed14d41efff1d841c346.html
  • Entity page: coinminer
  • Concept page: python-packed-payload

Provenance

  • file.txtfile command (PE32 executable)
  • strings.txt — strings (8,402 lines)
  • pefile.txtpefile Python module (sections, imports, resources)
  • binwalk.txtbinwalk (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 decompression, PyInstaller CArchive structure inspection, AES key extraction
  • R2 decompilation — radare2 via MCP (pdg at entry0)