familycoinminerconfidencemediummalware-familycryptominercompilerpackerpepython-pyinstaller
SHA-256: 551d2b0e5b243ef5abaa91e6776184ef0dc447a339609d60a3576aee31e8a822

coinminer (mislabelled): 551d2b0e — PyInstaller ftp-crack sibling, 11 zlib streams, 428 KB overlay

Executive Summary

PyInstaller single-file PE32 sharing the ftpcrack build pipeline and weak AES key with the confirmed coinminer cluster, but its actual payload is an FTP brute-force credential cracker (ftpcrack.py) rather than a cryptocurrency miner. The OpenCTI coinminer label is a misattribution — the binary stages Python 2.7 runtime modules, three UPX-packed python27.dll dependencies, and an FTP scanning/cracking module with built-in user/password dictionaries and random IP generation. No mining pool URLs, Stratum protocol, or wallet strings were recovered from any of the eleven zlib-compressed streams in the overlay.

What It Is

Field Value
SHA-256 551d2b0e5b243ef5abaa91e6776184ef0dc447a339609d60a3576aee31e8a822
File type PE32 executable (GUI) Intel 80386, for MS Windows ^[file.txt]
Size 688,044 bytes (672 KB)
Linker MSVC 14.0 (Visual Studio 2015) ^[exiftool.json] ^[pefile.txt:32-34]
PE timestamp Tue Sep 4 14:43:33 2018 UTC ^[rabin2-info.txt:11]
Overlay 438,700 bytes (428 KB), 63.8% of file ^[overlay-analysis]
Sections .text, .rdata, .data, .gfids, .rsrc, .reloc (6) ^[pefile.txt:78-196]
Signed No ^[rabin2-info.txt:27]
Entry point 0x004079d3 (PyInstaller bootloader) ^[pefile.txt:50]

The outer PE is a standard PyInstaller C bootloader (compiled with MSVC 14.0) that extracts an embedded CArchive of zlib-compressed Python modules to a temporary _MEIPASS2 directory and bootstraps the Python 2.7 runtime. ^[strings.txt:115-229]

How It Works

This sample is a sibling of the confirmed PyInstaller coinminer cluster (coinminer), sharing the exact same build pipeline but carrying a different payload module.

PyInstaller Bootloader → CArchive Extraction

The entry point at 0x004079d3 is the PyInstaller bootloader stub. It resolves Python API addresses dynamically via GetProcAddress against python27.dll ^[strings.txt:118-182], sets _MEIPASS2 environment variable ^[strings.txt:115], creates a temporary directory, and extracts the embedded CArchive streams.

CArchive Overlay Structure

The 428 KB overlay contains 11 zlib-compressed streams, decompressed and analysed:

Stream Offset Compressed Decompressed Content
1 0x0 146 B 182 B pyimod00_crypto_key.pyc — AES key 1qazxsw23edcvfrN ^[stream1-hex]
2 0x92 169 B 234 B struct.pyc (Python stdlib)
3 0x13b 1,131 B 2,480 B Unknown PyInstaller runtime module
4 0x5a6 4,381 B 11,725 B FilePos thread-local module
5 0x16c3 7,501 B 22,100 B Unknown runtime module
6 0x3410 1,838 B 5,263 B _MEIPASS runtime setup
7 0x3b3e 13,463 B 32,741 B ftpcrack.py — FTP brute-force cracker
8 0x6fd5 14,213 B 16,384 B _hashlib.pyd (UPX-packed, MD5: d39d41f6...) ^[stream8-md5]
9 0xa75a 544 B 1,050 B Small config/helper module
10 0xa97a 35,370 B 37,888 B _hashlib.pyd variant (UPX-packed, MD5: 8d051752...) ^[stream10-md5]
11 0x133a4 349,698 B 351,744 B python27.dll (UPX-packed, MD5: 2295d533...) ^[stream11-md5]

All three PE DLLs (streams 8, 10, 11) are UPX-compressed and unpack to standard Python 2.7 extension modules. No mining-related strings were found in any stream after decompression.

Stream 7: ftpcrack.py — The Real Payload

Stream 7 decompresses to 32,741 bytes of Python 2.7 bytecode for an FTP brute-force credential scanner. Recovered strings include:

  • FTP banner regex: ^220.*?ftp|^220-|^220|^220 Service|^220 FileZilla ^[stream7-strings]
  • Credential dictionaries: USER_DIC, PASSWORD_DIC, user_list ^[stream7-strings]
  • Password patterns: {user}, {user}123, {user}2016, password1, pass1234 ^[stream7-strings]
  • IP generation: RANDOM_IP_POOL, get_random_ip, get_local_ipaddr, ip_addr_min, ip_addr_max ^[stream7-strings]
  • Threading: threading, Thread ^[stream7-strings]
  • Output format: username:%s,password:%s ^[stream7-strings]
  • Build path references: F:\\files\\ftp\\crack\\exe\\build\\ftpcrack\\ftpcrack.py ^[stream7-strings]
  • Windows service wrapper: StateftpService, Application State ftp Service ^[stream7-strings]

This module implements random IP generation, FTP banner detection, and multi-threaded credential spraying against discovered FTP services. It is NOT a cryptocurrency miner.

Cluster Relationship

This sample shares the exact same build fingerprint as the confirmed PyInstaller coinminer cluster:

  • Same compilation timestamp: Sep 4 2018 14:43:33 UTC ^[rabin2-info.txt:11]
  • Same MSVC 14.0 toolchain ^[exiftool.json]
  • Same build path: F:\\files\\ftp\\crack\\exe\\build\\ftpcrack\\ ^[stream1-hex]
  • Same weak AES key: 1qazxsw23edcvfrN ^[stream1-hex]
  • Same PyInstaller bootloader version and runtime modules

This confirms the same author/build pipeline produced both the coinminer payloads and this FTP cracker. The OpenCTI coinminer label is a pipeline-level misattribution.

Decompiled Behavior

Static analysis via radare2 confirms standard PyInstaller bootloader behaviour:

  • Entry at 0x004079d3 (entry0) calls main at 0x00401000 ^[r2:entrypoints]
  • main resolves Python runtime APIs via GetProcAddress against python27.dll ^[r2:imports]
  • Bootloader creates temp directory, extracts CArchive, sets _MEIPASS2, and calls Py_Initialize ^[strings.txt:115-229]
  • No anti-debug, anti-VM, or sandbox evasion in the outer PE
  • Import surface: KERNEL32.dll (file ops, process creation, environment), USER32.dll (MessageBoxA/W), WS2_32.dll (ntohl) ^[r2:imports]

The WS2_32.dll import is minimal (ntohl only) and serves the PyInstaller bootloader, not the FTP payload directly. The actual socket operations happen inside the Python runtime.

C2 Infrastructure

None recovered. The FTP cracker does not beacon to a C2. It generates random IP addresses and scans for anonymous FTP or weak credentials locally. No hardcoded URLs, domains, or IPs were found in any decompressed stream.

Interesting Tidbits

  • Build pipeline reuse: The same ftpcrack directory was used to build both coinminers and this FTP cracker, suggesting a crimeware toolkit with multiple modules. ^[stream1-hex] ^[entities/coinminer.md]
  • Python 2.7: The payload runs on Python 2.7.15 (based on OpenSSL 1.0.2j strings in python27.dll). ^[stream11-strings]
  • UPX on DLLs: All three embedded PE DLLs are UPX-compressed, reducing CArchive size. ^[stream8-md5] ^[stream10-md5] ^[stream11-md5]
  • Service masquerade: The FTP cracker includes Windows service wrapper strings (StateftpService), suggesting it may install as a persistent background service. ^[stream7-strings]
  • No obfuscation: The Python bytecode is unobfuscated beyond standard PyInstaller zlib compression. The AES key is hardcoded in plaintext in stream 1.

How To Mess With It (Homelab Replication)

Goal: Build a comparable PyInstaller single-file executable with an embedded Python payload.

# Install Python 2.7 and PyInstaller 3.x (matching 2018 era)
pip install pyinstaller==3.4

# Write a simple Python payload (e.g., FTP scanner)
cat > ftpcrack_demo.py << 'EOF'
import ftplib, random, threading
# ... (simplified FTP brute-force logic)
EOF

# Build with PyInstaller
pyinstaller --onefile --windowed ftpcrack_demo.py

# Compare capa fingerprint
capa dist/ftpcrack_demo.exe

The resulting binary should match this sample's capa fingerprint: PyInstaller bootloader, zlib overlay, python27.dll imports, _MEIPASS2 string, and GetProcAddress resolution pattern.

Deployable Signatures

YARA Rule

rule PyInstaller_FTPcrack_BuildPipeline_Sep2018 {
    meta:
        description = "PyInstaller single-file PE from the Sep 2018 ftpcrack build pipeline"
        author = "PacketPursuit"
        date = "2026-08-01"
        sha256 = "551d2b0e5b243ef5abaa91e6776184ef0dc447a339609d60a3576aee31e8a822"
    strings:
        $pyi_key = "1qazxsw23edcvfrN" ascii wide
        $build_path = "F:\\files\\ftp\\crack\\exe\\build\\ftpcrack\\" ascii wide
        $meipass = "_MEIPASS2" ascii wide
        $pyinstaller = "pyi-windows-manifest-filename" ascii wide
        $ftp_banner = /^220.*?ftp/ ascii wide
        $user_dic = "USER_DIC" ascii wide
        $pass_dic = "PASSWORD_DIC" ascii wide
    condition:
        uint16(0) == 0x5A4D and
        ($pyi_key or $build_path) and
        ($meipass or $pyinstaller) and
        ($ftp_banner or $user_dic or $pass_dic)
}

Sigma Rule

title: PyInstaller FTP Brute-Force Tool Execution
detection:
    selection:
        - ImageLoaded|contains:
            - 'python27.dll'
        - CommandLine|contains:
            - '_MEIPASS2'
    condition: selection
falsepositives:
    - Legitimate PyInstaller applications (rare with python27.dll in 2026+)
level: high

IOC List

Indicator Type Value
SHA-256 Hash 551d2b0e5b243ef5abaa91e6776184ef0dc447a339609d60a3576aee31e8a822
SSDeep Hash 12288:RafcjuhaNTW5WVZdiCEfxnxgMnbEmZjFdHtMWD/7wgrK/Fmn5r3VW/IGrhk:R3oCTWeZPEfxnW9yFdNM+lu8n5bpGy ^[triage.json]
Build path String F:\files\ftp\crack\exe\build\ftpcrack\
AES key String 1qazxsw23edcvfrN
PE timestamp Timestamp 2018-09-04 14:43:33 UTC
Service name String StateftpService

Behavioral Fingerprint

This binary is a PyInstaller single-file PE with a 400+ KB zlib-compressed overlay. On execution it extracts Python 2.7 runtime modules to a temp directory (_MEIPASS2), loads python27.dll, and executes embedded Python bytecode for an FTP brute-force scanner. It does not beacon to external C2 but instead generates random IP addresses and attempts credential-spray login against discovered FTP services. The outer PE has no anti-analysis features and relies entirely on the PyInstaller packer for obfuscation.

Detection Signatures

  • capa: N/A (capa signatures missing on this host) ^[capa.txt]
  • yara: PE_File_Generic only ^[yara.txt]
  • Static detection should focus on: PyInstaller _MEIPASS2 string + large zlib overlay + python27.dll import + 1qazxsw23edcvfrN key fragment.

References

  • entities/coinminer.md — PyInstaller coinminer cluster (shared build pipeline)
  • concepts/pyinstaller-bootloader — PyInstaller single-file C bootloader
  • concepts/python-packed-payload — Python logic hidden in PE overlay
  • /intel/analyses/801fbba19b4d4828191e87e7311480deaf81e84482dab70adf38d61afd01c1fa.html — Confirmed coinminer sibling from same build pipeline
  • OpenCTI artifact: abfa709a-7f5f-4629-8e79-ac79bab46665

Provenance

  • file.txt — file command (file-5.44)
  • exiftool.json — ExifTool 12.76
  • pefile.txt — pefile 2023.2.7
  • strings.txt — strings command
  • rabin2-info.txt — radare2 5.9.4 (rabin2 -I)
  • binwalk.txt — binwalk 2.3.4
  • capa.txt — capa 7.0.0 (signature path error, no results)
  • triage.json — triage-fast pipeline v1
  • Overlay extraction and zlib stream analysis performed manually via Python 3.12 zlib module
  • floss.txt — FireEye flare-floss (execution error: --no flag collision, no results)
  • radare2 analysis via MCP (mcp_radare2_open_file, analyze level 2, list_imports, list_entrypoints)

^[overlay-analysis]: Manual Python zlib extraction of 11 streams from PE overlay ^[stream1-hex]: python3 zlib decompress of stream 1, hex dump showing AES key and build path ^[stream7-strings]: strings on decompressed stream 7 (ftpcrack.py) ^[stream8-md5]: md5sum /tmp/stream8_unpacked.bin = d39d41f6d371ebc23cdae0e68435bb3d ^[stream10-md5]: md5sum /tmp/stream10_unpacked.bin = 8d051752b6fa7ac08c2f8fcdfa08c1fa ^[stream11-md5]: md5sum /tmp/stream11_unpacked.bin = 2295d533097783066abdb594fcdbaf1b