typeanalysisfamilycoinminerconfidencemediumcreated2026-06-08updated2026-06-08compilerpemalware-familycryptominerdefense-evasionpython-pyinstaller
SHA-256: b4cc27e365f44dd18593d7ca2b4a2d9df95268079beff47940f48cce21bfc979

coinminer: b4cc27e3 — Smallest PyInstaller bootloader sibling, 630 KB, Python 2.7 payload

Executive Summary

PyInstaller single-file PE32 bootloader (MSVC 14.0, compiled Sep 4 2018 14:43:33 UTC) — the smallest observed sibling in the cluster at 630,707 bytes. The ~381 KB zlib-compressed overlay (60.5% of file) contains a Python 2.7 payload (python27.dll, libgcc_s_dw2-1.dll) rather than the Python 3.x runtime seen in the larger siblings. No mining pool URLs or wallet addresses are visible in the outer binary; actual coinminer logic lives inside the compressed overlay. CAPE skipped (no Windows guest).

What It Is

  • File: PE32 executable (GUI) Intel 80386, 6 sections ^[file.txt]
  • Size: 630,707 bytes (616 KB) — smallest sibling in the cluster ^[rabin2-info.txt]
  • Compiled: Tue Sep 4 14:43:33 2018 UTC — identical timestamp to siblings 801fbba1, 39b67a79, 5047235c, 640ed5b5, 359fcf01 ^[pefile.txt:34] ^[rabin2-info.txt]
  • Linker: MSVC 14.0 (Visual Studio 2015 RTM). Rich header not extracted in this triage run, but linker version and timestamp match the documented cluster. ^[pefile.txt:44-45] ^[exiftool.json]
  • 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: 381,363 bytes starting at raw offset 0x3CE00, zlib-compressed PyInstaller CFFI archive ^[binwalk.txt]
  • Overlay ratio: 60.5% of total file size — lower than 39b67a79 (94%) but larger proportionally than 640ed5b5 (see delta notes). ^[binwalk.txt]

How It Works

Same stock PyInstaller single-file bootstrap as the rest of the cluster ^[r2:entry0]:

  1. CRT initialisation — MSVC entry0 (0x004079d3) → main() → PyInstaller bootstrap ^[r2:entry0]
  2. Archive resolution — reads the appended CFFI archive from the PE overlay (0x3CE00) ^[binwalk.txt]
  3. Extraction — inflates zlib streams and writes to %TEMP%\_MEI<XXXX> ^[strings.txt:79-84] ^[binwalk.txt]
  4. Python runtime bootstrap — loads python27.dll and resolves CPython API (Py_Initialize, PyMarshal_ReadObjectFromString, etc.) ^[strings.txt:119-212]
  5. Script execution — unmarshals embedded .pyc and runs __main__.py ^[strings.txt:104-111]
  6. Cleanup — deletes temp directory on exit unless _MEIPASS2 environment variable is set. ^[strings.txt:115]

The overlay contains the actual coinminer payload. Mining pool URLs and wallet addresses are expected inside the compressed Python archive, not observable statically.

Decompiled Behaviour

  • entry0 (0x004079d3): Standard MSVC CRT entry stub. Sets up exception filters, TLS, and calls main(). No anti-debug or VM checks. ^[r2:entry0]
  • main (0x00401000): Calls the PyInstaller bootstrap core. Identical control flow to sibling 801fbba1. ^[r2:entry0]
  • No notable functions beyond standard PyInstaller C runtime bootstrap. The decompiler shows only CRT boilerplate (fcn.00408270, fcn.00407d1f, etc.) with no custom threat logic in the outer binary. ^[r2:entry0]

C2 Infrastructure

Not statically observable. No hardcoded IPs, domains, pool URLs, or wallet addresses in the PE sections or imports. Pool configuration lives inside the compressed Python payload. ^[strings.txt]

Interesting Tidbits

  • Python 2.7 build environment: Strings reference python27.dll, libgcc_s_dw2-1.dll, and a MinGW runtime path (C:/ming730/i686-730-posix-dwarf-rt_v5-rev0/mingw32), indicating the embedded interpreter was compiled with MinGW-w64 for Python 2.7. ^[strings.txt]
  • Smallest cluster sibling: At 630 KB, this is ~105 KB smaller than 640ed5b5 (735 KB) and ~188 KB smaller than 801fbba1 (819 KB). The size delta is entirely in the overlay (smaller Python payload / fewer bundled libraries). ^[rabin2-info.txt]
  • floss.txt triage bug: The triage script passed the sample path to --no instead of sample, yielding no decoded strings. No FLOSS recovery available. ^[floss.txt]
  • capa.txt non-functional: Default signature path missing on this station; no capa ATT&CK mapping. ^[capa.txt]
  • No obfuscation in bootloader: No API hashing, no PEB walking, no anti-debug (IsDebuggerPresent is imported by the CRT but not used for evasion). The outer binary is entirely benign infrastructure. ^[pefile.txt:249-363]
  • Overlay stream count: binwalk.txt identified 15 zlib-compressed blocks and a PNG icon in .rsrc, consistent with a multi-member CFFI archive. ^[binwalk.txt]

How To Mess With It (Homelab Replication)

  • Toolchain: Install Python 2.7 and PyInstaller 3.x on a Windows research VM. Build the onefile executable: pyinstaller --onefile --windowed your_miner_script.py
  • Extraction: Use pyinstxtractor.py against the PE to dump the embedded CFFI archive, then inspect with uncompyle6 or decompyle3.
  • Differentiator: This sibling's smaller size suggests fewer bundled dependencies (no numpy, no requests, etc.). Compare overlay entropy and member count across siblings.

Deployable Signatures

YARA rule

rule PyInstaller_Coinminer_2018_Sibling {
    meta:
        description = "PyInstaller single-file bootloader sibling (Sep 2018 MSVC, coinminer cluster)"
        author = "Titus"
        date = "2026-06-08"
        sha256 = "b4cc27e365f44dd18593d7ca2b4a2d9df95268079beff47940f48cce21bfc979"
    strings:
        $pyi1 = "PyInstaller: FormatMessageW failed." ascii wide
        $pyi2 = "_MEIPASS2" ascii wide
        $pyi3 = "pyi-runtime-tmpdir" ascii wide
        $pyi4 = "Failed to execute script %s" ascii wide
        $pyi5 = "Cannot open self %s or archive %s" ascii wide
        $inflate = "inflate 1.2.8 Copyright 1995-2013 Mark Adler" ascii wide
        $python27 = "python27.dll" ascii wide
        $libgcc = "libgcc_s_dw2-1.dll" ascii wide
    condition:
        uint16(0) == 0x5a4d and
        3 of ($pyi*) and
        $inflate and
        any of ($python27, $libgcc) and
        filesize > 400KB and filesize < 800KB
}

Sigma rule

Not suitable for the outer binary alone. Target the child process: python.exe or a renamed miner spawned from %TEMP%\_MEI* within seconds of parent launch.

IOC list

  • SHA-256: b4cc27e365f44dd18593d7ca2b4a2d9df95268079beff47940f48cce21bfc979
  • Temp path pattern: %TEMP%\_MEI*\* (PyInstaller extraction directory)
  • Embedded DLL names: python27.dll, libgcc_s_dw2-1.dll
  • Build timestamp: 0x5B8E9A15 (Tue Sep 4 14:43:33 2018 UTC)

Behavioural fingerprint

PE32 GUI executable compiled with MSVC 2015, containing a ~381 KB zlib-compressed overlay (60.5% of file). At runtime extracts payload to a _MEI-prefixed temp directory, loads python27.dll, and executes embedded marshalled Python bytecode. No suspicious imports in parent process; threat behaviour manifests in child Python/miner processes. Part of a cluster of at least six siblings sharing the identical Sep 2018 build timestamp.

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 _MEI path
  • Capa: non-functional (missing signatures). No ATT&CK mapping available.

References

Provenance

  • file.txtfile command (PE32 executable)
  • strings.txt — strings (1468 lines)
  • rabin2-info.txt — radare2 rabin2 -I (binary metadata)
  • pefile.txtpefile Python module (sections, imports, resources)
  • binwalk.txtbinwalk (embedded artifacts / zlib blocks)
  • exiftool.json — ExifTool PE metadata
  • floss.txt — flare-floss (tool argument error, no decoded output)
  • capa.txt — flare-capa (signature path error, no output)
  • triage.json — triage tier assignment
  • metadata.json — artifact metadata from OpenCTI
  • dynamic-analysis.md — CAPE skipped (no Windows guest available)
  • R2 decompilation — radare2 via MCP (entry0 at 0x004079d3)