typeanalysisfamilyghostpulseconfidencehighcreated2026-07-30updated2026-07-30malware-familyloaderqt5peevasionc2
SHA-256: 943cf1ebeb089abcd2e6ff0c2bfefa4631855948ab3ef3811cba1c635aa389d1

ghostpulse: 943cf1eb — Confirmed twin of 833bffd0 with individualized texture_mon.yaml encrypted payload

Executive Summary

A 12 MB 7-Zip SFX archive that is a byte-identical structural twin of the previously analyzed 833bffd0 sample. The outer SFX stub, inner Qt5 payload (CommunicMes.exe), and key/config sidecar (physics1024.map) all hash identically. The only delta is the 9.7 MB texture_mon.yaml encrypted payload, whose SHA-256 differs — confirming a builder that reuses the same loader but generates per-sample individualized ciphertext. No CAPE detonation available (no Windows guest); all behavior inferred from static extraction and hash comparison.

What It Is

  • Outer container: 7-Zip SFX mod (7ZSfxMod_x86.exe, Oleg Scherbakov, 2010), MSVC linker v8.0, compiled 2010-06-27 ^[file.txt] ^[exiftool.json]
  • Archive: LZMA-compressed 7z solid archive embedded at offset 0x2df4a; 11 files extracted ^[binwalk.txt] ^[sfx-config.json]
  • Inner payload: CommunicMes.exe — PE32+ x64, MSVC 14.26 (VS 2019), 8 sections, no exports, byte-identical to 833bffd0 inner payload (SHA-256 dd4469b6...) ^[file.txt] ^[rabin2-info.txt]
  • PDB path: D:\EPM\EPM19.9_release\Output\Release_x64\PELetterAdjust.pdb — EaseUS Partition Manager masquerade ^[strings.txt:1]
  • Sidecar files: texture_mon.yaml (9.7 MB, entropy 7.91) — individualized per-sample encrypted payload vs 833bffd0; physics1024.map (34 KB, entropy 5.49) — identical key/config sidecar to 833bffd0 ^[extracted/entropy-analysis]

How It Works

Stage 1 — SFX Extraction

Identical to 833bffd0: silent extraction to %TEMP% via RunProgram="%%T\\CommunicMes.exe" with Progress=no and GUIFlags=8 (suppress GUI). ^[sfx-config.json] The 7z archive contains the Qt5 runtime, MSVC redistributables, and three attacker-controlled files: CommunicMes.exe, texture_mon.yaml, and physics1024.map.

Stage 2 — Qt5 Payload Execution

CommunicMes.exe is a Qt5 GUI application compiled for x64. Import surface: Qt5Core (QProcess/QFile/QDir/QStorageInfo APIs), KERNEL32, SHELL32, and the UCRT/VCRT runtime. ^[rabin2-info.txt] No direct crypto, networking, or injection imports — malicious behavior is dynamically resolved or implemented inside the encrypted sidecar files. radare2 analysis reveals 562 functions, standard MSVC C++ CRT initialization, and QProcess::startDetached usage for child process spawning. ^[r2:analysis-output]

Stage 3 — Encrypted Sidecar Loading

texture_mon.yaml is 9.7 MB with Shannon entropy of 7.91 (near-random), consistent with encrypted payload data. It is the only per-sample individualized artifact — its SHA-256 differs from 833bffd0 (597f95aa... vs 840c209e...), while all other archive contents are byte-identical. physics1024.map (34 KB, entropy 5.49) is unchanged, suggesting it serves as a shared decryption key, configuration header, or IV/key-schedule file. The inner executable references .texture_mon.yaml in its .rdata section, confirming runtime file-open pattern. ^[strings.txt]

Decompiled Behavior

radare2 analysis of CommunicMes.exe (identical to 833bffd0 inner payload) shows standard MSVC C++ CRT initialization (__initterm_e, __initterm) followed by Qt5 framework calls. The most relevant behavioral indicator is QProcess::startDetached for child process execution, which can bypass conventional parent-child telemetry. No direct obfuscation, anti-debug, or control-flow flattening is present in the inner binary. ^[r2:analysis-output]

Notable strings in .rdata (identical to 833bffd0):

  • X:\Program Files\Other\Tools\EPM.bat — batch path for EaseUS masquerade
  • diskpart.exe /s %1, assign letter=%1, remove letter=%1 — disk-partition manipulation commands
  • TexturePattern, .texture_mon.yaml — confirms runtime reference to encrypted payload file

C2 Infrastructure

No static C2 indicators recovered. Network connectivity, if any, is expected to be encrypted inside texture_mon.yaml and decrypted at runtime by the Qt5 application. The absence of observable C2 strings is consistent with a modular loader pattern where per-sample C2 config is delivered inside the individualized sidecar.

Interesting Tidbits

  1. Builder confirmation: The fact that CommunicMes.exe and physics1024.map are byte-identical across two distinct outer samples (833bffd0 and 943cf1eb) confirms the GhostPulse builder uses a fixed inner-loader template and re-encrypts only the payload sidecar per distribution. This is economical — one compiled loader, many campaigns. ^[extracted/hash-comparison]

  2. Per-sample payload differentiation: texture_mon.yaml is the individualized component. Its SHA-256 differs, but its size (9.7 MB vs 9.8 MB in 833bffd0) and entropy (~7.9) remain consistent, suggesting the builder pads or re-encrypts a common inner payload with per-sample keys. ^[extracted/hash-comparison]

  3. Family scale: This is the 50th confirmed GhostPulse sibling in the PacketPursuit corpus. With 49 prior siblings and the builder reusing the same loader template, the true distribution count is likely far higher. ^[ghostpulse]

  4. EaseUS masquerade depth: The PDB path references EPM19.9 (EaseUS Partition Master v19.9), a real product. The diskpart strings and partition logic thematically reinforce the masquerade. ^[strings.txt]

  5. Qt5 as evasion surface: Bundling the entire Qt5 runtime (~6 MB for Qt5Core.dll alone) inflates the payload and buries malicious imports inside a massive legitimate library surface. ^[rabin2-info.txt]

How To Mess With It (Homelab Replication)

Identical to 833bffd0 — see the ghostpulse entity page for the full build recipe. Key takeaways:

  1. Build a Qt5 C++ GUI app with MSVC 2019+ linking dynamically against Qt5Core.dll
  2. Open a hardcoded sidecar file from the application directory, decrypt in-memory, and reflectively execute
  3. Compile with /SUBSYSTEM:WINDOWS
  4. Package with 7-Zip SFX (7zSfxMod) using RunProgram="%%T\\YourApp.exe"
  5. Bundle Qt5Core.dll, UCRT, VCRT, and your encrypted sidecar

Per-sample builder variant: The builder reuses the same CommunicMes.exe and physics1024.map but generates a fresh texture_mon.yaml per campaign. To replicate this pattern, keep the loader and key file static, and re-encrypt the inner payload with a campaign-specific key.

Deployable Signatures

YARA Rule — GhostPulse SFX Loader (Twin Detection)

rule GhostPulse_SFX_Qt5_Loader_Twin {
    meta:
        description = "Detects GhostPulse family 7-Zip SFX dropper with Qt5 inner payload and individualized texture_mon.yaml"
        author = "PacketPursuit"
        date = "2026-07-30"
        sha256 = "943cf1ebeb089abcd2e6ff0c2bfefa4631855948ab3ef3811cba1c635aa389d1"
    strings:
        $sfx1 = "7ZSfxMod" ascii
        $sfx2 = "7-Zip SFX" wide
        $runprog = /RunProgram="%%T\\[A-Za-z]{5,20}\.exe"/ wide
        $qt5 = "Qt5Core.dll" ascii
        $yaml = ".texture_mon.yaml" ascii
        $map = ".physics1024.map" ascii
    condition:
        uint16(0) == 0x5A4D and
        filesize > 5MB and filesize < 25MB and
        ($sfx1 or $sfx2) and
        $runprog and
        ($qt5 or $yaml or $map)
}

YARA Rule — GhostPulse Individualized Sidecar

rule GhostPulse_Individualized_TextureMon {
    meta:
        description = "Detects GhostPulse individualized encrypted payload sidecar texture_mon.yaml"
        author = "PacketPursuit"
        date = "2026-07-30"
    strings:
        $yaml = ".texture_mon.yaml" ascii
        $tex = "TexturePattern" ascii
    condition:
        uint16(0) == 0x5A4D and
        pe.machine == pe.MACHINE_AMD64 and
        any of ($yaml, $tex)
}

Behavioral Hunt Query (Sigma)

title: GhostPulse Qt5 Encrypted Sidecar Execution (Twin Variant)
logsource:
  category: process_creation
  product: windows
detection:
  selection:
    CommandLine|contains:
      - 'CommunicMes.exe'
    ParentImage|endswith:
      - '\7zSfxMod.exe'
      - '\7z.exe'
  sidecar:
    - TargetFilename|endswith:
        - 'texture_mon.yaml'
        - 'physics1024.map'
  condition: selection or sidecar
falsepositives:
  - Unknown
level: high

IOC List

Type Value Context
SHA-256 (outer) 943cf1ebeb089abcd2e6ff0c2bfefa4631855948ab3ef3811cba1c635aa389d1 7-Zip SFX dropper (this sample)
SHA-256 (inner) dd4469b6bb8bf5ce4dd8560cecf1cfc16272f18f26960a4569d636b8b02aec96 CommunicMes.exe (confirmed twin)
SHA-256 (sidecar, individualized) 597f95aad7e8f81cacd60a1d2ea7872e8507b197c39ecb89c5514534561d741e texture_mon.yaml (unique to this sample)
SHA-256 (sidecar, shared) cccf57e73ad1d23b674c0c6a64d10fc108a4dce2b569f09db86595c0e06845a8 physics1024.map (identical to 833bffd0)
PDB path D:\EPM\EPM19.9_release\Output\Release_x64\PELetterAdjust.pdb Masquerade artifact
File paths %TEMP%\CommunicMes.exe Extracted payload
File paths %TEMP%\texture_mon.yaml Individualized encrypted sidecar
File paths %TEMP%\physics1024.map Shared key/config sidecar

Detection Signatures

Technique ATT&CK ID Evidence
Masquerading T1036.005 EaseUS Partition Manager PDB path and diskpart strings
Ingress Tool Transfer T1105 7-Zip SFX extracts payload from embedded archive
Encrypted Payload T1027.002 texture_mon.yaml (9.7 MB, entropy 7.91) — individualized per sample
Data Obfuscation T1027 physics1024.map suspected shared key material
Process Injection (inferred) T1055 QProcess::startDetached used for child execution

References

  • ghostpulse — Entity page for this family
  • /intel/analyses/833bffd0ff2291001e0cb62f529cf947ba2753fa5888820848a2014eda2dc334.html — First detailed analysis (confirmed twin)
  • Sample source: OpenCTI / MalwareBazaar, artifact ID f4c70c52-ef44-42bf-a89f-10f2002b3243
  • EaseUS Partition Manager (legitimate): https://www.easeus.com/partition-manager/
  • 7-Zip SFX Mod (legitimate): https://github.com/chrislake/7zsfxmod

Provenance

  • Outer binary analysis: file v5.44, exiftool v12.76, pefile Python module, binwalk v2.3.4, radare2 v5.x
  • Archive extraction: 7z v23.01, offset 188234 (0x2df4a)
  • Inner binary analysis: file v5.44, radare2 v5.x (562 functions, level-2 analysis)
  • Entropy calculation: Python 3 math.entropy via custom script
  • Hash comparison: Python 3 hashlib.sha256 across extracted files
  • Capa: signatures path missing — no results ^[capa.txt]
  • Floss: CLI argument error — no results ^[floss.txt]
  • Dynamic analysis: Skipped — CAPE has no Windows guest available for PE32 platform ^[dynamic-analysis.md]