> ## Content Index
> Fetch the complete content index at: https://f4n6.co.uk/llms.txt
> Use this file to discover other available public pages before exploring further.

# Overlord RAT: Hidden Desktops, Solana-Driven C2, and a Screen the Victim Never Sees, Part 1
- URL: https://f4n6.co.uk/overlord-rat-hidden-desktops-solana-driven-c2-and-a-screen-the-victim-never-sees/
- Published: 2026-09-09T09:35:05.000Z
- Updated: 2026-09-10T11:20:35.000Z
- Author: Jeff Davies
- Tags: malware, Analysis, Reverse Engineering, Overlord, RAT, AI Security, #malware-feed

*How a routine MalwareBazaar pull turned into a full teardown of a Go surveillance implant that hides its operator on a virtual monitor and how an isolated sandbox plus a live debugger gave us the C2 without ever touching it.*

> **TLP:AMBER** contains IOC material and intended for defenders. Hashes and indicators included; no binaries are distributed.

---

Part 2 <https://f4n6.co.uk/inside-overlord-rat-part-2-emulating-the-c2-cracking-the-command-bus-and-catching-the-implant-killing-itself/>

## TL;DR

We analyzed `sample2` from a MalwareBazaar pull: an AES-256 password-protected ZIP containing a 31.7 MB x86-64 Windows executable built with **Go 1.26.2 + CGO (mingw-w64)**. Inside, the Go module path doesn't hide its identity:

```
path	overlord-client/cmd/agent
mod	overlord-client	(devel)
build	-tags=builder_release

```

It is a surveillance-grade remote access trojan we call **Overlord RAT** (after its own artifacts: `OverlordHiddenDesktop`, `OverlordPrivacyWindow`, `OverlordCriticalProcessShutdownWindow`).

Live cdb debugging of the detonated agent in a network-isolated VM produced this console capture the single most useful artifact of the session:

```
2026/09/08 23:33:31 runtime GOOS=windows GOARCH=amd64 cfg.OS=windows cfg.Arch=amd64
2026/09/08 23:33:31 [TLS] WARNING: Certificate verification is DISABLED. This is insecure!
2026/09/08 23:33:31 connecting to wss://privatec2.uk (TLS verify: false)
2026/09/08 23:36:01 dial failed [timeout]: failed to WebSocket dial: ... Get "https://privatec2.uk/api/clients/2e230d59...64ca24efa6/stream/ws?role=client": dial tcp: lookup privatec2.uk: i/o timeout (retrying in 18.415700099s)
2026/09/08 23:36:31 dial failed [DNS]: ... lookup privatec2.uk: no such host (retrying in 18.415700099s)

```

(Kept raw/un-defanged for fidelity — it's a verbatim console capture. The defanged IOC list is below.)

And from the debugger's handle table, the single-instance guard:

```
Name : \BaseNamedObjects\Overlord-3dFr72kGzMu2NW6bMVJe.Bfw
Type : Mutant

```

## The specimen

|                   |                                                                                               |
| ----------------- | --------------------------------------------------------------------------------------------- |
| Delivery          | AES-256 ZIP, password infected (classic Bazaar convention)                                    |
| Inner SHA-256     | 2da7c151676e991ebee73da26db28e6872f655b5487dc4b424a6024a3381472a                              |
| Inner SHA-1 / MD5 | 659a5696359eff19577a80ceb84aca7f95899914 / c5ec50a1192b42d07999becf34448952                   |
| Wrapper SHA-256   | 20658fdcbfcaee00f22c1ee556c1e4171b048347ced5a22d52032dbc49e779a0                              |
| imphash           | e2bf3ea500ed6add4b896d96c842dc0a                                                              |
| Size              | 31,751,794 bytes, 22 sections                                                                 |
| Signatures        | No Authenticode; TLS callbacks present; exports goDataCallback, goLogCallback, goStopCallback |

The exports are a tell: the same agent can be built as a library and driven by *(goData/goLog/goStop)Callback* host functions — a plugin-first design.

## Methodology (and why you should always go this deep)

The pipeline used: deep static triage (Go buildinfo, dependency graph, package map), isolated detonation (VMware guest, host-only network, snapshot-reverted before/after), then **live cdb attach** with API breakpoints when the sandbox's network isolation silenced the WebSocket handshake. The screenshot below is the detonation console as the agent warmed up its capture stack (note `d3d11.dll` and `DXGI.dll` loading before the console even emits a line):

That order of module loads — Direct3D11 *before* any C2 traffic — is consistent with the capture subsystem standing up first.

## The C2 story in three acts

![Overlord RAT C2 protocol — reconstruction of discovery, enrollment and command bus](https://storage.ghost.io/c/3c/c9/3cc9221c-3833-4967-a2f1-a72d36cbcaff/content/images/2026/09/overlord-c2-protocol.svg)

*(Diagram is a reconstruction: solid green = observed live in our debugger console; dashed = synthesized from static analysis; red dashed = requires a reachable C2, so not exercised in the isolated lab.)*

**1) Hard-coded default.** A Go string literal sits next to its buildinfo:

```
go1.26.2 ... privatec2.uk

```

The agent dials `wss://privatec2[.]uk`, flags certificate verification off, and authenticates with custom headers (`x-agent-token`, `x-overlord-client-id`) on the endpoint pattern `/api/clients/<64-hex-agent-id>/stream/ws?role=client`. Retry policy: \~18.4 s exponential-ish backoff per server, rotating through the configured list.

![](https://storage.ghost.io/c/3c/c9/3cc9221c-3833-4967-a2f1-a72d36cbcaff/content/images/2026/09/image-1.png)

Taking a look at the C2 Panel

**2) Solana rotator.** Before touching that default, the config module (`cmd/agent/config/solana.go`) can resolve its server list **from the Solana blockchain**: it calls `getSignaturesForAddress` against public RPC endpoints, reads the **memo** of discovered transactions, and **AES-GCM-decrypts them with the agent token**. Our static IOC pass picked up the well-known Memo program address `MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr` — the sample watches for transactions on that program's flows.

```
No server URLs configured. Resolving from Solana memo (address: %s)
[config] resolved server URLs from Solana memo (%d servers)
[solana] RPC %s failed for getSignatures: %v
[solana] failed to decrypt memo from tx %s: %v

```

**3) Purgatory gate.** On successful connection the server can hold the agent in a staging queue before any commands are honored:

```
[purgatory] identity fingerprint=%s
purgatory: status=denied / pending / approved

```

This is an anti-automation tripwire: an agent that can stall low-value sandbox victims until an operator verdicts their host as "interesting". Our isolated detonation never connected which is exactly why we went a step further and chased the handshake at the debugger instead.

## What passive sources say about the infrastructure

We did **not** contact the C2\. The following is from public archives and registries only (collected 2026-09-09):

| Source                       | Finding                                                                                                                                                                                                                                               |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Nominet WHOIS (.uk registry) | Registered **16-May-2026** via Cloudflare, Inc.; expires 2027-05-16; **Nominet could not match the registrant's name/address against a 3rd-party source** (same day as registration — a throwaway-look registrant profile)                            |
| Name servers                 | arch.ns\[.\]cloudflare\[.\]com, jillian.ns\[.\]cloudflare\[.\]com — full Cloudflare coverage                                                                                                                                                          |
| CT logs (crt\[.\]sh)         | First certificates on **16-May-2026** (Let's Encrypt E8 + Sectigo E36, exactly matching the domain's registration day); Let's Encrypt renewal 14-Jul-2026; a **Cloudflare TLS ECC cert** from 21-Jul-2026 — the C2 is served behind Cloudflare's edge |
| Cert SANs                    | privatec2.uk \+ wildcard \*.privatec2.uk — the wildcard hints at per-agent or per-region sub-hosts                                                                                                                                                    |
| Public archives              | URLScan: 0 scans; Wayback Machine: 0 captures — no indexed web face (as expected: enrollment is over WSS, not a login form)                                                                                                                           |

Two observations worth pondering. First, the **Cloudflare fronting + Ed25519/X25519 identity + pinned custom CA** explains the agent's odd console warning — with an edge TLS-terminator in front and a per-operator CA, "verification disabled" is how the agent trusts its *own* pinned material instead. Second, the **domain itself is only \~4 months old and wholly Cloudflare-fronted**: resilience comes from the *Solana memo rotator*, not from domain age. Blocking the domain is durability theater; the reach is the blockchain and the token.

## Core capabilities what the agent code does

From the Go package tree and the behaviors compiled in:

**The screen the victim never sees.** A `virtual_windows` module installs (or enables) a **Virtual Display Driver** — it even fetches a legitimate one from the public `VirtualDrivers/Virtual-Display-Driver` GitHub releases API — then starts a process (typically a browser) *on the virtual monitor*. `virtual: moved window hwnd=0x%x (pid=%d) to virtual monitor` is the quote that matters: operator actions happen on a display `ChangeDisplaySettingsExW`\-hidden from the user.

**"Backstage" browser injection (the crown jewel).** `capture/backstage_*` \+ `handlers/backstage*` clone a browser profile, apply an **Opera patch** (`opera_patch=%v`), kill the real browser (`kill_exe`), and relaunch the clone **with a DLL injected into its GPU child process** (`backstage inject: found GPU child process PID %d for browser PID %d`). The injected DLL streams video directly to the agent via a DXGI shared-memory bridge (`Local\backstage_rdi_%d`). The displaced user gets `auto-start explorer` re-launched so the desktop looks normal. The target set is broad: *Chromium family (Chrome, Edge, Arc, Brave, Vivaldi, Yandex, Opera GX), Firefox and Waterfox*, with browser-pinned UA walkers for input simulation.

**Capture stack with no mercy for missing hardware.** A display-encoding waterfall: native `NVIDIA NVENC (D3D11 texture)` → AMD `AMF` → Intel `QSV/oneVPL` → `Windows Media Foundation H.264 MFT (software/HW)` → raw JPEG/black-frame filler. HEVC where available; multi-display, per-display fps/bitrate/quality set remotely.

**Sensors.** Webcam via Media Foundation (`windows-camera-go`), microphone/voice sessions (`gen2brain/malgo`), clipboard sync, an active-window monitor, file search, installed-apps with icon extraction — and the mandatory **keylogger** with rotating logs under `%APPDATA%`.

**Control plane.** Mouse/keyboard injection on chosen displays (three modes: plain, backstage, virtual), a real **CONPTY shell**, scripts (its updater literally ships a PowerShell `Invoke-WebRequest` snippet), UAC elevation, process suspend/resume/kill, file upload/pull zipped from anywhere, SOCKS5 pivot, WebRTC push (`whipPath`/WHIP+stun/turn) for the "overlord\_webrtc" build.

**Self-sustainment.** Startup-folder persistence, a `.bat` self-updater (the notorious `overlord-update-*.bat` \+ `ping -n 3 127.0.0.1 >NUL` delay trick), self-replacement of the running image, and self-defense by becoming a **critical process** (`NtSetInformationProcess(ProcessBreakOnTermination)` — so killing it takes the box down).

**Pluggability.** Both a **WASM plugin runtime** (wazero; plugins must export `overlord_alloc`) and a **native PE plugin loader**, with plugin payload pull over the C2 HTTP plane and callbacks wired through the `goDataCallback`/`goLogCallback`/`goStopCallback` exports. Stage-2 DLLs for injection are delivered as dispatcher messages (`dllSize=%d`), zero-written to disk — stored in shared memory and mapped into the GPU process.

> **Analyst's note on "embedded PE".** Our first YARA hit promised an embedded PE (`malbox_embedded_pe`). It wasn't. Every `MZ` occurrence beyond the header resolves to *machine code of the loader's header validator* (`66 81 38 4D 5A` — `cmp word [rax],'MZ'`; `81 38 50 45 00 00` — `cmp dword [rax],'PE\0\0'`). The only `PK\x03\x04`/`PK\x05\x06` bytes are Go's `archive/zip` *writer* constants compiled inline. Forget carving; this is a **loader**, not a dropper. Stage-2 lives at C2 or in victim memory.

## Dependencies red-flag the design intent

From the Go buildinfo blob (file offset `0x631C20`):

| Dependency                                          | Purpose in this agent                                                  |
| --------------------------------------------------- | ---------------------------------------------------------------------- |
| nhooyr.io/websocket v1.8.10                         | C2 channel                                                             |
| github.com/vmihailenco/msgpack/v5                   | wire protocol (dispatcher messages)                                    |
| github.com/tetratelabs/wazero v1.12.0               | WASM plugin runtime                                                    |
| github.com/UserExistsError/conpty v0.1.4            | hidden console shell                                                   |
| github.com/gen2brain/malgo v0.11.24                 | audio capture/playback                                                 |
| github.com/Kirizu-Official/windows-camera-go v0.2.0 | webcam capture                                                         |
| github.com/lxn/win                                  | raw Win32 bindings                                                     |
| golang.org/x/crypto v0.49.0                         | Ed25519/X25519/HKDF identity + ChaCha20Poly1305/AES-GCM channel crypto |

Combined with `-trimpath` and tag `builder_release`, this is a professionally maintained codebase — a quality signal relevant to attribution discussions (internal self-identifiers only; no actor attribution asserted).

## Indicators of Compromise (defanged)

| Type           | Value                                                                                                                                                                                                                                                |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Domain         | privatec2\[.\]uk                                                                                                                                                                                                                                     |
| URL            | wss://privatec2\[.\]uk/api/clients/<64-hex>/stream/ws?role=client                                                                                                                                                                                    |
| HTTP headers   | x-agent-token, x-overlord-client-id                                                                                                                                                                                                                  |
| Mutex          | \\BaseNamedObjects\\Overlord-<random-suffix>                                                                                                                                                                                                         |
| Files          | config/settings\[.\]json, config/server\_index.json, overlord-update-\*.bat, overlord-update-%d.log, crashlogC\[.\]log, agent-\*.tmp                                                                                                                 |
| Env keys       | OVERLORD\_SOL\_ADDRESS, OVERLORD\_AGENT\_TOKEN, OVERLORD\_DISABLE\_CAPTURE, OVERLORD\_DESKTOP\_MAX\_FPS, OVERLORD\_JPEG\_QUALITY, OVERLORD\_PING\_INTERVAL\_MS, OVERLORD\_BLOCK\_CODEC, OVERLORD\_FETCH\_PUBLIC\_IP, OVERLORD\_TLS\_CLIENT\_CERT/KEY |
| Hash (inner)   | 2da7c151676e991ebee73da26db28e6872f655b5487dc4b424a6024a3381472a                                                                                                                                                                                     |
| Hash (wrapper) | 20658fdcbfcaee00f22c1ee556c1e4171b048347ced5a22d52032dbc49e779a0                                                                                                                                                                                     |
| imphash        | e2bf3ea500ed6add4b896d96c842dc0a                                                                                                                                                                                                                     |

## Detection

YARA (from the malbox session; matches indicate resemblance):

```yara
rule Overlord_Go_RAT {
  meta:
    author = "malbox analysis session"
    description = "Overlord Go RAT agent (overlord-client/cmd/agent)"
  strings:
    $pkg1 = "overlord-client/cmd/agent" ascii
    $pkg2 = "overlord-client/cmd/agent/capture" ascii
    $hd   = "OverlordHiddenDesktop" ascii
    $cp   = "OverlordCriticalProcessShutdownWindow" ascii
    $pw   = "OverlordPrivacyWindow" ascii
    $cb1  = "goDataCallback" ascii
    $cb2  = "goLogCallback" ascii
    $cb3  = "goStopCallback" ascii
    $sol  = "Resolving from Solana memo" ascii
  condition:
    uint16(0) == 0x5A4D and (2 of ($cb*) or (2 of ($pkg1,$pkg2))) and ($hd or $cp or $pw or $sol)
}

```

Hunt targets worth logging in EDR/SIEM:

- New mutexes matching `\BaseNamedObjects\Overlord-`
- Any query/lookup for `privatec2[.]uk`
- WebSocket processes emitting `x-overlord-client-id` headers
- `pnputil`/PnP installs of unfamiliar display drivers (VDD)
- `.bat` files named `overlord-update-*.bat` executed from temp dirs
- A browser process whose parent created a mutex inside `Local\backstage_*` named shared-memories

## Closing

Overlord RAT is a reminder that "Go + CGO + a virtual display driver" is now a state of the art for **surveillance-first implants**, and that blockchain-native C2 rotation (Solana memos, in this family) robs IR teams of their favorite class of static IOCs. Sample-level carving gets you nothing: the agent ships its own reflective loader and expects the DLLs from the server. If you're hunting something like this live, **capture memory first** — the stage-2 artifacts only exist in RAM once injections start.

*Analysis performed in a network-isolated detonation environment with live debugger introspection. No attribution claims are asserted beyond internal family identification; the "overlord-client" names are sample-internal self-identifiers.*

*This analysis was performed by an AI agent that is currently being developed to further enhance its capabilities going forward*

---

*Sample credit: MalwareBazaar ('sample2' delivery package). All tactics in this post correspond to MITRE ATT&CK: T1219, T1071.001, T1573.002, T1055.001, T1055.003, T1105, T1059.001, T1113.003, T1125, T1123, T1056.001, T1115, T1547.001, T1090.001.*