PhantomVault — PHANTOMPULSE Blockchain-C2 RAT via Obsidian

An intrusion set (Elastic REF6598) that abuses the legitimate Obsidian note-taking app — via DLL side-loading — to launch PHANTOMPULSE, a modular RAT whose C2 configuration is resolved from a public blockchain (smart-contract / EtherHiding-style resilient C2) rather than a fixed domain. Defensive hunt & harden pack — no offensive code.
Threat
PhantomVault / REF6598 · PHANTOMPULSE RAT
Severity
HIGH · RESILIENT-C2 RAT
Type
RAT · DLL side-load · blockchain C2
Abused App
Obsidian (legit note app) — side-loaded DLL
C2
Blockchain smart-contract resolver (EtherHiding-style)
Version
v0.3 · 2026-06-12
Author
HuntPack
01

Executive Summary

PhantomVault (Elastic Security Labs intrusion set REF6598) deploys PHANTOMPULSE, a modular remote-access trojan, by abusing the trusted Obsidian markdown note-taking application. The actor places a malicious DLL alongside the legitimate, signed Obsidian executable so that launching Obsidian side-loads the attacker DLL (DLL search-order hijack) — the signed app provides cover, and the malicious code runs inside a trusted process.

PHANTOMPULSE's most notable trait is blockchain-based C2 resolution: instead of hard-coding a C2 server, the implant reads its current C2 / next-stage configuration from data stored on a public blockchain (smart contract / on-chain payload, EtherHiding-style). This makes the C2 cheap to rotate and extremely resilient to takedown — there is no single domain or IP to sinkhole. Once resolved, the RAT performs command execution, file operations, staging, and exfiltration over standard web protocols.

Defender priority: The durable signals are the DLL side-load into Obsidian (Q1 — Obsidian loading an unsigned/unexpected DLL from a user-writable path) and the blockchain-C2 resolution traffic (Q4/N3 — endpoints reaching public blockchain RPC/gateway nodes from a non-wallet process). Because C2 is on-chain, do not anchor on a single domain — anchor on the side-load behavior and the anomalous blockchain-RPC egress.

02

Source Review & Web Hunter Notes

TierSourceKey FindingCarry
1 · Vendor researchElastic Security Labs — REF6598 / PHANTOMPULSEObsidian DLL side-load; modular RAT; blockchain-based C2 resolutionyes
2 · TechniqueEtherHiding / on-chain C2 reporting (Google/Mandiant)Blockchain smart contracts as resilient, takedown-resistant C2/payload storesyes
2 · TechniqueDLL search-order hijack literature (MITRE T1574.001/.002)Side-loading trusted apps to run malicious DLLs under coverpartial

Decisions: behavior-first because there is no stable C2 atom (on-chain resolver); anchor on the Obsidian side-load (trusted-process cover) and the blockchain-RPC egress from a non-wallet process; treat smart-contract/wallet-RPC reachability from servers/workstations without a business need as anomalous; module hashes rotate, so the side-load + resolver chain is the durable surface.

03

Hunt Brief & Attack Chain

Working hypothesis: The actor stages a malicious DLL next to a legitimate Obsidian install (or a portable copy); launching Obsidian side-loads it, spawning PHANTOMPULSE, which resolves C2 from a blockchain smart contract and then runs hands-on RAT operations.

StepBehaviorTelemetryHunt Angle
1 · DeliveryTrojanized/portable Obsidian + malicious DLL staged to a user pathfile; ProcessRollup2Q2; N1
2 · Side-loadObsidian.exe loads an unsigned/unexpected DLLmodule load; ProcessRollup2Q1; N2
3 · PHANTOMPULSERAT runs inside the trusted process; spawns childrenProcessRollup2Q3
4 · C2 resolveReads C2 config from a blockchain RPC/gatewayNetworkConnectIP4; DNSQ4; N3
5 · PersistenceRun key / scheduled task / startup to relaunch Obsidian chainregistry; taskQ5
6 · ActionsExec, file ops, staging, exfil over web protocolsProcessRollup2; netQ3 / Q6

Affected surface & telemetry

SurfaceRequired TelemetryPriorityGap Risk
Workstations (Obsidian users)Module-load + process lineageCriticalMedium — needs module-load telemetry
EgressProxy/DNS + netflow to blockchain RPCHighMedium — on-chain resolver
PersistenceRun keys / scheduled tasksMediumLow
App inventoryObsidian install locations + signaturesMediumMedium — portable copies
04

Consolidated IOC Table

C2 is resolved on-chain — there is no durable domain/IP atom. The Obsidian DLL side-load and the blockchain-RPC egress from a non-wallet process are the durable behaviors. Copy-ready blocks in §9.
TypeValueConfActionContext
BehaviorObsidian.exe loading an unsigned/unexpected DLL from a user pathhighdetectSide-load — flagship
BehaviorBlockchain RPC/gateway egress from a non-wallet processmediumhuntOn-chain C2 resolve
MalwarePHANTOMPULSE modular RAT (runs inside Obsidian)mediumhuntImplant
BehaviorPersistence relaunching the Obsidian chain (Run key / task)mediumhuntPersistence
FilePortable/relocated Obsidian + sideloaded DLL outside Program FilesmediumhuntStaging
05

ATT&CK Mapping

TacticTechniqueObserved BehaviorQuery / Control
Execution / Defense EvasionT1574.002 — DLL side-loadingObsidian side-loads a malicious DLLQ1; N2
Defense EvasionT1036 — Masquerading (trusted-process cover)RAT runs inside signed ObsidianQ1, Q3
Command & ControlT1071 / T1102 — Web service / dead-drop (blockchain)C2 config resolved on-chainQ4; N3
PersistenceT1547.001 / T1053.005 — Run key / scheduled taskRelaunch of the Obsidian chainQ5
ExecutionT1059 — Command/script interpreterRAT spawns shells / toolingQ3
Collection / ExfilT1005 / T1041 — Local data / C2 exfilFile ops + exfil over webQ6
06

Native Audit-Log Hunts

HuntSourceLogicResponse
N1 · Obsidian inventorySoftware / file inventoryObsidian installs outside the standard path; portable copies; unexpected sibling DLLsVerify signature/origin
N2 · Side-load module loadSysmon 7 (Image Load) / EDRObsidian.exe loading an unsigned DLL from a user-writable pathIsolate; pull the DLL
N3 · Blockchain-RPC egressProxy / DNS / netflowConnections to public blockchain RPC/gateway nodes from non-wallet processesBlock; identify host
N4 · PersistenceRegistry (Run) / Task SchedulerRun keys / tasks pointing at an Obsidian copy in a user pathRemove; investigate
07

CrowdStrike LogScale CQL Hunt Queries

Pick your tenant's cloud first — every "Open in Falcon" button below uses this selection.
Module-load hunts use ImageLoad/ClassifiedModuleLoad events — verify field names in your sensor schema. C2 is on-chain, so Q4 keys on blockchain-RPC reachability from a non-wallet process; maintain an allow-list of sanctioned crypto/wallet apps to suppress FPs.
Q1 · Obsidian side-loading an unsigned/user-path DLL
CONF HIGHFP LOWCOST LOW

Looks for: Obsidian.exe loading a DLL from a user-writable path (the side-load). Accomplishes: catches the trusted-process cover. FP: low — Obsidian's own DLLs load from its install dir; tune to your module-load schema.

// HUNT: PHANTOMPULSE DLL side-load into Obsidian
// MITRE: T1574.002, T1036 | CONF: high  FP: low  COST: low
// FP NOTES: genuine Obsidian DLLs load from its install dir; flag user-path/unsigned
#event_simpleName=/ImageLoad|ClassifiedModuleLoad|ModuleLoadFromMemory/
| FileName=/^Obsidian\.exe$/i
| ImageFileName=/\\(Temp|AppData|Downloads|Users\\Public|ProgramData)\\.+\.dll$/i
| table([@timestamp, ComputerName, UserName, FileName, ImageFileName, SHA256HashData], limit=200)
Q2 · Portable Obsidian + sibling DLL staged to a user path
CONF MEDFP MEDCOST LOW

Looks for: Obsidian.exe running from a non-standard path (portable/relocated copy used for side-load staging). FP: some legit portable use — correlate to Q1.

// HUNT: Obsidian running from a non-standard (staging) path
// MITRE: T1574.002 | CONF: medium  FP: medium  COST: low
// TUNING: baseline legit Obsidian install paths; flag user/temp/download dirs; correlate to Q1
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| FileName=/^Obsidian\.exe$/i
| ImageFileName=/\\(Temp|Downloads|Users\\Public|ProgramData)\\/i
| table([@timestamp, ComputerName, UserName, ImageFileName, CommandLine], limit=200)
Q3 · PHANTOMPULSE — Obsidian spawning shells / tooling
CONF MED-HIGHFP LOW-MEDCOST LOW

Looks for: Obsidian.exe (a note app) spawning shells/LOLBins/recon — abnormal for a markdown editor. Accomplishes: the RAT running inside the trusted process. FP: low — Obsidian rarely spawns cmd/powershell.

// HUNT: PHANTOMPULSE child execution from Obsidian
// MITRE: T1059, T1036 | CONF: med-high  FP: low-med  COST: low
// FP NOTES: a note app should not spawn cmd/powershell/recon tooling
#event_simpleName=/ProcessRollup2|SyntheticProcessRollup2/
| ParentBaseFileName=/^Obsidian\.exe$/i
| FileName=/^(cmd|powershell|pwsh|wscript|cscript|rundll32|regsvr32|mshta|whoami|net|net1|nltest|curl)\.exe$/i
| table([@timestamp, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine], limit=200)
Q4 · Blockchain-RPC C2 resolution (non-wallet process)
CONF MEDFP MEDCOST MED

Looks for: DNS for public blockchain RPC/gateway providers from a process that is not a sanctioned wallet/crypto app (the on-chain C2 resolve). FP: medium — allow-list sanctioned crypto apps; tune the provider list to current intel.

// HUNT: on-chain C2 resolution via blockchain RPC/gateway
// MITRE: T1102, T1071 | CONF: medium  FP: medium  COST: med
// TUNING: allow-list sanctioned wallet/crypto apps; tune the provider domain list
#event_simpleName=DnsRequest
| DomainName=/(infura\.io|alchemy\.com|ankr\.com|bsc-dataseed|binance\.org|cloudflare-eth\.com|llamarpc\.com|publicnode\.com|quiknode\.pro|drpc\.org)/i
| ContextBaseFileName!=/^(metamask|exodus|electrum|ledger.*|trust.*|coinbase.*)\.exe$/i
| table([@timestamp, ComputerName, ContextBaseFileName, DomainName], limit=200)
Q5 · Persistence relaunching the Obsidian chain
CONF MED-HIGHFP LOW-MEDCOST LOW

Looks for: Run keys / scheduled tasks pointing at an Obsidian copy in a user/temp path. FP: low-med — legit Obsidian auto-start is from its install dir, not a temp path.

// HUNT: persistence relaunching the side-loaded Obsidian
// MITRE: T1547.001, T1053.005 | CONF: med-high  FP: low-med  COST: low
// TUNING: legit auto-start is from the install dir; flag user/temp-path Obsidian
#event_simpleName=/AsepValueUpdate|ScheduledTaskRegistered|RegGenericValueUpdate/
| RegStringValue=/Obsidian\.exe/i
| RegStringValue=/\\(Temp|AppData|Downloads|Users\\Public|ProgramData)\\/i
| table([@timestamp, ComputerName, UserName, RegObjectName, RegStringValue], limit=200)
Q6 · RAT egress from inside Obsidian
CONF MEDFP MEDCOST MED

Looks for: outbound connections attributed to Obsidian.exe beyond its normal sync/update endpoints (RAT C2/exfil under cover). FP: medium — baseline Obsidian's legit sync/update hosts.

// HUNT: anomalous egress attributed to Obsidian.exe
// MITRE: T1071, T1041 | CONF: medium  FP: medium  COST: med
// TUNING: baseline Obsidian sync/update endpoints; flag the remainder
#event_simpleName=NetworkConnectIP4
| ImageFileName=/\\Obsidian\.exe$/i
| in(RemotePort, values=[443, 80, 8080, 8443])
| groupBy([ComputerName, RemoteAddressIP4, RemotePort], function=count())
| table([ComputerName, RemoteAddressIP4, RemotePort, _count], limit=200)
08

CrowdStrike Custom IOA Recommendations

IOA NameField PatternsBenign ExclusionsDeployment Path
PhantomVault — Obsidian side-loadImage load: Obsidian.exe + DLL from %Temp%/%AppData%/DownloadsGenuine Obsidian install dir (allow)Endpoint Security → Custom IOA → Image Load, Detect+Block
PhantomVault — Obsidian spawns shellParent Obsidian.exe; Child cmd/powershell/rundll32None (note app should not)Custom IOA → Process Creation, Detect+Block
Q1 and Q3 are strong promotions — a markdown editor side-loading a user-path DLL or spawning a shell is near-unambiguous. Q4 (blockchain-RPC) stays a tuned hunt — keep a sanctioned-crypto allow-list.
09

Machine-Readable IOC Appendix

Grouped IOC Quick-Copy

One-click blocks for detection. C2 is on-chain (no durable domain) — behavior is the surface. Add per-incident atoms (DLL hashes, contract/wallet addresses, resolved C2) during triage.

Behavioral Signaturesdetection logic
Obsidian.exe loading an unsigned/unexpected DLL from %Temp%/%AppData%/Downloads/ProgramData (side-load)
Obsidian.exe running from a non-standard (user/temp/download) path
Obsidian.exe spawning cmd/powershell/rundll32/recon tooling (a note app should not)
DNS to public blockchain RPC/gateway from a non-wallet process (on-chain C2 resolve)
Run key / scheduled task pointing at an Obsidian copy in a user/temp path
Anomalous egress attributed to Obsidian.exe beyond its sync/update endpoints
Named Tooling / AttributionREF6598
PhantomVault / REF6598  # Elastic intrusion set
PHANTOMPULSE            # modular RAT delivered via Obsidian DLL side-load
Abused app: Obsidian (legitimate markdown note-taking application)
Technique: DLL side-loading (T1574.002) into a signed, trusted process
C2: blockchain smart-contract resolver (EtherHiding-style on-chain config)
# No durable C2 domain/IP -- the config is read on-chain and rotated cheaply.
Blockchain-RPC Watchliston-chain C2
# Public RPC/gateway providers to watch from NON-wallet processes (tune to your intel):
infura.io
alchemy.com
ankr.com
bsc-dataseed*.binance.org
cloudflare-eth.com
llamarpc.com
publicnode.com
quiknode.pro
drpc.org
# Allow-list sanctioned wallet/crypto apps (metamask/exodus/ledger/etc.) before alerting.
Hardening / Blockdefense-in-depth
App control (WDAC/AppLocker): only allow Obsidian from its signed install dir
Block DLL loads from user-writable paths into signed apps where feasible
Promote Q1 (Obsidian side-load) + Q3 (Obsidian spawns shell) to Detect+Block IOAs
Egress: block/alert blockchain RPC from non-wallet processes (allow-list crypto apps)
Restrict portable-app execution from Downloads/Temp; default-deny user-path EXEs
Inventory Obsidian installs + signatures; remove unsanctioned portable copies
10

Hardening — Tiered & Deployable

Kill the side-load surface, then cut the on-chain C2 path.

Immediate — Kill the side-load
  • App control: allow Obsidian only from its signed install dirM1038. Defeats the portable-copy side-load.
  • Promote Q1 (side-load) + Q3 (Obsidian spawns shell) to Detect+BlockM1040.
  • Block DLL loads from user-writable paths into signed appsM1044. Breaks T1574.002.
  • Restrict portable-app execution from Downloads/TempM1038.
Near term — Cut the on-chain C2 (pilot first)
  • Egress: block/alert blockchain RPC from non-wallet processesM1037. Allow-list sanctioned crypto apps (Q4/N3).
  • Monitor Run keys / tasks pointing at user-path ObsidianM1028. Feeds Q5/N4.
  • Inventory + signature-verify Obsidian installsM1033. Removes unsanctioned copies (N1).
Strategic — Reduce trusted-app abuse surface
  • Application allowlisting fleet-wide; default-deny user-path executionM1038.
  • Crypto/wallet-app governance: define which hosts may reach blockchain RPCM1037.
  • Module-load / image-load telemetry coverage (Sysmon 7 / EDR)M1047. Enables Q1/N2.
11

Containment Runbook

PhaseActionsOwnerEvidence
IsolateNetwork-contain the host; preserve the Obsidian copy + sideloaded DLL + any resolved C2 / contract addressSOC L2Containment timestamp; Q1 module-load event; DLL
TriageMap side-load → PHANTOMPULSE → on-chain resolve → C2; capture the blockchain RPC + contract/wallet addresses; scope persistenceIRModule-load timeline; resolved C2; addresses
EradicateRemove the sideloaded DLL + portable Obsidian + persistence; block the resolved C2 and RPC path; reset credsIRRemoval log; cred reset
RecoverReimage if hands-on RAT control occurred; reinstall Obsidian from a verified source if neededIR + ITRebuild ticket
HardenApp control on Obsidian; promote Q1/Q3; block blockchain RPC from non-wallet processesDetection EngIOA enabled; egress rule
12

Detection Coverage Map & Validation

TechniqueBehaviorCQLIOACoverage
T1574.002Obsidian DLL side-loadQ1, Q2IOA-1Good + app control
T1036 / T1059RAT inside Obsidian (spawns shell)Q3IOA-2Good
T1102 / T1071On-chain C2 resolutionQ4Partial + proxy (N3)
T1547.001 / T1053.005PersistenceQ5Good
T1071 / T1041RAT egress / exfilQ6Partial baseline Obsidian egress
Initial delivery of the trojanized ObsidianGAP web/email + inventory (N1)

Validation gates: (1) confirm image-load + process lineage + DNS/proxy telemetry; (2) baseline genuine Obsidian install paths + its sync/update endpoints + sanctioned crypto apps; (3) lab-test a benign Obsidian launch (must NOT fire Q1/Q3) and a benign wallet RPC call (must NOT fire Q4 — allow-listed); (4) enable app control + promote Q1/Q3. No single C2 atom — anchor on behavior.

13

Hunt Summary Ticket

TITLE:        Hunt — PhantomVault / PHANTOMPULSE (Obsidian side-load, blockchain C2)
SEVERITY:     High (resilient on-chain-C2 RAT in a trusted process)
SCOPE:        Workstations with Obsidian; egress; persistence
HYPOTHESIS:   Malicious DLL staged next to Obsidian -> side-load -> PHANTOMPULSE RAT ->
              resolves C2 from a blockchain smart contract -> hands-on exec/file ops/exfil.
QUERIES RUN:  Q1 Obsidian side-load (IOA) | Q2 portable Obsidian staging | Q3 Obsidian spawns
              shell (IOA) | Q4 blockchain-RPC C2 resolve | Q5 persistence | Q6 anomalous egress
              + Native N1-N4 (Obsidian inventory, side-load module load, blockchain egress, persistence)
DO FIRST:     App control on Obsidian; Q1, Q3 -- escalate any side-load/shell-spawn hit
FINDINGS:     <pending analyst execution>
GAPS:         Initial delivery of the trojanized Obsidian; on-chain C2 has no durable atom
ACTIONS:      App control (signed Obsidian only); block user-path DLL loads into signed apps;
              promote Q1/Q3; block blockchain RPC from non-wallet processes; inventory Obsidian
OWNER:        HuntPack
VERSION:      v0.3 - 2026-06-12
14

Changelog

v0.52026-07-24CQL correctness pass. All table() calls now carry an explicit row limit: the default is 200 and truncation is silent, so a capped result was indistinguishable from a complete one. Atomic-IOC sweeps (filters over 5+ hashes or C2 IPs) use limit=max so a wide infection is never silently under-scoped; behavioural hunts use limit=200, where exceeding the cap indicates the query needs tuning. Where present, event names that do not exist in the Falcon data model were corrected (e.g. ServiceInstalled is a Sysmon concept, not a Falcon event; ElfFileWritten is ELFFileWritten) — such queries could never return a row. No detection logic, fields, or IOCs changed.
v0.42026-06-29CQL syntax review (crowdstrike-logscale-v3): replaced regex-on-numeric RemotePort with in() (Q6).
v0.32026-06-12Re-hunt + reformatted to the review-v2 gold layout (fixed left-sidebar scrollspy TOC, collapsible, cloud selector inside the CQL section, per-card Copy/Open-in-Falcon, Grouped IOC Quick-Copy grid, coverage+validation, .ticket). Refreshed from Elastic REF6598: PHANTOMPULSE modular RAT delivered by DLL side-load into Obsidian, blockchain (smart-contract) C2 resolution (EtherHiding-style), persistence + RAT egress under trusted-process cover. 6 CQL + 4 native hunts, 2 IOA candidates; behavior-anchored (no durable C2 atom).
v0.12026-05-14Initial pack: PhantomVault overview + hunts. Pre-gold top-bar layout.
15

References

TierSourceUsed For
1Elastic Security Labs — PhantomVault / REF6598Obsidian side-load, PHANTOMPULSE RAT, blockchain C2 resolution
2Google / Mandiant — EtherHiding (on-chain C2/payloads)Blockchain smart contracts as resilient C2/payload stores
2MITRE ATT&CK T1574.002 — DLL Side-LoadingSide-loading technique mapping

HuntPack v0.3 · PhantomVault / PHANTOMPULSE · Generated 2026-06-12 · Defensive use only — no offensive code. C2 is resolved on-chain, so there is no durable domain to block — anchor on the Obsidian DLL side-load and anomalous blockchain-RPC egress. Validate module-load field names and maintain a sanctioned-crypto allow-list before promoting any query.