typeanalysisfamilycoinminerconfidencemediumcreated2026-08-01updated2026-08-01compilerpemalware-familycryptominerdefense-evasionpython-pyinstaller
SHA-256: 1fed143e0f95ce0e7e6070d89745c74b6a086df0387a2e091720be20a27774b4

coinminer: 1fed143e — PyInstaller bootloader sibling, 4.14 MB plain-zlib overlay, Sep 2018 cluster

Executive Summary

Large PyInstaller single-file PE32 from the Sep 2018 MSVC 14.0 coinminer cluster. At 4.14 MB it is the second-largest plain-zlib sibling observed in this corpus (surpassed only by the 6.1 MB f284c9aa). Same compilation timestamp and bootloader as sixteen confirmed cluster siblings; no AES encryption layer (no pyimod00_crypto_key.pyc recovered), no appended secondary PE, and no ftpcrack.py misattribution. The ~3.87 MB overlay contains the actual coinminer payload in zlib-compressed Python bytecode, not recoverable without extraction. Static-only — CAPE skipped for lack of a Windows guest.

What It Is

Field Value
SHA-256 1fed143e0f95ce0e7e6070d89745c74b6a086df0387a2e091720be20a27774b4
File type PE32 executable (GUI) Intel 80386, 6 sections ^[file.txt]
Size 4,342,176 bytes (4.14 MB) ^[triage.json]
Linker MSVC 14.0 (Visual Studio 2015 RTM) ^[exiftool.json] ^[pefile.txt:45-46]
PE timestamp Tue Sep 4 14:43:33 2018 UTC ^[rabin2-info.txt:11] ^[pefile.txt:34]
Signed No ^[rabin2-info.txt:27]
ASLR / DEP Enabled (DllCharacteristics: 0x8140) ^[pefile.txt:74]
Entry point 0x004079d3 (PyInstaller bootloader) ^[pefile.txt:50]
Overlay ~3.87 MB starting at raw offset 0x3CE00, zlib-compressed ^[binwalk.txt]
Sections .text, .rdata, .data, .gfids, .rsrc, .reloc ^[pefile.txt:78-196]

The outer binary is a stock PyInstaller C bootloader circa 2018. No mining pool URLs, wallet addresses, or Stratum protocol strings are visible in the PE sections or imports; the coinminer logic is assumed to live inside the compressed overlay.

How It Works

Standard PyInstaller single-file C bootloader flow, identical to siblings 801fbba1, 640ed5b5, and 39b67a79:

  1. CRT initialisation — entry0 at 0x004079d3 sets up security cookie and SEH, then calls main() ^[r2:entry0]
  2. Archive resolution — main at 0x00401000 resolves the executable path and hands control to the PyInstaller bootstrap core ^[r2:main]
  3. Extraction — Decompresses the CFFI archive from the overlay to %TEMP%\_MEI<XXXX> using zlib/inflate 1.2.8 ^[strings.txt:79] ^[binwalk.txt]
  4. Python runtime bootstrap — Loads embedded python*.dll, resolves CPython C-API functions (Py_Initialize, PyMarshal_ReadObjectFromString, PyEval_EvalCode, etc.) via GetProcAddress ^[strings.txt:119-212]
  5. Script execution — Unmarshals and runs the embedded __main__.py bytecode ^[strings.txt:104-111]
  6. Cleanup — Removes the _MEI temp directory on exit unless _MEIPASS2 env var is set ^[strings.txt:115]

Cluster fingerprinting:

  • Same compilation second as the entire cluster: 2018-09-04 14:43:33 UTC ^[rabin2-info.txt:11]
  • No pyimod00_crypto_key.pyc or hardcoded AES key 1qazxsw23edcvfrN found in overlay (unlike AES-encrypted siblings 359fcf01, 058ab625, 983d2606, etc.)
  • No appended secondary PE (unlike sibling 5047235c)
  • No ftpcrack.py payload (unlike mislabelled sibling 551d2b0e)
  • Plain zlib compression: 44 zlib blocks identified by binwalk ^[binwalk.txt]

Decompiled Behavior

  • entry0 (0x004079d3): MSVC CRT entry, 103 instructions, 21 basic blocks, cyclomatic complexity 11. Sets up SEH chain and security cookie, then jumps to main(). ^[r2:entry0]
  • main (0x00401000): Archive status resolution via GetModuleFileNameW, UTF-8 conversion of argv/envp via WideCharToMultiByte, then calls the PyInstaller bootstrap. ^[r2:main]
  • Import surface is entirely benign Win32 + Python CRT APIs: KERNEL32.dll (file ops, process creation, environment), USER32.dll (MessageBoxA/W), WS2_32.dll (ntohl only — used by the bootloader, not direct C2). ^[r2:imports]

No anti-debug checks, no VM detection, no API hashing, no sandbox evasion — pure stock PyInstaller behaviour.

C2 Infrastructure

Not statically observable. The outer binary contains only generic PyInstaller and MSVC CRT strings. Mining pool URLs, wallet addresses, and Stratum configuration are assumed to reside inside the zlib-compressed Python payload in the overlay. No hardcoded IPs, domains, or mutex names were recovered. ^[strings.txt]

Interesting Tidbits

  • floss.txt is a tool-usage error (triage script passed sample path to --no instead of positional arg), yielding no decoded strings. ^[floss.txt]
  • capa.txt failed with missing default signature path — signatures not installed on this station. ^[capa.txt]
  • binwalk.txt identifies 44 zlib-compressed blocks in the overlay plus a PNG icon (256×256) in .rsrc — standard PyInstaller default icon inheritance. ^[binwalk.txt]
  • Overlay entropy is ~7.999 (near-random), confirming compressed/encrypted payload. No base_library.zip or struct.pyc strings recovered from overlay without decompression.
  • The .rsrc section contains standard PyInstaller icon groups; no custom version info masquerade. ^[pefile.txt:159-492]
  • This sample's size (4.14 MB) places it between the 4.07 MB sibling fa98331d and the 5.34 MB sibling 6b2591e4 in the cluster size distribution, suggesting the same build pipeline with variable payload sizes.

How To Mess With It (Homelab Replication)

Follow the recipe at pyinstaller-bootloader and python-packed-payload:

  1. Install PyInstaller 3.4 on a Windows research VM with Python 2.7 or 3.6.
  2. pyinstaller --onefile --windowed --name=miner_stub your_script.py
  3. The resulting EXE will match this cluster's MSVC 14.0 linker fingerprint, _MEIPASS strings, and zlib overlay structure.
  4. Extract the embedded payload with pyinstxtractor.py (or pyinstxtractor-ng for Python 3.x archives) to inspect .pyc modules and mining configuration.
  5. Verification: strings on the output EXE should show _MEIPASS2, PyInstaller, Py_Initialize, and zlib blocks in the overlay. Compare entropy and section layout to this sample.
  6. 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_1fed143e {
    meta:
        description = "PyInstaller single-file bootloader (2018 MSVC 14.0 cluster) with large plain-zlib embedded coinminer payload"
        author = "Titus"
        date = "2026-08-01"
        sha256 = "1fed143e0f95ce0e7e6070d89745c74b6a086df0387a2e091720be20a27774b4"
    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 and
        filesize < 7MB
}

Sigma rule

title: PyInstaller Coinminer Child Process Spawned from _MEI Temp Directory
logsource:
    product: windows
    category: process_creation
detection:
    selection:
        Image|startswith:
            - '%TEMP%\_MEI'
        ParentImage|endswith:
            - '.exe'
    condition: selection
falsepositives:
    - Legitimate PyInstaller-built applications
level: medium

IOC list

  • SHA-256: 1fed143e0f95ce0e7e6070d89745c74b6a086df0387a2e091720be20a27774b4
  • Temp path pattern: %TEMP%\_MEI*\* (PyInstaller extraction directory)
  • Compilation timestamp: 2018-09-04 14:43:33 UTC (cluster indicator shared with siblings)

Behavioral fingerprint

PE32 GUI executable compiled with MSVC 2015, containing a ~3.87 MB zlib-compressed overlay (93% 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. Same build fingerprint as confirmed coinminer siblings 801fbba1, 39b67a79, 5047235c, 640ed5b5, and others.

Detection Signatures

  • MITRE ATT&CK
    • T1059.006 (Python) — execution via embedded Python interpreter
    • T1074.001 (Data Staged: Local Data Staging) — extraction to temp directory
    • T1055 (Process Injection) — possible process hollowing or injection by the embedded Python payload; not confirmed statically

References

Provenance

Analysis derived from:

  • file.txt — file(1) type identification
  • pefile.txt — PE structure and section analysis via pefile (Python)
  • rabin2-info.txt — radare2 binary header summary
  • strings.txt — ASCII string extraction via GNU strings
  • binwalk.txt — embedded artefact identification via binwalk
  • exiftool.json — EXIF/metadata extraction via ExifTool
  • dynamic-analysis.md — CAPE sandbox status (skipped)
  • triage.json — triage pipeline metadata
  • r2:entry0, r2:main, r2:imports — radare2 static disassembly and import analysis
  • floss.txt, capa.txt — non-functional during analysis (tool errors)

Overlay byte-level analysis performed with custom Python scripts; no mining pool URLs, wallet addresses, or ftpcrack.py strings were recovered from the outer PE or overlay without decompression.