af7aebb9817900fca79fc4d193f61b7f1c7550cf4cdd8bd6beed53f0ba023043coinminer: 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:
- CRT initialisation — MSVC
entry0→main()→ PyInstaller bootstrap core ^[r2:entry0] - Archive resolution — locates the CFFI archive appended past the PE sections (overlay at
0x3CE00) ^[binwalk.txt] - Extraction — decompresses 85 zlib blocks and decrypts AES-encrypted entries to
%TEMP%\_MEI<XXXX>^[manual_overlay_analysis] - Python runtime bootstrap — loads the Python DLL, resolves CPython API procs (
Py_Initialize,PyMarshal_ReadObjectFromString, etc.) ^[strings.txt:119-212] - Script execution — unmarshals the embedded code object and runs
__main__.py^[strings.txt:104-111] - Cleanup — deletes the temp directory on exit unless
_MEIPASS2is 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, thenmain(). No anti-debug or VM checks. ^[r2:entry0]main(0x00401000): Three calls — archive status resolution, UTF-8 argv conversion, thenfcn.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] .rsrcsection 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
- 85 zlib blocks — the highest block count in the cluster (previous record was
6b2591e40fbbwith 285). This suggests a denser or more fragmented embedded Python runtime / payload structure. ^[binwalk.txt] - No appended PE — unlike sibling
5047235c, there is no secondary PE executable appended at the end of the overlay. ^[manual_overlay_analysis] floss.txtandcapa.txtfailures — same recurring tool issues as the rest of the cluster: floss received a bad argument, capa lacks signatures. ^[floss.txt] ^[capa.txt]- No YARA matches beyond generic PE — confirms no known mining-family signatures cover the outer bootloader shell. ^[triage.json]
- 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.
stringsshould show_MEIPASS,PyInstaller, andinflate 1.2.8. - Decrypt: Recover the AES key from a known sibling (
359fcf01), patchpyi-archive_viewerto use it, and dump the decrypted entries. - Learning outcome: Recognising that high-entropy overlays in PyInstaller binaries indicate
--keyencryption, 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
_MEIpath - 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—filecommand (PE32 executable)strings.txt— strings (4,287 lines)pefile.txt—pefilePython module (sections, imports, resources)binwalk.txt—binwalk(embedded artefacts / zlib blocks)rabin2-info.txt— radare2rabin2 -I(binary metadata)exiftool.json— ExifTool PE metadatatriage.json— triage tier assignmentmetadata.json— artifact metadata from OpenCTIfloss.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 (
pdgatentry0,main)