typeanalysisfamilyblackmatterconfidencehighpeloadermalware-familyreflective-pe-loaderpeb-walking-api-resolutionxor-not-alphabet-cipherlcg-prng-c2-url-generationcpuid-hypervisor-vm-gatemsvc-pogo-reflective-loaderdropped-by-phorpiex
SHA-256: 0cd5240c696194cf2eb701cd4d4ca81e7f17612a4042ebb56959008d66537b4b

blackmatter (blackmatter cluster): 0cd5240c6961 — 27th sibling, .text hash matches majority group, PE checksum 0x287d2

Executive Summary

Twenty-seventh confirmed sibling in the MSVC 14.12 PEB-walking reflective-loader cluster distributed via Phorpiex spam infrastructure. Same compilation timestamp (0x631A9665), same linker (MSVC 14.12), same XOR-NOT alphabet cipher key (0x10035fff), and same .text hash (000a9a8b...) as the majority-group siblings. Per-sample deltas are limited to the individualized .data payload and PE checksum (0x287d2). Bears both blackmatter and dropped-by-phorpiex OpenCTI labels. Static-only analysis (CAPE skipped — no Windows guest).

What It Is

  • File type: PE32 executable (GUI) Intel 80386, 6 sections ^[file.txt]
  • Size: 149,504 bytes (146 KB) ^[triage.json]
  • Compilation: Fri Sep 9 01:27:01 2022 UTC (0x631A9665) ^[pefile.txt:34]
  • Linker: MSVC 14.12 (VS 2017 15.5+) — MajorLinkerVersion=0xE, MinorLinkerVersion=0xC ^[pefile.txt:45]
  • Subsystem: Windows GUI ^[pefile.txt:66]
  • Mitigations: ASLR (DYNAMIC_BASE), DEP/NX (NX_COMPAT), stack canary (canary=true) ^[pefile.txt:74],^[rabin2-info.txt:6]
  • Signing: Unsigned (signed: false) ^[rabin2-info.txt:27]
  • POGO: IMAGE_DEBUG_TYPE_POGO debug directory present ^[pefile.txt:313]
  • PE checksum: 0x287d2 (unique per-sample) ^[terminal:python hash]
  • OpenCTI labels: blackmatter, dropped-by-phorpiex, exe, malware-bazaar ^[triage.json]
  • Family: blackmatter cluster sibling (contested label — actual payload family is unattributed reflective loader) ^[entities/blackmatter.md]

How It Works

Builder-pipeline twin: shared MSVC 14.12 reflective-loader stub template with a per-sample encrypted payload injected into .data. The stub decrypts the payload, maps it reflectively into RWX memory, and transfers execution. No disk write of the inner payload.

Shared behavior (identical across all 27 siblings) is documented at blackmatter and peb-walking-api-resolution. Per-sample deltas are limited to:

  • .data section contents (individualized encrypted payload)
  • .pdata section contents (exception-table update for payload)
  • PE checksum (builder-computed, unique per sample)

Decompiled Behavior

Radare2 analysis recovered the same three core functions seen in every sibling:

fcn.004192f4 — Payload decryption loop

^[r2:fcn.004192f4]

Implements a 6-round (24 dwords) decryption over the .data payload:

  • bswap → ror 0xd → not → XOR with next dword
  • rol 0xb → bswap
  • rol 9 → bswap → not
  • rol 7 → bswap → XOR with not of previous
  • rol 5 → final XOR

Identical cipher sequence to all prior siblings.

fcn.0041941c — Runtime string decryption (XOR-NOT alphabet table)

^[r2:fcn.0041941c]

Builds a 256-byte substitution alphabet in a stack buffer, then XOR-decrypts strings using the running table. Same 0x10035fff-keyed XOR-NOT cipher documented at peb-walking-api-resolution.

fcn.004104b4 — Reflective PE mapper / entry-point orchestrator

^[r2:fcn.004104b4]

Called by fcn.00409bb0 (entry-point wrapper). Resolves the decrypted payload as a PE image, patches relocations, resolves imports via PEB-walking, allocates RWX memory (0x40 = PAGE_EXECUTE_READWRITE), and maps sections. Uses VirtualAlloc, memmove, and GetProcAddress equivalents resolved at runtime.

fcn.00401564 — PEB-walking API resolver

^[r2:fcn.00401564]

Traverses InMemoryOrderModuleList to find kernel32.dll / ntdll.dll, hashes export names, and caches pointers in .data slots. Same function in every sibling with identical control flow.

C2 Infrastructure

No hardcoded C2 strings recovered statically. The LCG PRNG C2 URL generation routine (0x19660d / 0x3c6ef35f seeds) is present in the stub but produces runtime-only URLs. No domains, IPs, or URLs in strings.

Interesting Tidbits

  • .text SHA-256 000a9a8b1440e44cde00fd7acc5bdda6efc34f09e404de77cff1f5298e0af369 matches the majority-group siblings exactly, confirming identical compiler flags and source. ^[terminal:python hash of .text]
  • .data SHA-256 3c3597677127c210f4189f8a343cbad8032223fbe91c714d7bc51518a3a732d8 is unique to this sample — the individualized payload. ^[terminal:python hash of .data]
  • Both blackmatter and dropped-by-phorpiex OpenCTI labels present. ^[triage.json]
  • capa and floss both errored during triage (missing signatures and bad CLI invocation), so analysis relies on radare2 + manual PE inspection. ^[capa.txt],^[floss.txt]
  • .itext section (0x600 bytes, entropy 2.93) contains the decompression/thunk stub, low-entropy confirming fixed template. ^[pefile.txt:112]
  • LCG constants 0x19660d and 0x3c6ef35f found at file offsets 0x518 and 0x522 respectively. ^[terminal:python pattern search]
  • XOR key 0x10035fff found at file offset 0x64e. ^[terminal:python pattern search]
  • CPUID instruction found at file offset 0x4c1. ^[terminal:python pattern search]

How To Mess With It (Homelab Replication)

See primary cluster analysis at /intel/analyses/136b57507a3cfe1fc39cf6973869dca7e871e91d63f283c77380fc33298d6d51.html for full reproduction pipeline. In short:

  1. Compile a MSVC 14.12 x86 PE stub with POGO optimization.
  2. Embed a PE payload in .data, encrypted with the 6-round bswap/ror/rol/not cipher.
  3. Implement PEB-walking API resolution and RWX VirtualAlloc mapping.
  4. Run capa on reproducer and compare to cluster fingerprint (minimal IAT, GDI/USER32 facade imports, VirtualAlloc+memmove runtime resolution).

Deployable Signatures

YARA rule

rule BlackmatterCluster_ReflectiveLoader
{
    meta:
        description = "MSVC 14.12 PEB-walking reflective-loader cluster (blackmatter siblings)"
        author = "Titus"
        reference = "/intel/analyses/0cd5240c696194cf2eb701cd4d4ca81e7f17612a4042ebb56959008d66537b4b.html"
    strings:
        $peb_walk_sig = { 64 A1 30 00 00 00 }         // mov eax, fs:[0x30]  ; PEB access
        $decrypt_a = { 0F C8 66 C1 C8 0D F7 D0 }      // bswap, ror 0xd, not
        $decrypt_b = { C1 C0 0B 0F C8 33 D0 }        // rol 0xb, bswap, xor
        $decrypt_c = { C1 C0 09 0F C8 F7 D0 }        // rol 9, bswap, not
        $decrypt_d = { C1 C0 07 0F C8 33 D0 }        // rol 7, bswap, xor
        $xor_key = { FF 5F 03 10 }                   // XOR-NOT key fragment 0x10035fff
        $pogo = "POGO" ascii
        $linker_14_12 = { 0E 0C }                    // MajorLinker=14, MinorLinker=12
    condition:
        uint16(0) == 0x5A4D and
        uint32(uint32(0x3C)) == 0x00004550 and
        #linker_14_12 >= 1 and
        #pogo >= 1 and
        any of ($decrypt_a, $decrypt_b, $decrypt_c, $decrypt_d) and
        filesize < 200KB
}

IOC list

Indicator Value Notes
SHA-256 0cd5240c696194cf2eb701cd4d4ca81e7f17612a4042ebb56959008d66537b4b This sample
MD5 ce52f7d83d81eaaf9f01bea6343d0ce8 Full file
SHA-1 b12135523a1f8d1ce0fa2845ffcaa049e2e09952 Full file
.text SHA-256 000a9a8b1440e44cde00fd7acc5bdda6efc34f09e404de77cff1f5298e0af369 Majority-group fingerprint
.data SHA-256 3c3597677127c210f4189f8a343cbad8032223fbe91c714d7bc51518a3a732d8 Unique individualized payload
PE checksum 0x287d2 Unique per sample
Compilation Fri Sep 9 01:27:01 2022 UTC Shared across all 27 siblings
XOR key 0x10035fff Alphabet-cipher key (same across cluster)
LCG seeds 0x19660d / 0x3c6ef35f C2 URL PRNG (same across cluster)
Import facade GDI32 (6), USER32 (11), KERNEL32 (8) Minimal IAT, no threat APIs
Distribution dropped-by-phorpiex Phorpiex spam infrastructure

Behavioral fingerprint statement

This binary is a 150 KB PE32 GUI executable compiled with MSVC 14.12 and POGO optimization. Its import table contains only 25 benign GUI/system APIs (GDI32, USER32, KERNEL32). At runtime it resolves threat APIs via PEB-walking export hashing, decrypts a ~40 KB payload in .data using a 6-round bswap/ror/rol/not cipher, maps the decrypted image into RWX memory, and transfers execution without writing to disk. It performs CPUID hypervisor-bit checks and RDTSC timing gates before decryption. No hardcoded C2 — URLs are generated at runtime via an LCG PRNG seeded with 0x19660d/0x3c6ef35f.

Detection Signatures

ATT&CK Technique Evidence Source
T1055 — Process Injection RWX VirtualAlloc + reflective PE mapping into self process ^[r2:fcn.004104b4]
T1027 — Obfuscated Files or Information 6-round custom cipher on .data payload ^[r2:fcn.004192f4]
T1027.002 — Software Packing Runtime decryption + in-memory mapping; no payload on disk ^[r2:fcn.004104b4]
T1620 — Reflective Code Loading Manual PE mapping, relocation patching, import resolution ^[r2:fcn.004104b4]
T1497.001 — Virtualization/Sandbox Evasion: System Checks CPUID hypervisor-bit check + RDTSC timing gate ^[peb-walking-api-resolution]
T1106 — Native API PEB-walking to resolve Nt* / Zw* APIs without imports ^[r2:fcn.00401564]

References

  • Primary cluster analysis: /intel/analyses/136b57507a3cfe1fc39cf6973869dca7e871e91d63f283c77380fc33298d6d51.html
  • Entity pages: blackmatter, peb-walking-api-resolution, unattributed
  • Delivery: phorpiex
  • Sibling reports: raw/analyses/89dc341bbd.../report.md (19th), raw/analyses/8655b3b9b2.../report.md (20th), raw/analyses/91e39f6bb60a.../report.md (21st), raw/analyses/65844473d39b.../report.md (22nd), raw/analyses/044539a2eacf.../report.md (23rd), raw/analyses/f016df16d0f3.../report.md (24th), raw/analyses/a397bea4c70b.../report.md (25th), raw/analyses/93da3f615d04.../report.md (26th)

Provenance

  • file.txt — file-type identification (file v5.44)
  • exiftool.json — PE metadata (ExifTool 12.76)
  • pefile.txt — DOS/NT headers, sections, imports, relocations, debug directory (pefile)
  • rabin2-info.txt — radare2 binary summary (r2)
  • strings.txt — ASCII/Unicode strings extraction (strings)
  • triage.json — triage pipeline metadata (custom)
  • metadata.json — OpenCTI connector artifact metadata
  • capa.txt — Mandiant capa (errored: missing signatures)
  • floss.txt — FireEye FLOSS (errored: bad CLI invocation)
  • dynamic-analysis.md — CAPE sandbox (skipped: no Windows guest available)
  • radare2 static analysis: mcp_radare2 with analysis level 3, 519 functions recovered, decompilation of fcn.004192f4, fcn.0041941c, fcn.004104b4, fcn.00401564, fcn.00409bb0