39b67a790b89fc8170703baaa98b29e1453a63416f0320bb3ae0f2936306f184coinminer: 39b67a79 — PyInstaller bootloader sibling, 4.3 MB with 94% zlib overlay
Executive Summary
Cluster sibling of the 801fbba1 PyInstaller coinminer dropper. Same MSVC 2015 toolchain, same compilation second (Sep 4 2018 14:43:33 UTC), same bootloader, but with a 3.8 MB zlib-compressed overlay — roughly seven times larger than its sibling. The outer binary is pure PyInstaller infrastructure; the coinminer logic, pool configuration, and likely an entire Python runtime live inside the compressed CFFI archive. No mining indicators are visible without overlay extraction.
What It Is
- File: PE32 executable (GUI) Intel 80386, 6 sections ^[file.txt]
- Size: 4,259,320 bytes (4.06 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). Rich header shows
Utc1810_CPP(40116) x172,Utc1900_C x17,Utc1900_CPP x29,Masm1400 x18— nearly identical fingerprint to 801fbba1 ^[rabin2-info.txt] - Signed: false; checksum
0x00000000^[rabin2-info.txt] - ASLR / DEP: enabled (
DllCharacteristics: 0x8140) ^[pefile.txt:74] - Subsystem: Windows GUI ^[file.txt]
- Overlay: 3,823,976 bytes (94.1% of file) starting at raw offset
0x3CE00, zlib-compressed PyInstaller CFFI archive ^[binwalk.txt]
How It Works
Standard PyInstaller single-file bootloader flow ^[ghidra:entry-004079d3] ^[ghidra:FUN_00401000-00401000] ^[ghidra:FUN_00402520-00402520]:
- CRT initialisation —
entry()calls__security_init_cookie()and__scrt_common_main_seh(), then reachesmain()^[ghidra:entry-004079d3] - Archive resolution —
main()callsFUN_004049d0to resolve the executable path, then hands control toFUN_00402520^[ghidra:FUN_00401000-00401000] - Extraction —
FUN_00402520allocates anARCHIVE_STATUSstruct (0x4078 bytes), checks_MEIPASS2, locates the CFFI archive appended past the PE sections, and decompresses it to%TEMP%\_MEI<XXXX>^[ghidra:FUN_00402520-00402520] ^[strings.txt:115] ^[strings.txt:235] - Python runtime bootstrap — loads
python*.dllviaLoadLibraryExW, resolves CPython API procs (Py_Initialize,PyMarshal_ReadObjectFromString,PyEval_EvalCode, etc.) ^[strings.txt:119-212] - Script execution — unmarshals the embedded Python code object and runs
__main__.py^[strings.txt:104-111] - Cleanup — deletes the temp directory on exit unless
_MEIPASS2is set ^[strings.txt:115]
The 3.8 MB overlay suggests the embedded payload is not just a miner script but likely a bundled Python interpreter plus dependencies (e.g., base_library.zip, compiled .pyc modules). Mining pool URLs, wallet addresses, and stratum configuration are compressed inside this archive and not statically recoverable from the PE sections.
Decompiled Behaviour
entry(0x004079d3): MSVC CRT entry point. Sets up security cookie and SEH, then callsmain(). ^[ghidra:entry-004079d3]FUN_00401000(main): Fetches the archive status struct and argv via helper functions, then callsFUN_00402520with the resolved paths. ^[ghidra:FUN_00401000-00401000]FUN_00402520(PyInstaller bootstrap core): AllocatesARCHIVE_STATUS, checks_MEIPASS2env var, opens self as archive, iterates TOC entries, extracts files to temp, callsSetDllDirectoryWto the_MEIfolder, then launches the Python VM. ^[ghidra:FUN_00402520-00402520]
No anti-debug checks, no VM detection, no API hashing — behaviour is entirely that of a stock PyInstaller bootloader circa 2018.
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 present in the PE sections or imports. Pool/C2 configuration is assumed to reside inside the compressed Python payload in the overlay. ^[strings.txt]
Interesting Tidbits
floss.txtis a tool-usage error (the triage script passed the sample path to--noinstead ofsample), yielding no decoded strings. ^[floss.txt]capa.txtfailed with missing default signature path — signatures were never installed on this station. ^[capa.txt]binwalk.txtidentified 40+ zlib-compressed blocks and a PNG icon in.rsrc, confirming the overlay is a multi-member CFFI archive. ^[binwalk.txt]- The
.rsrcsection contains 7 icon groups (typical of PyInstaller default Python icon inheritance). ^[pefile.txt:159-492] - Identical compilation timestamp to 801fbba1 (down to the second) and nearly identical Rich header strongly suggests both binaries were produced by the same build pipeline or builder on the same machine. ^[pefile.txt:34] ^[rabin2-info.txt]
- The
c:/PyIpartial path fragment at line 1090 of strings.txt hints the build environment had aPyIdirectory (PyInstaller source). ^[strings.txt:1090] - Overlay ratio of 94.1% makes this one of the largest PyInstaller coinminers observed in the corpus; the bulk of the file is compressed payload, not executable code.
How To Mess With It (Homelab Replication)
- Toolchain: Install PyInstaller (
pip install pyinstaller==3.4for 2018-era behaviour) on a Windows research VM with Python 2.7 or 3.6. - Build a onefile payload:
pyinstaller --onefile --windowed --name=miner_stub your_script.py - Extraction test: Run the stub, then inspect
%TEMP%for a_MEIfolder. Or usepyinstxtractor.pyagainst the built EXE to dump the embedded archive. - Verification:
stringson the output EXE should show_MEIPASS,PyInstaller,Py_Initialize, and zlib blocks in the overlay. Compare entropy and section layout to this sample. - Learning outcome: Recognising that the outer binary is benign infrastructure and the actual threat lives in the overlay prevents triage teams from stopping analysis after a benign-looking import table. The size delta between siblings (800 KB vs 4.3 MB) is a useful heuristic for payload richness.
Deployable Signatures
YARA rule
rule PyInstallerBootloader_LargeOverlay_Coinminer {
meta:
description = "PyInstaller single-file bootloader with oversized zlib-compressed overlay (coinminer sibling)"
author = "Titus"
date = "2026-05-26"
sha256 = "39b67a790b89fc8170703baaa98b29e1453a63416f0320bb3ae0f2936306f184"
strings:
$pyi1 = "PyInstaller: FormatMessageW failed." ascii wide
$pyi2 = "_MEIPASS2" ascii wide
$pyi3 = "pyi-runtime-tmpdir" ascii wide
$pyi4 = "Installing PYZ: Could not get sys.path" ascii wide
$pyi5 = "Failed to execute script %s" ascii wide
$pyi6 = "base_library.zip" ascii wide
$inflate = "inflate 1.2.8 Copyright 1995-2013 Mark Adler" ascii wide
condition:
uint16(0) == 0x5a4d and
4 of ($pyi*) and
$inflate and
filesize > 3MB
}
Sigma rule
Not suitable — the outer binary exhibits no unique process-level behaviour beyond generic PyInstaller extraction. Sigma should target the child process: python.exe or renamed miner executable spawned from %TEMP%\_MEI* within seconds of parent launch.
IOC list
- SHA-256:
39b67a790b89fc8170703baaa98b29e1453a63416f0320bb3ae0f2936306f184 - Temp path pattern:
%TEMP%\_MEI*\*(PyInstaller extraction directory) - Mutex / named pipe: not observed in outer binary
- Registry: not observed in outer binary
- Compilation timestamp:
2018-09-04 14:43:33 UTC(cluster indicator)
Behavioural fingerprint
PE32 GUI executable compiled with MSVC 2015, containing a >3.8 MB zlib-compressed overlay (94% of file size). At runtime extracts its payload to a _MEI-prefixed temp directory, loads python*.dll from that directory, and executes embedded marshalled Python bytecode. No suspicious imports in the parent process; threat behaviour manifests in spawned Python/miner child processes. Sibling of 801fbba1 by build fingerprint.
Detection Signatures
- MITRE ATT&CK
- T1059.003 (Windows Command Shell) — possible batch/powershell launcher in embedded payload; not confirmed statically
- 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
- Capa: non-functional (missing signatures). No ATT&CK mapping available.
References
- Artifact ID:
0141549b-5e24-4f8e-bbc5-f1b8dbd6da77^[metadata.json] - OpenCTI labels:
coinminer,exe,urlhaus^[metadata.json] - Cluster sibling: /intel/analyses/801fbba19b4d4828191e87e7311480deaf81e84482dab70adf38d61afd01c1fa.html
- Related wiki: coinminer
- Related concept: pyinstaller-bootloader
- Related technique: python-packed-payload
Provenance
file.txt—filecommand (PE32 executable)strings.txt—strings(7822 lines)rabin2-info.txt— radare2rabin2 -I(binary metadata + rich header)pefile.txt—pefilePython module (sections, imports, resources)binwalk.txt—binwalk(embedded artifacts / zlib blocks)exiftool.json— ExifTool PE metadatafloss.txt— flare-floss (tool argument error, no decoded output)capa.txt— flare-capa (signature path error, no output)triage.json— triage tier assignmentmetadata.json— artifact metadata from OpenCTIdynamic-analysis.md— CAPE status (skipped, no Windows guest)- Ghidra decompilation — pyghidra MCP (
entry,FUN_00401000,FUN_00402520) - radare2 decompilation — radare2 MCP (
entry0,main,fcn.00402520)