typeanalysisfamilyphorpiexconfidencehighmalware-familypespamimpactc2-protocoldefense-evasion
SHA-256: c3b1b4e4eab9589b9132c57cc6dc9f26b93fee922b78923780cb79ce705f106b

phorpiex: c3b1b4e4 — MSVC9 sextortion spam bot, $800 variant, mutex t5

Self-contained SMTP spam bot compiled with Visual Studio 2008 (MSVC 9.0), distributed via the Phorpiex dropper pipeline. It downloads a recipient list, spawns 5,000 threads, and relays sextortion emails demanding $800 in BTC to a hardcoded wallet. Static-only analysis (CAPE skipped — no Windows guest).

What It Is

Field Value
SHA-256 c3b1b4e4eab9589b9132c57cc6dc9f26b93fee922b78923780cb79ce705f106b
File PE32 executable (GUI) Intel 80386, 5 sections, 18.9 KB ^[file.txt]
Linker MSVC 9.0 (Visual Studio 2008), MSVCR90.dll CRT ^[exiftool.json] ^[rabin2-info.txt]
Compiled 2026-05-29 12:34:02 UTC ^[exiftool.json]
Signed Unsigned ^[rabin2-info.txt]
Packing None — normal section layout, .text entropy 5.99 ^[pefile.txt] ^[binwalk.txt]
Family phorpiex — high-confidence campaign attribution via dropped-by-phorpiex tag, MSVC9/MSVCR90 toolchain match, and identical sextortion payload architecture to confirmed siblings edd6ad22 and 150e4652.

How It Works

  1. Startup gate — Sleeps 2,000 ms, then creates mutex t5. If the mutex already exists, it exits immediately ^[strings.txt:20] ^[r2:main].
  2. Evasion — Deletes its own Zone.Identifier ADS to remove the "Downloaded from Internet" marker ^[r2:main].
  3. MX resolution — Queries yahoo.com via DnsQuery_A (type DNS_TYPE_MX, value 15) to find a relay target ^[strings.txt:16] ^[r2:fcn.00401790].
  4. String decrypt — Decrypts runtime strings with a 4-byte XOR+NOT cipher using the key Tmlr (0x54,0x6D,0x6C,0x72) ^[r2:fcn.00401030].
  5. Recipient list download — Generates a random %TEMP%\{rand}n.txt filename (srand(GetTickCount()) + rand() + %s%d), then downloads the recipient list via WinInet using a hardcoded Chrome/202 UA ^[strings.txt:17] ^[r2:fcn.004024e0].
  6. Thread storm — Spawns 5,000 threads in a nested loop (100 outer iterations × 50 inner iterations). Each thread reads the temp file, probabilistically selects one line using a floating-point RNG comparison (fild/fdivrp/fcompp), tokenises on : and //, and passes the result to the SMTP engine ^[r2:fcn.004024e0] ^[r2:fcn.00402340].
  7. SMTP delivery — Opens a TCP socket to the recipient domain, negotiates EHLO/HELO, emits MAIL FROM (spoofed as the victim's own address), RCPT TO, and DATA, then sends the full sextortion template including the $800 demand and BTC wallet 1Gpu4hxcqpLZyjQ4JHZ6ieojyVBFj81Y3K ^[strings.txt:36-60] ^[r2:fcn.00401a10].
  8. Cleanup — After the loops, sleeps 20 s, deletes the temp file, and exits ^[r2:fcn.004024e0].

Decompiled Behavior

main @ 0x00402740 ^[r2:main]

  • Calls Sleep(2000).
  • Calls CreateMutexA(NULL, FALSE, "t5"); exits on ERROR_ALREADY_EXISTS (0xB7).
  • Builds a wide path %s:Zone.Identifier and calls DeleteFileW.
  • Calls WSAStartup(0x202, ...).
  • Calls fcn.00401790 (DNS MX query to yahoo.com).
  • Calls fcn.00401030 (string decrypt).
  • Spawns one background thread at fcn.004024e0.
  • Falls into an infinite Sleep(0xcdfe600) (effectively the main thread sleeps forever while the worker runs).

fcn.004024e0 (thread dispatcher) ^[r2:fcn.004024e0]

  • Copies 260 bytes from an argument struct, seeds PRNG with GetTickCount().
  • Expands %TEMP% to a wide buffer, formats %sn.txt with a random integer suffix.
  • Calls fcn.00401900 (WinInet GET) to download the recipient list into that file.
  • Reads the first line via atoi; if the value is ≤ 0, calls ExitThread.
  • Outer loop iterates 100 times; inner loop iterates 50 times. Each inner iteration creates a thread at fcn.00402340 then sleeps rand() % 50 + 50 ms.
  • After loops, sleeps 20 s (0x4e20), deletes the temp file, and exits.

fcn.00402340 (recipient parser / SMTP launcher) ^[r2:fcn.00402340]

  • Opens %TEMP%\{rand}n.txt in read mode (_wfopen(L"r")).
  • Reads every line with fgets. Uses x87 FPU operations (fild, fdivrp, fcompp) to randomly select one line.
  • Copies the selected line to dest, then tokenises on : and // via strtok.
  • Calls fcn.00401a10 with the extracted address.

fcn.00401a10 (SMTP client) ^[r2:fcn.00401a10]

  • Calls socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) and connect to the MX target.
  • Sets SO_KEEPALIVE via setsockopt.
  • Implements a 7-case state machine (jump table at 0x401b4b):
    • Case 0: Search received banner for ESMTP (StrStrA).
    • Case 1: Send HELO %s\r\n.
    • Case 2: Send MAIL FROM: %s\r\n.
    • Case 3: Send RCPT TO: <%s>\r\n.
    • Case 4: Send DATA\r\n.
    • Case 5: Assemble the email body (From, To, Subject, Date, Message-ID, MIME headers) and the sextortion plaintext.
    • Case 6: Send QUIT\r\n and close the socket.
  • All sends route through fcn.00401150, which wraps WS2_32.dll_send and confirms full-length delivery.

fcn.00401030 (string decrypt) ^[r2:fcn.00401030]

  • Loads the 4-byte key Tmlr from .rdata (0x4041c0).
  • Iterates over the input buffer: buf[i] = ~(buf[i] ^ key[i % 4]).
  • Returns the in-place decrypted buffer.

fcn.00401900 (WinInet downloader) ^[r2:fcn.00401900]

  • Calls InternetOpenW with the hardcoded Chrome/202 UA.
  • Calls InternetOpenUrlW (URL not visible statically; likely decrypted at runtime).
  • Reads up to 1023 bytes via InternetReadFile into a static buffer at 0x406130.
  • If called with arg_8h == 1, writes the buffer to disk via CreateFileW + WriteFile.
  • Otherwise returns the buffer pointer.

C2 Infrastructure

No traditional command-and-control server. The binary is fully self-contained for its primary mission (SMTP spam), with two supporting network interactions:

  • External IP discovery — http://icanhazip.com/ (hardcoded, likely used in email headers or for campaign logging) ^[strings.txt:18].
  • MX resolution — yahoo.com via DnsQuery_A (type 15 / MX) ^[strings.txt:16].
  • Recipient list staging — A WinInet-downloaded plaintext file to %TEMP%\{rand}n.txt. The download URL is runtime-decrypted and was not recovered from static analysis. The file content is expected to be newline-delimited email addresses (or email:password pairs), with : and // used as delimiters.

Interesting Tidbits

  • Decrypt key Tmlr is Base64 for the lowercase letter i — likely a builder default or an inside joke, not a strong anti-analysis measure ^[r2:fcn.00401030].
  • x87 FPU RNG for line selection (fild, fdivrp, fcompp) is unusual in crimeware; it suggests the author copied a "pick random line from file" snippet from a legacy C tutorial ^[r2:fcn.00402340].
  • 5,000 threads is massive over-subscription for a ~19 KB binary. It relies on Windows scheduler and rapid connection failures (fire-and-forget) rather than any connection pooling or async I/O.
  • The email body is entirely in English, with no localisation, and reuses the exact template seen in siblings 150e4652, 17960bcb, and edd6ad22 — only the BTC wallet and ransom amount differ, confirming a shared builder/template engine ^[strings.txt:36-60].
  • floss.txt and capa.txt both failed during triage (floss received an invalid --no argument; capa could not locate its default signature database) ^[floss.txt] ^[capa.txt].
  • No persistence observed. No registry writes, no scheduled tasks, no startup folder drops. The binary expects to be executed once per campaign drop.

How To Mess With It (Homelab Replication)

Toolchain: Visual Studio 2008 (MSVC 9.0) or modern MinGW-w64 with -lwininet -lws2_32 -ldnsapi.

Core C skeleton that reproduces the static fingerprint:

#include <windows.h>
#include <wininet.h>
#include <stdio.h>
#pragma comment(lib, "wininet.lib")

void decrypt(char *s) {
    const char key[] = "Tmlr";
    for (size_t i = 0; i < strlen(s); i++)
        s[i] = ~(s[i] ^ key[i % 4]);
}

int main() {
    Sleep(2000);
    HANDLE h = CreateMutexA(NULL, FALSE, "t5");
    if (GetLastError() == ERROR_ALREADY_EXISTS) return 0;
    // ... WSAStartup, DnsQuery_A, InternetOpenW, thread storm ...
    return 0;
}

Verification: Compile and inspect imports with rabin2 -i repro.exe. Expected surface: MSVCR90.dll (or msvcrt.dll for MinGW), WININET.dll, WS2_32.dll, DNSAPI.dll, KERNEL32.dll, USER32.dll, SHLWAPI.dll. No ADVAPI32.dll, no CRYPT32.dll.

Deployable Signatures

YARA

rule phorpiex_sextortion_spam_bot_c3b1b4e4 {
    meta:
        description = "Phorpiex sextortion spam bot $800 variant (c3b1b4e4)"
        author      = "PacketPursuit"
        date        = "2026-09-01"
        sha256      = "c3b1b4e4eab9589b9132c57cc6dc9f26b93fee922b78923780cb79ce705f106b"
    strings:
        $btc     = "1Gpu4hxcqpLZyjQ4JHZ6ieojyVBFj81Y3K" ascii wide
        $ua      = "Chrome/202.0.4664.110 Safari/537.36" ascii wide
        $mx      = "yahoo.com" ascii wide
        $ipcheck = "http://icanhazip.com/" ascii wide
        $ehlo    = "EHLO %s\r\n" ascii wide
        $mailfrom= "MAIL FROM: %s\r\n" ascii wide
        $subject = "YOU PERVERT! I RECORDED YOU!" ascii wide
        $mutex   = "t5" ascii wide
        $tmpl1   = "Unfortunately, there is some bad news for you." ascii wide
        $tmpl2   = "My Trojan allowed me to access your files, accounts, and your camera." ascii wide
        $tmpl3   = "I RECORDED YOU (through your camera) MASTURBATING!" ascii wide
        $tmpl4   = "All you need is $800 USD in Bitcoin (BTC)" ascii wide
    condition:
        uint16(0) == 0x5A4D and filesize < 30KB and
        4 of ($tmpl*) and
        ( ($btc and $ua) or ($mx and $ipcheck and $ehlo and $mailfrom) )
}

Behavioral Hunt Query (KQL)

// Process creates mutex t5 and imports WININET+WS2_32+DNSAPI
let phorpiex_mutex = "t5";
let phorpiex_btc   = "1Gpu4hxcqpLZyjQ4JHZ6ieojyVBFj81Y3K";
DeviceProcessEvents
| where InitiatingProcessCommandLine !contains "explorer.exe"
| where ProcessCommandLine contains phorpiex_mutex
   or ProcessCommandLine contains phorpiex_btc
// Memory-hunt variant: search process memory for the BTC wallet string

IOC List

Indicator Value Notes
SHA-256 c3b1b4e4eab9589b9132c57cc6dc9f26b93fee922b78923780cb79ce705f106b Canonical
ssdeep 192:BnIISCngTBvblVPT0Y76fIkq2NleQY9T4KUSvu9zw+ggSmOiMbO5Ot1EdkF39TGW:BxIblVP4Y/2N0bLu9JgPL7Nyav8U9c4 ^[ssdeep.txt]
tlsh E8824B0FF9418216D1E210B452B5867BDA799C72338458DBFBD08A9D0BA86E6FC3315F ^[tlsh.txt]
Mutex t5 Single-instance gate ^[strings.txt:20]
BTC wallet 1Gpu4hxcqpLZyjQ4JHZ6ieojyVBFj81Y3K Campaign-specific ^[strings.txt:59]
Fake UA Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/202.0.4664.110 Safari/537.36 Impossible version ^[strings.txt:17]
MX target yahoo.com DNS query target ^[strings.txt:16]
IP check http://icanhazip.com/ External IP discovery ^[strings.txt:18]
Temp file %TEMP%\{rand}n.txt Random numeric suffix via srand(GetTickCount()) ^[r2:fcn.004024e0]
Subject YOU PERVERT! I RECORDED YOU! Window title / email subject ^[strings.txt:146]

Behavioral Fingerprint

This PE32 GUI binary, compiled with MSVC 9.0 and linked against MSVCR90.dll, imports WININET.dll, WS2_32.dll, and DNSAPI.dll but not ADVAPI32.dll or CRYPT32.dll. Upon execution it creates a mutex named t5, deletes its own Zone.Identifier ADS, queries yahoo.com via DnsQuery_A for MX records, downloads a recipient list over HTTP using a hardcoded Chrome/202 UA, then spawns 5,000 threads that open TCP/25 sockets and emit SMTP EHLO, MAIL FROM, and RCPT TO commands followed by a sextortion email body demanding $800 in BTC to wallet 1Gpu4hxcqpLZyjQ4JHZ6ieojyVBFj81Y3K. It writes a temporary %TEMP%\{rand}n.txt file and deletes it after the campaign loop.

Detection Signatures

  • YARA: Suspicious_Wininet_Imports (triage hit) ^[yara.txt].
  • capa: Failed — signature database not installed during triage ^[capa.txt].
  • floss: Failed — CLI argument parsing error (--no flag) ^[floss.txt].

References

  • phorpiex — Crimeware botnet/dropper family; umbrella label for spam-delivered droppers and sextortion spam bots.
  • edd6ad22 — Phorpiex sibling ($800 variant, mutex etyueu, identical toolchain) ^[/intel/analyses/edd6ad227595d25c2cf6cf41d2ac9b6640b2e977aabb2d07eea58fa500b6db19.html]
  • 150e4652 — Phorpiex sibling ($1200 variant, identical SMTP engine) ^[/intel/analyses/150e46523ae4a3e90ce949f15630b2f07d475d3a781188301edded1d527f03af.html]

Provenance

  • file.txt — file v5.44
  • exiftool.json — ExifTool v12.76
  • pefile.txt — pefile v2023.2.7 + Python 3.11
  • rabin2-info.txt — radare2 v5.9.2
  • strings.txt — strings from GNU binutils 2.40
  • floss.txt — flare-floss v3.1.0 (CLI error)
  • capa.txt — capa v7.0.0 (signature path missing)
  • yara.txt — YARA v4.5.0
  • ssdeep.txt — ssdeep v2.14.1
  • tlsh.txt — tlsh v4.12.0
  • Static RE performed with radare2 v5.9.2 (78 functions recovered, level-3 analysis) on 2026-09-01.