From 7a1816e78e65d3eb8d9f2977d76e7edc69befa04 Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Sat, 12 Sep 2026 10:14:01 +0000 Subject: [PATCH] Add content from: Project CAV3RN Continues: DNS-Controlled Multi-Transport C2 ... --- .../malware-analysis.md | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/src/generic-methodologies-and-resources/basic-forensic-methodology/malware-analysis.md b/src/generic-methodologies-and-resources/basic-forensic-methodology/malware-analysis.md index 392dffcdf57..78ce5b4b8e0 100644 --- a/src/generic-methodologies-and-resources/basic-forensic-methodology/malware-analysis.md +++ b/src/generic-methodologies-and-resources/basic-forensic-methodology/malware-analysis.md @@ -764,6 +764,66 @@ For DPAPI-specific post-exploitation workflows, see [DPAPI - Extracting Password When a transport module exposes generic verbs such as `get`, `send`, `upload`, `ws`, or `sendws`, check for a **small fixed XOR key** and text-safe wrappers such as **Base64** before assuming heavy crypto. Reused static headers, fixed URL paths, and custom tokens are often better detection pivots than domains alone. +## DNS-controlled multi-transport C2 and modular DLL brokers + +### Treat DNS answers as control messages, not only tunneled data + +A transport module can query authoritative DNS **before every poll and result upload**, encoding a nonce, client identifier, and the previous transport error in the name. The A-record answer then selects direct HTTPS, a trusted-service relay, rejection, or failure handling for that single transaction. Because a new transaction resets the state, reconstruct decisions as `(query state, returned IPv4)` pairs instead of classifying an IP address in isolation.[[24]](#references) + +A representative query grammar is:[[24]](#references) + +```text +..m. +``` + +In one implementation, `0` meant no error, `1` a relay-ID failure, `2` a relay transport failure, and `3` a direct transport failure. The last A-record octet acted as an opcode: `120` and `130` selected different channels according to that state, `140` raised an exception, other values defaulted to the cloud relay, and one exact IPv4 value rejected the client. This design gives the authoritative server transaction-by-transaction failover without changing the implant configuration.[[24]](#references) + +### Rotate cloud relay identifiers through A records + +A cloud deployment identifier can also be maintained over DNS. The implant first compares a truncated digest of the stored identifier with an A-record response; on mismatch, it requests sequential answers that reconstruct a replacement. In the observed layout, the initial IPv4 answer encoded one total-length byte plus three data bytes, while each continuation answer supplied four more bytes. The client persisted the resulting identifier and immediately used the new relay.[[24]](#references) + +```text +..q. # digest/freshness check +..p. # sequential replacement chunks +``` + +A four-byte MD5 prefix provides only a **32-bit freshness marker**, not authenticated configuration. During PCAP analysis, order the `.p` answers, interpret their IPv4 octets as raw bytes, use the first byte as the declared length, concatenate the remaining bytes, and trim padding only after reaching that length.[[24]](#references) + +### Trusted-service relay and header-gated fallback + +A Google Apps Script deployment can hide an application-layer proxy behind normal Google endpoints. The client POSTs a wrapper containing a relay key, an upstream method, forwarded headers, an optional body/content type, and a redirect flag. Apps Script performs the actor-facing request, responds with a `302` to `script.googleusercontent.com/macros/echo`, and returns a JSON-wrapped upstream response after redirects are followed.[[24]](#references) + +```json +{"k":"","m":"GET","h":{"X-Client-Id":"","User-Agent":""},"b":null,"ct":null,"r":true} +``` + +The direct HTTPS fallback may be **header gated**: scanners receive a generic failure body, while an expected custom client header unlocks tasking. Do not stop decoding after the relay's outer JSON—its body can contain another Base64 value and then a fixed-byte XOR layer. Packet type fields may decide whether the transport handles a task locally or forwards it to an internal broker.[[24]](#references) + +### Metadata-driven hot loading + +A local broker can continuously rescan its directory, group DLLs by version metadata such as `CompanyName`, select the highest-version candidate per group, validate a common export contract, and load or replace components without restarting the host. A replacement may need both a higher version **and a new path** because overwriting a previously discovered file in place is not necessarily noticed. Before `FreeLibrary`, a designated export can request shutdown and allow worker threads to exit.[[24]](#references) + +This pattern adds useful static and runtime pivots:[[24]](#references) + +- Cluster colocated DLLs by `CompanyName`, version, export set, and creation timeline rather than filename alone. +- Compare suspicious exports against the legitimate library being impersonated; a plausible public export may secretly initialize the broker. +- Look for rapid repeated directory enumeration followed by version-resource reads, `LoadLibrary`, the shutdown export, and `FreeLibrary`. +- Trace broker routing errors. A component may intentionally message a nonexistent fixed destination, parse an `Err1::` response to learn the broker identity, and then register its callback. +- Treat broker inventory commands that return loaded names, versions, and paths as framework reconnaissance, even when no host reconnaissance command follows. + +If the same framework exposes a command that Base64-decodes, GZip-decompresses, and writes attacker bytes to an arbitrary path, correlate writes with the broker scan. A new higher-version DLL under a new path is a plausible delivery-to-hot-load chain, but record it as an inference unless execution or broker-loading telemetry proves the full sequence.[[24]](#references) + +### Investigation pivots + +For this class of implant, combine DNS, proxy, and endpoint telemetry rather than relying on a domain IOC alone:[[24]](#references) + +- Hunt for high-frequency A queries whose leftmost label ends in a small state digit, followed by a hex-looking client label and stable mode labels such as `.m`, `.q`, and `.p`. +- Detect bursts of sequential `.p` answers whose four octets decode to printable deployment-ID bytes, preceded by a `.q` four-byte digest comparison. +- Search proxy bodies for the stable Apps Script wrapper keys `k`, `m`, `h`, `b`, `ct`, and `r`, particularly `"m":"GET"`, custom client-ID headers, and the Apps Script-to-`googleusercontent.com/macros/echo` redirect chain. +- Carve nested Base64 layers and test small constant XOR keys; correlate decoded broker packets with subsequent DLL enumeration or filesystem writes. +- Hunt for the shared exports `GroupByCategory`, `CheckAvailability`, `IsPrimeNumber`, and `OrderByDate` across otherwise unrelated DLL names, and for version-incremented replacements created at new paths. + + ## References @@ -790,4 +850,5 @@ When a transport module exposes generic verbs such as `get`, `send`, `upload`, ` - [21] [Recovering Metadata from .NET Native AOT Binaries](https://blog.washi.dev/posts/recovering-nativeaot-metadata/) - [22] [YARA-X CLI commands](https://virustotal.github.io/yara-x/docs/cli/commands/) - [23] [Dynamic capa: Exploring Executable Run-Time Behavior with the CAPE Sandbox](https://cloud.google.com/blog/topics/threat-intelligence/dynamic-capa-executable-behavior-cape-sandbox/) +- [24] [Project CAV3RN Continues: DNS-Controlled Multi-Transport C2 and a Modular DLL Broker](https://securelist.com/project-cav3rn-continues/120991) {{#include ../../banners/hacktricks-training.md}}