typeanalysisfamilydolphinconfidencehighcreated2026-05-30updated2026-05-30perustinfostealerratc2-protocolpersistencedefense-evasiondiscoverylateral-movementexfiltrationanti-vmanti-debugcode-injectionimpactsigning
SHA-256: ca6be0bf2f87f1998bfe4ba762d59bfa43a574fb011b4d19d587d83763c5c64f

dolphin: ca6be0bf — Rust x64 polymorphic RAT/stealer with 80+ task types, WebSocket C2, masquerading as NVIDIA Display Container LS

Executive Summary

A 5.9 MB Rust x64 PE32+ GUI binary, internally self-identifying as dolphin. It is a builder-configurable polymorphic RAT/infostealer with a WebSocket-over-TLS C2 at dolphin.dark-matter-analytics.com:32768, an embedded AES-GCM encrypted configuration, and an extensive tasking surface (~80 distinct ServerMessage commands). It masquerades as "NVIDIA Display Container LS" (version 560.81), mashes browser credentials via DPAPI, injects JavaScript into Electron apps (Bitwarden, Exodus, Ledger, Atomic, Telegram, Discord), targets 200+ gaming clients, and runs a crypto-address clipper. Anti-analysis includes anti-VM, anti-debug, and self-morphing to a new PE in TEMP (poly / meta / ultra modes). Static-only: CAPE was unavailable for x64 Windows at time of analysis.^[dynamic-analysis.md]

What It Is

Field Value
SHA-256 ca6be0bf2f87f1998bfe4ba762d59bfa43a574fb011b4d19d587d83763c5c64f
Size 5,949,440 bytes
Type PE32+ executable (GUI) x86-64, 7 sections^[file.txt]
Compiler Rust — rustc 59807616e1fa2540724bfbac14d7976d7e4a3860, MSVC linker 14.44 (Visual Studio 2022)^[rabin2-info.txt]^[exiftool.json]
Crate stack tokio 1.52.1, tokio-tungstenite 0.21.0, serde_json 1.0.149, chrono 0.4.44, zip 0.6.6, tracing-core 0.1.36, bcrypt (via bcryptprimitives.dll), gdiplus (screenshots)^[strings.txt:10513]^[strings.txt:10537]^[strings.txt:10571]^[strings.txt:10580]
PDB java_update_scheduler_557655.pdb^[rabin2-info.txt]
VersionInfo NVIDIA Display Container LS — product_name 560.81, FileDescription hstsvc, LegalCopyright (c) 2024 NVIDIA Corporation^[pefile.txt]
Signed false^[rabin2-info.txt]
IAT ~350 imports across KERNEL32, ADVAPI32, CRYPT32, WS2_32, NTDLL, USER32, GDI32, GDIPlus, OLE32, OLEAUT32, IPHLPAPI, MPR, SHELL32, SETUPAPI, MFPlat, MFReadWrite, WINMM, POWRPROF, SECUR32, NETAPI32, WTSAPI32, WEVTAPI, BCRYPT^pefile.txt
Packing None — native Rust binary, no UPX/VMProtect/themida. Section entropies: .xdata3 6.33, .rdata3 5.93, .rsrc0 6.22, .datax 7.97^[pefile.txt]
Config AES-GCM encrypted JSON blob; decrypts via CryptUnprotectData or BCrypt fallback. Hardcoded defaults embedded in binary include C2 host, port, TLS, auth token, morph mode, loot toggles^[strings.txt:14419]^[strings.txt:14455]

The builder produces binaries with toggles for anti_analysis, morph_mode (Off / Poly / Meta / Ultra), melt, deferred_morph, critical_process, block_russian_egress, loot_gaming, loot_messengers, loot_email, loot_vpn, loot_webcam, loot_clipboard, persist, and ~12 UAC-bypass / privilege-escalation methods^[strings.txt:13819]^[strings.txt:13843].

How It Works

Boot & Decryption

On launch the binary attempts to decrypt an embedded config JSON. The decryption path tries CryptUnprotectData (DPAPI) first, then falls back to BCryptGenerateSymmetricKey / BCryptDecrypt with AES-GCM. If decryption fails, a set of plaintext hardcoded defaults is used as fallback^[strings.txt:12070]. The config schema fields are fully self-describing via Serde-derived JSON: server_host, server_port, use_tls, tls_fingerprint, install_path (e.g. appdata), product_name, tag, persistent, anti_analysis, morph_mode, melt, deferred_morph, reconnect_delay_secs, heartbeat_interval_secs, fallback_hosts, dead_drops, cdn_front_domain, asn_bypass_token, ws_auth_token, uac_method, anti_bot, block_russian_egress, and per-loot booleans^[strings.txt:10523]^[strings.txt:14419].

C2 & Tasking

After config decryption, the agent resolves its public IP via a hardcoded list of IP checkers (api.ipify.org, checkip.amazonaws.com, ifconfig.me, icanhazip.com), builds a Hello / TaskAssign handshake over a tokio-tungstenite WebSocket, and sends periodic heartbeats (default 5s). C2 messages are defined by a large ServerMessage adjacently-tagged enum with 80+ variants^[strings.txt:10775]^[strings.txt:18552].

Observable categories:

  • Discovery & System Info: GetSystemInfo, GetPublicIp, Ping, NetworkScan, GetDnsCache, EnvRecon, PrivescScan, ProcessList, ProcessStringScan, ProfilerStart/Stop
  • Credential & Data Theft: BrowserSave, BrowserHttpInterceptStart/Stop, TokenStealAll, EnrichDiscordTokens, WalletInject, WalletExtract, WalletInjectAllExtensions, AppInject, ClipboardGet/Set, KeyloggerStart/Stop, KeyloggerDump, MicCapture, MicStreamStart/Stop, WebcamCapture, ScreenRecordStart/Stop, SmartScreenshotStart/Stop, WifiHarvest, CredManagerDump, FileHunt, HostsRead, HostsAdd, HostsRemove, ExportAll, ExportAllSelective
  • Remote Access & Surveillance: VncStart/Stop, HiddenVncStart/Stop, ShellCommand, ShellInput, ShellClose, ReverseShellConnect, BindShellListen, TtsSpeak, ChatSend, ChatClose, OpenUrl, ScreenRecordStart, PlayAudioChunk
  • Lateral Movement & Propagation: LateralWmi, LateralWinrm, LateralSmb, LateralDeploy, LateralDiscover, UsbSpreadNow, UsbSpreadMonitorStart/Stop
  • Persistence & Privilege Escalation: AddStartupEntry, RemoveStartupEntry, CreateScheduledTask, DeleteScheduledTask, ToggleScheduledTask, ScheduledTaskModified, GetScheduledTasks, UacElevate, UacCheckStatus, UacDisablePolicy, PotatoEscalate
  • Defense Evasion & Anti-Forensics: BotKill, CleanTraces, KillSwitch, WipeEventLogs, WipePrefetch, WipeRecent, WipeTemp, WipePsHist, WipeThumbs, DisableVss, BlockUpdates, UnblockUpdates, BlockDefenderSubmissions, KillDefenderServices, BlockAVUpdatesOnly, ChangeDns, RestoreDns, DefenderExcludePath, DefenderExcludeProcess, DefenderDisableRealtime, DefenderAutoExclude, DefenderListExclusions, DefenderResult
  • Network Pivoting & Proxy: ProxyConnect, ProxyClose, PortForwardStart/Stop, PortForwardList, UPnpProxyStart/Stop, Socks5Start/Stop, RevSocksStart/Stop, RevSocksConnect, MeshRelay, MeshPing
  • Process Manipulation: DllInject, ProcessHollow, ShellcodeInject, ProcessDump, KillProcess, KillProcessByName
  • Misc / Impact: MinerStart/Stop, MinerDeploy, MinerGetStatus, StressStart/Stop, StressStopAll, DownloadTestStart/Stop, DiskSpam, VolumeMax, MessageBoxSpam, SetWallpaperColor, TaskbarToggle, InvertScreen, MouseJitter, SwapMouseButtons, SetMouseSpeed, HideCursor, RotateScreen, FakeFreeze, FakeUpdate, MatrixRain, EarRape, CdTrayTrigger, Bsod, MonitorPower, SelfUpdate, InstallUpdate, RemoveUser, CreateUser

Browser & Wallet Injection

Fully embedded JavaScript payloads hook Electron IPC for:

  • Bitwarden — intercepts login, unlock, masterPassword, setPassword; also hooks webRequest for api.bitwarden.com and vault.bitwarden.com calls^[strings.txt:10802]^[strings.txt:10837]
  • Exodus — hooks exodus.sendTransaction, exodus.signMessage, exodus.unlockWallet, EXODUS_UNLOCK, EXODUS_SEED, EXODUS_EXPORT_PRIVATE_KEY; targets exodus.wallet.seco.json seed files and passphrase.json^[strings.txt:10940]^[strings.txt:10984]
  • Ledger Live — hooks ledger-sign-transaction, ledger-sign-personal, sign-eth, sign-bitcoin; snares swap/buy endpoints and HID transport layer^[strings.txt:10858]^[strings.txt:10865]
  • Atomic Wallet — hooks UNLOCK_WALLET, CREATE_WALLET, IMPORT_WALLET; targets leveldb for raw mnemonic extraction^[strings.txt:11013]
  • Telegram Desktop — extracts tdata directory^[strings.txt:11000]
  • Discord — collects tokens from tokens/discord_tokens.txt, injects into the client, and runs enrichment^[strings.txt:11119]^[strings.txt:13109]

The injection writes collected data to %TEMP%/.dolphin_app.dat, then relays it back to C2 as AppInjectResult / TokenStealResult messages^[strings.txt:10799]^[strings.txt:10854].

Gaming Loot

The binary enumerates 200+ gaming-related process names: every major title from Counter-Strike / Valorant / Apex / Fortnite / PUBG / Call of Duty / Rainbow Six / Destiny / Halo / Rust / DayZ / GTA V / League of Legends / Dota 2 to niche titles like Phasmophobia, Lethal Company, Palworld, Enshrouded, Wuthering Waves, plus launchers (Steam, Epic, GOG Galaxy, EA Desktop, Bethesda, Battle.net, GamePass, Xbox) and overlay/capture tools (Bandicam, Fraps, MSI Afterburner, GeForce Experience, Parsec, Moonlight). The intent is to harvest session tokens, saved credentials, and in-game inventory^[strings.txt:13637]^[strings.txt:13643].

Crypto Clipper

A ClipperStart / ClipperStop task monitors clipboard for cryptocurrency address patterns (BTC, ETH, LTC, XMR, SOL, TRX) and replaces them with attacker-controlled addresses^[strings.txt:10705]^[strings.txt:10780].

Polymorphic Morph / Melt

The svc\polymorph.rs module implements four morph modes^[strings.txt:13843]^[strings.txt:18144]:

  • Poly — rewrites the running binary in-place with a polymorphic variant
  • Meta — creates a morphed copy in TEMP and spawns a child
  • Ultra — same as Meta but with additional anti-signature jitter
  • Melt — deletes the original after child spawn

If deferred_morph is true, persistence is installed first and the morph happens afterward. The module also attempts to writeback a modified image with mismatched CRC to frustrate hash-based blocking^[strings.txt:18296]^[strings.txt:18304].

Anti-Analysis

  • Anti-VM / anti-debug toggles referenced in builder strings; explicit warning strings: "WARNING: ANTI-VM IS ON -- will exit if VM/debugger detected"^[strings.txt:13819]
  • Stack spoofing via svc\stack_spoof.rs^[strings.txt:11078]
  • CheckRemoteDebuggerPresent and IsDebuggerPresent imported^[pefile.txt]
  • Critical-process protection (RtlSetProcessIsCritical, NtRaiseHardError)^[pefile.txt]

Decompiled Behavior

No Ghidra decompilation was performed because the binary is a large native Rust artifact with heavy async runtime boilerplate; capa signatures were also unavailable (signature path missing)^[capa.txt]. Analysis is therefore strings- and import-driven. XREF mapping was not pursued on the 5.9 MB image given the density of tokio/serde macro-generated code, which yields low signal-to-noise in pseudo-C.

C2 Infrastructure

Indicator Value
Primary C2 dolphin.dark-matter-analytics.com:32768^[strings.txt:14455]
Protocol WebSocket over TLS (use_tls: true)^[strings.txt:14460]
WS auth token f58d15520b35a1c619914048470bf17cf262b61cc994b4b8347e71a26d15e729^[strings.txt:14462]
Heartbeat 5 seconds^[strings.txt:14431]
Reconnect delay 10 seconds^[strings.txt:14454]
IP checkers api.ipify.org, checkip.amazonaws.com, ifconfig.me, icanhazip.com^[strings.txt:14455]
Fallback hosts empty in this sample^[strings.txt:14455]
Dead drops empty^[strings.txt:14455]
CDN front empty^[strings.txt:14460]
E2E cipher dolphin-e2e-aes256gcm-v1^[strings.txt:12069]
Named pipes \\.\pipe\dolphin_http_hook_<pid> used for browser HTTP interception^[strings.txt:17469]^[strings.txt:17721]
Log files %TEMP%/dolphin_agent.log, dolphin_agent_fallback.log, dolphin_protection.log^[strings.txt:13709]^[strings.txt:15763]
DLL inject helper dolphin_http_hook.dll / dolphin_http_hook.pdb^[strings.txt:17612]^[strings.txt:17646]
Hardcoded user-agent / branding mfa.svc\discord_token.rs (joke/reference), separator string dQw4w9WgXcQ (YouTube Rickroll ID)^[strings.txt:11119]

No secondary C2 or DGA observed in this sample. The dead_drops and fallback_hosts fields are empty strings in the default config, suggesting a single-tenant builder deployment.

Interesting Tidbits

  • The builder leaks internal project names: hedgehog, pledge, and dolphin all appear as identifier strings^[strings.txt:11535]^[strings.txt:11758]. dolphin is the dominant runtime branding.
  • The masquerade is deep: not just the NVIDIA Display Container LS version resource, but also service-host style log strings like Initializing service configuration...Service started successfully...^[strings.txt:14398] and a fabricated Windows Service Host Runtime v10.0.22621 banner.
  • The builder includes a geographic block toggle: block_russian_egress: true by default^[strings.txt:14421]. This is an OPSEC / localization gate, not an anti-VM check.
  • E2E key exchange uses a custom dolphin-e2e-aes256gcm-v1 protocol, likely a builder-specific handshake to encrypt task traffic inside the already-TLS WebSocket^[strings.txt:12069].
  • The Discord token module path is literally dQw4w9WgXcQ:mfa.svc\discord_token.rs, mixing a Rickroll YouTube ID with the Microsoft MFA service name. Author humour or deliberately misleading string for analysts^[strings.txt:11119].
  • Browser DPI awareness and screen-capture use SetThreadDpiAwarenessContext, EnumDisplayMonitors, GetDeviceCaps, and GDI+ GdipSaveImageToStream for high-resolution screenshots^[pefile.txt].
  • Clipboard monitoring and crypto-address replacement are modular tasks rather than hardcoded loops, implying the builder can ship clipper-only or stealer-only variants.

How To Mess With It (Homelab Replication)

Toolchain: Rust nightly ~2024 (rustc hash 59807616e1fa2540724bfbac14d7976d7e4a3860), Windows x64 target, tokio 1.52, tokio-tungstenite 0.21, serde_json, chrono, bcrypt, gdiplus-sys.

  1. Create a Rust binary crate with tokio::main, tokio-tungstenite WebSocket client, serde_json config struct matching the builder schema.
  2. Embed a JSON config as an AES-GCM ciphertext blob. Decrypt at startup via windows::Win32::Security::Cryptography::CryptUnprotectData (DPAPI) or BCryptDecrypt.
  3. Use winapi / windows-rs for IAT imports: registry, service, process/thread, named pipes, DPAPI, BCrypt.
  4. For browser injection: ship an Electron preload script as a string constant, inject it via CreateRemoteThread or SetWindowsHookEx into the target renderer process.
  5. Enumerate gaming processes by name via CreateToolhelp32Snapshot.
  6. Clipper: monitor WM_CLIPBOARDUPDATE/GetClipboardData, regex-match (bc1|[13])[a-zA-Z0-9]{25,62} for BTC, 0x[a-fA-F0-9]{40} for ETH, etc, and replace with attacker addresses via SetClipboardData.

Verification step: Build a minimal variant with morph_mode: "Off", anti_analysis: false, loot_gaming: true, and run strings on the output. You should see the same tokio-1.52.1, tokio-tungstenite-0.21.0, serde_json-1.0.149 registry paths and the dolphin task enum variants.

Deployable Signatures

YARA Rule

rule dolphin_rust_stealer {
    meta:
        author      = "pp-hermes"
        date        = "2026-05-30"
        description = "Dolphin Rust RAT/stealer — polymorphic, WebSocket C2, browser/wallet injector"
        family      = "dolphin"
        hash        = "ca6be0bf2f87f1998bfe4ba762d59bfa43a574fb011b4d19d587d83763c5c64f"
        confidence  = "high"
    strings:
        $s1 = "dolphin.dark-matter-analytics.com" ascii wide
        $s2 = "svc\\polymorph.rs" ascii wide
        $s3 = "dolphin_agent.log" ascii wide
        $s4 = "dolphin-e2e-aes256gcm-v1" ascii wide
        $s5 = "java_update_scheduler_557655::" ascii wide
        $s6 = "dolphin_app.dat" ascii wide
        $s7 = "dolphin_http_hook.dll" ascii wide
        $s8 = "\\.\\pipe\\dolphin_http_hook_" ascii wide
        $s9 = "ServerMessage::BrowserHttpIntercept" ascii wide
        $s10 = "ServerMessage::TokenStealAll" ascii wide
        $m1 = { 4D 5A } // MZ
    condition:
        $m1 at 0 and
        (2 of ($s1,$s2,$s3,$s4,$s5,$s6,$s7,$s8,$s9,$s10))
}

Sigma Rule

title: Dolphin Rust RAT Process Spawn and Network Connection
status: stable
description: Detects a process masquerading as NVIDIA Display Container LS spawned from a non-canonical path, or network connections to *.dark-matter-analytics.com
logsource:
  category: process_creation
  product: windows
detection:
  selection_process:
    - Image|endswith: 'NVIDIA Display Container LS.exe'
    - CommandLine|contains: 'RuntimeBroker.alive'
  selection_path:
    Image|contains:
      - '\AppData\'
      - '\Temp\'
      - '\ProgramData\'
  selection_network:
    DestinationHostname|endswith: '.dark-matter-analytics.com'
  condition: (selection_process and selection_path) or selection_network
falsepositives:
  - None expected for .dark-matter-analytics.com
  - Very low for RuntimeBroker.alive masquerade
level: critical

IOC List

Category Indicator
C2 domain dolphin.dark-matter-analytics.com
C2 port 32768
WebSocket auth token f58d15520b35a1c619914048470bf17cf262b61cc994b4b8347e71a26d15e729
Named pipe prefix \\.\pipe\dolphin_http_hook_
Temp data files %TEMP%\.dolphin_app.dat, %TEMP%\.dolphin_dc.dat, %TEMP%\.dolphin_wl.dat
Log files %TEMP%\dolphin_agent.log, %TEMP%\dolphin_agent_fallback.log, %TEMP%\dolphin_protection.log
Injector DLL dolphin_http_hook.dll
Registry run Matches NVIDIA Display Container LS in non-System32 path
Masquerade image name NVIDIA Display Container LS with parent /AppData/Local/ or /Temp/

Behavioral Fingerprint

This binary is a large (5–6 MB) x64 Rust executable with no packing but extremely rich imports (350+, spanning crypto, networking, media, registry, services, and WMI/SMB). It spawns from a user-writable directory while claiming the image name "NVIDIA Display Container LS". Within 5–10 seconds it resolves public IP via well-known checkers, then opens a TLS WebSocket to a hardcoded host. It creates named pipes with prefix dolphin_http_hook_, writes small .dolphin_*.dat files to TEMP, and may inject JavaScript into Electron renderer processes if Bitwarden, Exodus, Ledger, Telegram, or Discord are running. Network traffic is WebSocket-framed JSON with serialized ServerMessage enums.

References

  • dolphin — family entity page (capabilities, build stack, TTPs)
  • rust-async-rat-framework — technique page documenting the Rust/tokio/tungstenite builder pattern observed here
  • Sample source: MalwareBazaar via OpenCTI connector, label dropped-by-gcleaner^[triage.json]

Provenance

  • file.txt — PE32+ x64, 7 sections^[file.txt]
  • exiftool.json — linker version 14.44, subsystem GUI^[exiftool.json]
  • pefile.txt — full import table, version resource, section entropy^[pefile.txt]
  • rabin2-info.txt — PDB path, Rust language marker, no signing^[rabin2-info.txt]
  • strings.txt — builder config, task enums, C2 host, embedded JS, internal module paths (ca. 21,422 lines of output)^[strings.txt]
  • binwalk.txt — no embedded archive or packer detected; header-only PE at offset 0^[binwalk.txt]
  • capa.txt — capa signature directory missing; no capability extraction performed^[capa.txt]
  • dynamic-analysis.md — CAPE skipped; no Windows x64 guest available^[dynamic-analysis.md]