801fbba19b4d4828191e87e7311480deaf81e84482dab70adf38d61afd01c1facoinminer: 801fbba1 — PyInstaller bootloader, Sep 2018 MSVC build, embedded Python payload
Executive Summary
PyInstaller-packaged PE32 dropper (compiled Sep 2018 with MSVC 14.0). The outer binary is a stock PyInstaller C bootloader that extracts a ~560 KB CFFI archive to a _MEI temp directory, loads an embedded Python DLL, and executes the marshalled Python payload. No mining pool strings are visible in the outer binary; actual coinminer logic lives inside the compressed overlay. Static triage tooling (floss, capa) were non-functional during analysis due to argument error and missing signatures, respectively.
What It Is
- File: PE32 executable (GUI) Intel 80386, 6 sections ^[file.txt]
- Size: 819,100 bytes (799.9 KB) ^[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
Utc1900_C(24210) x17,Utc1900_CPP(24123) x29,Utc1810_CPP(40116) x172,Masm1210(40116) x12^[rabin2-info.txt] - Signed: false; checksum
0x00000000^[rabin2-info.txt] - ASLR / DEP: enabled (
DllCharacteristics: 0x8140= DYNAMIC_BASE | NX_COMPAT | TERMINAL_SERVER_AWARE) ^[pefile.txt:74] - Subsystem: Windows GUI ^[file.txt]
- Overlay: 569,756 bytes starting at raw offset
0x3CE00, zlib-compressed PyInstaller CFFI archive ^[binwalk.txt]
How It Works
The binary is a PyInstaller single-file bootloader that performs the following at runtime ^[r2:entry0] ^[r2:fcn.00402520] ^[r2:fcn.00401bc0]:
- CRT initialisation — standard MSVC
entry0→main()→ PyInstaller bootstrap ^[r2:entry0] - Archive resolution — locates the CFFI archive appended past the PE sections (overlay at
0x3CE00, size ~570 KB) ^[binwalk.txt] - Extraction — decompresses the archive to
%TEMP%\_MEI<XXXX>using zlib/inflate 1.2.8 ^[strings.txt:79-84] ^[binwalk.txt] - Python runtime bootstrap — loads
python<ver>.dllviaLoadLibrary, 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
_MEIPASS2env var is set (used for debugging) ^[strings.txt:115]
The overlay contains the actual coinminer payload. Because it is zlib-stream compressed and structurally a PyInstaller CFFI archive, mining pool URLs, wallet addresses, or miner parameters are not observable without extracting and decompiling the embedded .pyc files.
Decompiled Behaviour
entry0(0x004079d3): MSVC CRT entry. Calls initialisers, thenmain(0, NULL, NULL)^[r2:entry0]main(0x00401000): Three calls: (1) resolve archive status struct, (2) convert argv/envp to UTF-8 viaWideCharToMultiByte/MultiByteToWideChar, (3) callfcn.00402520(PyInstaller bootstrap core) ^[r2:main]fcn.00402520: AllocatesARCHIVE_STATUSstruct; checks_MEIPASS2; builds extraction path underGetTempPathW; callsfcn.00402110to iterate TOC entries and extract files; callsSetDllDirectoryWto the_MEIfolder; then launches the Python interpreter with the unmarshalled script. ^[r2:fcn.00402520]fcn.00401bc0: TOC walker. Formats nested paths via%s%s%s%s%sand%s%s%s%s%s%s%s; opens.pkgand.exemembers; copies out bytes viafwrite. ^[r2:fcn.00401bc0]
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 15 zlib-compressed blocks and a PNG icon in.rsrc, confirming the overlay is a multi-member archive. ^[binwalk.txt]- The
.rsrcsection contains 7 icon groups (typical of PyInstaller inheriting default Python icons). ^[pefile.txt:159-492] - Rich header heavy use of
Utc1810_CPP(40116)(172 counts) withLinker1400suggests the CRT static library was built with VS 2013 toolset while the final link used VS 2015 — common in PyInstaller's own build pipeline. ^[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] - There are no suspicious imports in the PE: imports are entirely standard Win32 + Python CRT APIs. Threat activity will manifest in child processes spawned from
%TEMP%\_MEI*. ^[pefile.txt:249-363]
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.
Deployable Signatures
YARA rule
rule PyInstallerBootloader_Coinminer_2018 {
meta:
description = "PyInstaller single-file bootloader with embedded coinminer payload (2018-era)"
author = "Titus"
date = "2026-05-26"
sha256 = "801fbba19b4d4828191e87e7311480deaf81e84482dab70adf38d61afd01c1fa"
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 > 500KB
}
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:
801fbba19b4d4828191e87e7311480deaf81e84482dab70adf38d61afd01c1fa - Temp path pattern:
%TEMP%\_MEI*\*(PyInstaller extraction directory) - 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 ~560 KB zlib-compressed overlay. 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.
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:
c913803e-06c0-4d30-8309-64af3b5daaf0^[metadata.json] - OpenCTI labels:
coinminer,exe,urlhaus^[metadata.json] - PyInstaller bootloader source: https://github.com/pyinstaller/pyinstaller/blob/develop/bootloader/src/pyi_main.c
- Related wiki: coinminer
Provenance
file.txt—filecommand (PE32 executable)strings.txt— strings (1795 lines, truncated output)rabin2-info.txt— radare2rabin2 -I(binary metadata)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 OpenCTI- R2 decompilation — radare2 via MCP (
pdgatentry0,main,fcn.00402520,fcn.00401bc0)