5047235c1d599c8a4e39a073c8c71e6ac6579da3f03606f51cae9b17fe971858coinminer: 5047235c — PyInstaller bootloader sibling with appended sub-PE, 1.8 MB overlay
Executive Summary
PyInstaller-packed PE32 dropper from the Sep 2018 MSVC 14.0 bootloader cluster (see siblings /intel/analyses/801fbba19b4d4828191e87e7311480deaf81e84482dab70adf38d61afd01c1fa.html and /intel/analyses/39b67a790b89fc8170703baaa98b29e1453a63416f0320bb3ae0f2936306f184.html). The 1.8 MB file embeds a large zlib-compressed overlay typical of PyInstaller, but also carries a secondary valid PE32 at raw offset 0x173c00 (303 KB) with the identical compilation stamp and linker version. This sample is static-only: CAPE skipped because no Windows guest is available.
What It Is
- File: PE32 executable (GUI) Intel 80386, 6 sections ^[file.txt]
- Size: 1,826,593 bytes (1.75 MB) ^[rabin2-info.txt]
- Linker: MSVC 14.0 (Visual Studio 2015 RTM). Compiled Tue Sep 4 14:43:33 2018 UTC — same second as siblings 801fbba1 and 39b67a79 ^[pefile.txt:34] ^[rabin2-info.txt]
- SSDeep:
49152:R3XTWsOBDNQ2iselXOfTITJR0nr43XTWsTd:RLGSThOfTC/LR— shares the commonR3XTWsOBDNQ2iselXOfTITJR0nprefix with sibling 39b67a79 ^[triage.json] - Signed: false; header checksum
0x00000000^[rabin2-info.txt] - ASLR / DEP: enabled (
DllCharacteristics: 0x8140) ^[pefile.txt:74] - Subsystem: Windows GUI
- Overlay: starts at raw offset
0x3CE00(249,344) and continues to EOF; binwalk identifies numerous zlib blocks and a second PE32 at offset0x173c00(1,523,200) ^[binwalk.txt]
How It Works
Outer binary is a standard PyInstaller single-file C bootloader circa 2018 ^[strings.txt:105-250].
- Extraction — Decompresses the CFFI archive from the overlay to a temporary directory (
%TEMP%\_MEI<XXXX>) using zlib/inflate 1.2.8 ^[strings.txt:79-84] ^[binwalk.txt] - Python bootstrap — Loads an embedded
python<ver>.dll, resolves CPython C-API functions viaGetProcAddress, and executes the marshalled__main__.pybytecode ^[strings.txt:119-212] - Cleanup — Removes the
_MEIdirectory on exit unless_MEIPASS2env var is set ^[strings.txt:115]
Unique to this sample:
At raw offset 0x173c00 (1,523,200) there is a complete secondary PE32 (303,905 bytes) with the exact same linker version, timestamp, and section layout as the outer file ^[binwalk.txt:31]. Its strings set is a strict subset of the outer file's — it contains the same PyInstaller error strings but terminates early, suggesting it is either an embedded drop-stage or a build artifact from the same build pipeline. The secondary PE has no .rsrc icon group beyond the same PNG, no additional imports, and no observable C2 strings.
Because pyinstxtractor-ng and pyi-archive_viewer both fail to parse a valid TOC (likely due to the appended sub-PE disrupting the CArchive cookie alignment at the file tail), extracting the embedded Python payload requires manual carving or trimming the trailing 304 KB before applying PyInstaller unpacking tools.
Decompiled Behaviour
Static decompilation yields the same MSVC CRT entry → PyInstaller bootstrap chain observed in sibling 801fbba1:
entry0(0x004079d3): CRT initialisation, thenmain()^[r2:entry0]main(0x00401000): Archive status resolution, UTF-8 argument conversion, thenfcn.00402520(PyInstaller bootstrap core) ^[r2:main]
No anti-debug, no VM detection, no API hashing.
C2 Infrastructure
Not statically observable. The outer binary contains only generic PyInstaller and MSVC CRT strings. Pool URLs, wallet addresses, and miner configuration are assumed to live inside the compressed Python payload in the overlay, which remains unextracted.
Interesting Tidbits
- The
c:/PyIfragment at line 1090 ofstrings.txtsuggests the same build environment as sibling 801fbba1 (c:/PyIor PyInstaller source tree). ^[strings.txt:1090] - Binwalk reports 14 zlib blocks plus the secondary PE. The overlay region (0x3CE00–0x173c00, ~1.15 MB) is the likely CFFI archive. ^[binwalk.txt]
- No capa output because signatures are missing on the station. ^[capa.txt]
- FLOSS failed with a CLI argument error. ^[floss.txt]
- The secondary PE is not UPX-packed, not signed, and has entropy values matching the outer file's sections. It is effectively a truncated clone.
How To Mess With It (Homelab Replication)
Follow the same recipe as /intel/analyses/801fbba19b4d4828191e87e7311480deaf81e84482dab70adf38d61afd01c1fa.html:
- Install PyInstaller 3.4 on a Windows VM with Python 2.7/3.6.
pyinstaller --onefile --windowed --name=miner_stub your_script.py- Build artifacts: same MSVC 14.0 linker, zlib overlay,
_MEIPASSstrings. - To reproduce the secondary-PE append quirk (if desired), concatenate the built EXE to itself:
copy /b stub.exe + stub.exe doubled.exe
Deployable Signatures
YARA rule
rule PyInstallerBootloader_Coinminer_2018_Cluster {
meta:
description = "PyInstaller single-file bootloader (2018 MSVC 14.0 cluster) with embedded Python coinminer payload"
author = "Titus"
date = "2026-06-02"
sha256 = "5047235c1d599c8a4e39a073c8c71e6ac6579da3f03606f51cae9b17fe971858"
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
$mz = "MZ" ascii wide
condition:
uint16(0) == 0x5a4d and
4 of ($pyi*) and
$inflate and
filesize > 500KB and
filesize < 5MB
}
Sigma rule
title: PyInstaller Coinminer Extraction Detected
logsource:
product: windows
category: process_creation
detection:
selection:
Image|startswith:
- '%TEMP%\_MEI'
ParentImage|endswith:
- '.exe'
condition: selection
falsepositives:
- Legitimate PyInstaller applications
level: medium
IOC list
- SHA-256:
5047235c1d599c8a4e39a073c8c71e6ac6579da3f03606f51cae9b17fe971858 - Temp path pattern:
%TEMP%\_MEI*\* - Secondary embedded PE: begins at raw offset
0x173c00(same timestamp as outer)
Behavioural fingerprint
PE32 GUI executable compiled with MSVC 14.0 in Sep 2018. Contains a zlib-compressed overlay with PyInstaller CFFI archive signatures. At runtime extracts to a _MEI-prefixed temp directory, loads python*.dll, and executes embedded marshalled Python bytecode. Threat behaviour manifests in child processes spawned from the _MEI directory. No suspicious imports in the parent process itself.
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
- Capa: non-functional (missing signatures). No ATT&CK mapping available.
References
- Artifact ID:
db279cab-a35e-43c0-b7dc-d83c8f83b585^[metadata.json] - OpenCTI labels:
coinminer,exe,urlhaus^[metadata.json] - Related wiki: coinminer
- Siblings:
- /intel/analyses/801fbba19b4d4828191e87e7311480deaf81e84482dab70adf38d61afd01c1fa.html — first sibling (800 KB)
- /intel/analyses/39b67a790b89fc8170703baaa98b29e1453a63416f0320bb3ae0f2936306f184.html — second sibling (4.3 MB)
Provenance
file.txt—filecommand (PE32 executable)strings.txt— strings (3917 lines, truncated output)pefile.txt—pefilePython module (sections, imports, resources)rabin2-info.txt— radare2rabin2 -I(binary metadata)binwalk.txt—binwalk(embedded artifacts / zlib blocks, secondary PE)exiftool.json— ExifTool PE metadatametadata.json— artifact metadata from OpenCTItriage.json— triage tier assignment- R2 decompilation — radare2 via MCP (
entry0,main, standard PyInstaller bootstrap chain)