94db5892d51fa7f24c6f406591d5cc143f48f3f9f576c66d36a8682e3950102bghostpulse: 94db5892 — x86 YHClient masquerade with Log.dll sidecar and cmd.exe pipe execution
Executive Summary
A 6.2 MB 7-Zip SFX archive that silently extracts an x86 MSVC C++ payload (FrameworSwitch32.exe) to %TEMP% and executes it. The inner PE masquerades as a "YHClient" product with PDB paths referencing D:\slave\workspace\YHClient\Release\startbc.pdb. It is bundled with a custom Log.dll helper, legitimate MSVC redistributables, a 6 MB high-entropy encrypted sidecar (monitor.sym), and a 34 KB config file (sampler.xml). Notably, this sample diverges from prior GhostPulse siblings by using an x86 (not x64/Qt5) inner payload and introducing a cmd.exe pipe-execution pattern not observed in the Qt5 cluster. No CAPE detonation available (no Windows guest); all behavior inferred from static extraction and decompilation.
What It Is
- Outer container: 7-Zip SFX stub (
7ZSfxMod_x86.exe, Oleg Scherbakov, 2010), MSVC linker v8.0, compiled 2010-06-27 ^[exiftool.json] ^[pefile.txt] - Archive: LZMA-compressed 7z solid archive at offset
0x2df4f; 6 files extracted to%TEMP%^[binwalk.txt] ^[sfx-config.json] - Inner payload:
FrameworSwitch32.exe— PE32 x86, MSVC 14.x (VS 2019+), timestamp0x6790d7cb(2025-01-22), 6 sections, no Authenticode ^[file.txt] ^[rabin2-info.txt] - PDB path:
D:\slave\workspace\YHClient\Release\startbc.pdb— masquerades as a "YHClient" product build ^[rabin2-info.txt] ^[r2:str.startbc.pdb] - Helper DLL:
Log.dll— PE32 x86, same toolchain/timestamp as inner payload, exportsGenericLogImpl,LogSetOption,LogSetOutputLevel^[file.txt] - Sidecar files:
monitor.sym(5.98 MB, entropy 7.95, near-random — encrypted payload) andsampler.xml(34 KB, entropy 5.35 — likely config/key) ^[terminal:entropy-check] - Legitimate libraries:
msvcp_win.dllanducrtbase.dll— standard MSVC 2019+ redistributables
How It Works
Stage 1 — SFX Extraction
The outer binary is a legitimate 7-Zip SFX mod configured to silently extract (Progress=no, GUIFlags=8) to %TEMP% and immediately run "%%T\\FrameworSwitch32.exe". ^[sfx-config.json] The 7z archive contains the inner payload, the Log.dll helper, MSVC runtime libraries, and two attacker-controlled sidecar files.
Stage 2 — Payload Execution (FrameworSwitch32.exe)
main() at 0x004058b0 performs the following control flow: ^[r2:main]
- Clean-Edashi gate: Tests bit
0x4000at0x43394c. If set, logs"Execute Clean Edashi finished!"vialog.dll_GenericLogImpland exits. This is a conditional abort path, possibly environment-gated. - Single-instance mutex: Opens mutex
{FA531CC1-0497-11d3-A180-00105A276C3E}withSYNCHRONIZErights. If the mutex exists, the process finds a window viaFindWindowWand sendsWM_USER+0x4a(0x4a = 74) withlParampointing to a 1307-byte (0x51b) payload — likely inter-process communication to an already-running instance. ^[r2:main] - Path construction: Builds a wide-char path to
BarClientView.exein the same directory. ^[r2:main:0x00405986] - File-existence check: Calls
PathFileExistsWon the constructed path. ^[r2:main:0x004059dd] - Launch: If the file exists, calls
ShellExecuteW("open", ...)to launch it. If not, logs"path not exists.%s". ^[r2:main:0x00405a0f]
Stage 3 — Encrypted Sidecar Loading
monitor.sym (5.98 MB, entropy 7.95) is strongly consistent with encrypted payload data. sampler.xml (34 KB, entropy 5.35) is lower-entropy, consistent with a configuration or decryption-key file. Neither filename appears as a plaintext string in FrameworSwitch32.exe, suggesting the sidecar names may be hardcoded in .data or resolved dynamically. The Log.dll helper provides structured logging, indicating the authors care about operational telemetry.
Stage 4 — cmd.exe Pipe Execution (fcn.004026c0)
A distinct function at 0x004026c0 (2,492 bytes) creates anonymous pipes via CreatePipe, builds a STARTUPINFO with redirected std handles, and spawns cmd.exe. ^[r2:fcn.004026c0] This pattern is consistent with a reverse-shell or command-execution backdoor capability. It is not invoked from the main() flow visible in the disassembly, suggesting it may be triggered by:
- A command received from the decrypted
monitor.sympayload - An IPC message sent by a companion process (e.g.,
BarClientView.exe) - A callback from
Log.dllunder specific conditions
Decompiled Behavior
Notable Functions
| Address | Size | Description |
|---|---|---|
main (0x004058b0) |
528 | Entry logic: Clean-Edashi gate → mutex check → BarClientView.exe launch |
fcn.004026c0 |
2,492 | Pipe creation + cmd.exe spawn with redirected I/O |
fcn.004063a0 |
3,619 | Window message handler; sends WM_USER+0x4a with 1307-byte payload to existing window |
fcn.00405340 |
1,386 | Path/string construction helper |
fcn.00405ac0 |
897 | Early initialization called before gate check |
Key Imports and Their Roles
KERNEL32.dll:CreatePipe,PeekNamedPipe,CreateProcessW— pipe-based command execution ^[r2:fcn.004026c0]USER32.dll:FindWindowW,SendMessageW,PostMessageW— IPC to existing instance ^[r2:main]SHELL32.dll:ShellExecuteW— launchBarClientView.exe^[r2:main]SHLWAPI.dll:PathFileExistsW— file-existence gate ^[r2:main]log.dll:GenericLogImpl— structured logging telemetry ^[r2:main:0x004058fb]
Resource Section
The .rsrc section (586 KB, entropy 3.79) contains 17 RT_ICON groups, RT_GROUP_ICON, RT_VERSIONINFO, and RT_MANIFEST resources. ^[pefile.txt] The VS_VERSIONINFO reports:
- ProductName:
startbc - FileVersion:
1.0 - InternalName:
startbc - OriginalFilename:
startbc.exeThis masquerades as a benign "startbc" application.
C2 Infrastructure
No static C2 indicators recovered. No hardcoded URLs, IPs, domains, or mutex names (beyond the single-instance GUID) appear in plaintext. Network connectivity, if any, is expected to be:
- Encrypted inside
monitor.symand decrypted at runtime - Communicated via a companion process (
BarClientView.exe) - Or relayed through the
Log.dlltelemetry channel
The BarClientLocatePassport export name in the strings hints at a "locate passport" function — possibly a geo-location or system-fingerprinting module that would beacon to a C2 server.
Interesting Tidbits
-
Divergent build morph: Unlike all prior GhostPulse siblings (x64 Qt5 payloads with EaseUS masquerade), this sample is x86 MSVC C++ with a completely different masquerade identity ("YHClient" / "startbc"). The outer SFX packaging pattern is the only family fingerprint shared. ^[entities/ghostpulse.md]
-
"YHClient" attribution clue: PDB paths reference
D:\slave\workspace\YHClient\.... "YH" is a common Chinese abbreviation (银河 Yínhé, 银汉 Yínhàn). The "slave" directory name suggests a CI/CD build server or Jenkins-like environment. -
"Clean Edashi" gate: The conditional abort string "Execute Clean Edashi finished!" uses a Japanese given name (江戸橋 Edashi / 枝 Edashi). This may be a developer artefact, a code-name for an uninstall/cleanup routine, or an anti-analysis breadcrumb.
-
Virtual disk bus driver reference: Source path
ControlvDiskBus.cppin the strings suggests the payload or a companion module includes virtual-disk or storage-filter-driver functionality — potentially used for hiding files or maintaining persistence. -
Multilingual UI support: 31 locale strings (zh-CHS, ar-SA, de-DE, en-US, fr-FR, ja-JP, ko-KR, ru-RU, etc.) in the
.rsrcsection indicate international deployment or a product built for global distribution. ^[r2:rabin2-z] -
Log.dll operational telemetry: The helper DLL exports
LogSetOutputLevelandLogSetOption, suggesting configurable log verbosity and output redirection — unusual for commodity malware and more consistent with a managed tool or RAT.
How To Mess With It (Homelab Replication)
Reproducing the dropper pattern:
- Build a small MSVC C++ Win32 GUI app (VS 2019+, x86) that checks a mutex, then launches a hardcoded companion EXE via
ShellExecuteW - Add an IPC path:
FindWindowW+SendMessageW(WM_USER+0x4a, ...)for single-instance coordination - Include a conditional abort gate that logs and exits (mimic "Clean Edashi")
- Build a helper DLL with
GenericLogImplexport and structured logging - Package with 7-Zip SFX (
7zSfxMod) withRunProgram="%%T\\YourApp.exe"andProgress=no - Bundle a large encrypted sidecar file with >7.5 entropy alongside a smaller config file
Detection target for your own VMs: The resulting binary will have:
- A 7-Zip SFX outer stub with
RunProgramconfig - An inner x86 PE importing a custom
log.dll - A
.rsrcsection with 17+ icons and multilingual locale tables - Companion files with >7.5 entropy and non-standard extensions (.sym, .xml)
Deployable Signatures
YARA Rule — GhostPulse SFX Loader (x86 YHClient Morph)
rule GhostPulse_SFX_YHClient_x86 {
meta:
description = "Detects GhostPulse family 7-Zip SFX dropper with x86 YHClient inner payload"
author = "PacketPursuit"
date = "2026-08-06"
sha256 = "94db5892d51fa7f24c6f406591d5cc143f48f3f9f576c66d36a8682e3950102b"
strings:
$sfx1 = "7ZSfxMod" ascii
$sfx2 = "7-Zip SFX" wide
$runprog = /RunProgram="\\%%T\\\\[A-Za-z]{5,30}\.exe"/ wide
$yhclient = "YHClient" ascii
$startbc = "startbc.pdb" ascii
$logdll = "log.dll" ascii
$monitor = ".monitor.sym" ascii
$barclient = "BarClientView.exe" ascii
$passport = "BarClientLocatePassport" ascii
$mutex = "{FA531CC1-0497-11d3-A180-00105A276C3E}" ascii
condition:
uint16(0) == 0x5A4D and
filesize > 3MB and filesize < 15MB and
($sfx1 or $sfx2) and
$runprog and
(any of ($yhclient, $startbc, $logdll, $monitor, $barclient, $passport, $mutex))
}
YARA Rule — FrameworSwitch32 Inner Payload
rule GhostPulse_YHClient_Inner {
meta:
description = "Detects GhostPulse x86 inner payload with YHClient masquerade"
author = "PacketPursuit"
date = "2026-08-06"
sha256 = "94db5892d51fa7f24c6f406591d5cc143f48f3f9f576c66d36a8682e3950102b"
strings:
$pdb = "D:\\slave\\workspace\\YHClient\\Release\\startbc.pdb" ascii
$src1 = "D:\\slave\\workspace\\YHClient\\startbc\\startbc.cpp" ascii
$src2 = "D:\\slave\\workspace\\YHClient\\startbc\\SecPolicy.cpp" ascii
$src3 = "D:\\slave\\workspace\\YHClient\\CommFile\\driver\\ControlvDiskBus.cpp" ascii
$passport = "BarClientLocatePassport" ascii
$device = "\\\\.\\ControlDevice" ascii
$clean = "Execute Clean Edashi finished!" ascii
$log = "GenericLogImpl" ascii
condition:
uint16(0) == 0x5A4D and
pe.machine == pe.MACHINE_I386 and
3 of them
}
Behavioral Hunt Query (Sigma)
title: GhostPulse YHClient x86 Payload Execution
description: Detects the execution of GhostPulse inner payload FrameworSwitch32.exe or its BarClientView.exe companion
logsource:
category: process_creation
product: windows
detection:
selection:
CommandLine|contains:
- 'FrameworSwitch32.exe'
- 'BarClientView.exe'
selection_mutex:
- MutexName|contains: '{FA531CC1-0497-11d3-A180-00105A276C3E}'
selection_pipe:
ParentImage|endswith:
- 'FrameworSwitch32.exe'
Image|endswith:
- 'cmd.exe'
CommandLine|contains: 'cmd.exe'
condition: selection or selection_mutex or selection_pipe
falsepositives:
- Unknown
level: high
IOC List
| Indicator | Type | Value |
|---|---|---|
| SHA-256 | Hash | 94db5892d51fa7f24c6f406591d5cc143f48f3f9f576c66d36a8682e3950102b |
| Inner payload SHA-256 | Hash | (requires extraction from SFX) |
| Mutex | Mutex | {FA531CC1-0497-11d3-A180-00105A276C3E} |
| Sidecar payload | File | %TEMP%\monitor.sym (5.98 MB, entropy ~7.95) |
| Sidecar config | File | %TEMP%\sampler.xml (34 KB, entropy ~5.35) |
| Inner executable | File | %TEMP%\FrameworSwitch32.exe |
| Companion executable | File | %TEMP%\BarClientView.exe (launched by inner payload) |
| Helper DLL | File | %TEMP%\Log.dll |
| Device path | String | \\.\ControlDevice |
| Build path | String | D:\slave\workspace\YHClient\Release\startbc.pdb |
Behavioral Fingerprint Statement
This binary is a 7-Zip SFX archive that silently extracts to %TEMP% and launches FrameworSwitch32.exe. The inner x86 PE checks a single-instance mutex ({FA531CC1-0497-11d3-A180-00105A276C3E}); if already running, it finds the existing window and sends WM_USER+0x4a with a 1307-byte payload. Otherwise it constructs a path to BarClientView.exe, verifies existence via PathFileExistsW, and launches it via ShellExecuteW. A secondary function creates anonymous pipes and spawns cmd.exe with redirected I/O, suggesting reverse-shell capability. The payload carries a custom Log.dll helper for structured telemetry and is accompanied by a 6 MB encrypted sidecar (monitor.sym) and a 34 KB config file (sampler.xml). Build artefacts reference a Chinese-origin "YHClient" product with virtual-disk driver components.
Detection Signatures
| Technique | ATT&CK ID | Evidence |
|---|---|---|
| Single-instance mutex gating | T1497.001 | OpenMutexW("{FA531CC1-0497-11d3-A180-00105A276C3E}") ^[r2:main] |
| Windows Command Shell | T1059.003 | CreatePipe → CreateProcessW("cmd.exe") ^[r2:fcn.004026c0] |
| Shared Modules | T1129 | log.dll imported at runtime ^[pefile.txt] |
| Signed Binary Proxy Execution | T1218.011 | ShellExecuteW("open", "BarClientView.exe") ^[r2:main] |
| Ingress Tool Transfer | T1105 | Sidecar files (monitor.sym, sampler.xml) extracted via SFX ^[sfx-config.json] |
| File and Directory Discovery | T1083 | PathFileExistsW on companion EXE ^[r2:main] |
| Virtualization/Sandbox Evasion | T1497 | Conditional abort gate (bit 0x4000) ^[r2:main] |
| Process Injection (inferred) | T1055 | Pipe-based cmd.exe spawn capability ^[r2:fcn.004026c0] |
References
- ghostpulse — Family entity page with full cluster description
833bffd0— Prior GhostPulse analysis (x64 Qt5 EaseUS masquerade variant) ^[/intel/analyses/833bffd0ff2291001e0cb62f529cf947ba2753fa5888820848a2014eda2dc334.html]943cf1eb— Confirmed twin of833bffd0^[/intel/analyses/943cf1ebeb089abcd2e6ff0c2bfefa4631855948ab3ef3811cba1c635aa389d1.html]
Provenance
- File type:
filev5.44 — PE32 executable (GUI) Intel 80386, for MS Windows, 4 sections ^[file.txt] - PE headers:
pefile2023.2.0 — full DOS/NT/optional headers, section entropy, import table ^[pefile.txt] - Strings:
stringsv2.42 — 11,290 strings recovered ^[strings.txt] - FLOSS: Failed (CLI argument error) ^[floss.txt]
- capa: Failed (missing signatures directory) ^[capa.txt]
- binwalk: 7-zip archive data at offset 0x2DF4F ^[binwalk.txt]
- radare2: r2 v5.9.4 —
rabin2 -I,rabin2 -z,r2 -Adisassembly ofmain,fcn.004026c0,fcn.004063a0^[rabin2-info.txt] ^[r2:*] - 7-Zip extraction: 7-Zip 23.01 — 6 files extracted from offset 188,239 ^[terminal:7z-extract]
- Entropy analysis: Custom Python using
math.log2andcollections.Counter^[terminal:entropy-check]