Contents
Mature SOCs catch Cobalt Strike on day one. Sliver and Mythic get caught on day three. Off-the-shelf C2 frameworks are useful for capability demonstrations, but they are not useful for engagements where the goal is to test whether your client’s detection actually works.
Writing a fully custom C2 from scratch, on the other hand, is a six-month project that I do not have time for on most engagements.
The middle ground I have settled on: a lightweight implant + dispatcher pair that I assemble per-engagement from a small library of building blocks.
The tasking format
A typical task message between the dispatcher and an implant looks like this:
{
"id": "a4f8b2c1",
"verb": "exec",
"args": ["whoami", "/all"],
"jitter": 30,
"next_check": 1731508800
}
Eight verbs total. Three required fields. Anything beyond that and you’re overengineering an in-memory loader.
The components
- Transport layer. HTTPS to an attacker-controlled domain fronted by a CDN, with optional DNS-over-HTTPS as a fallback.
- Beaconing. Jittered Gaussian intervals around a per-engagement mean. No fixed cadence — fixed cadence is what detections look for.
- Tasking format. A small JSON schema with maybe eight verbs. Enough to be useful, small enough that the parser has no surprise behaviour.
- Implant body. Reflective in-memory loader written for each engagement, signed with a leaf cert from a one-shot CA that we burn after the engagement.
What I deliberately do not build
- No keylogger. Not in scope for the kind of engagements I run.
- No persistence module. We achieve persistence per engagement using whatever target-specific mechanism makes sense — there is no value in baking a generic one in.
- No lateral movement built into the implant itself. That belongs in tasking, not in the binary.
The trade-off
This approach is slower than dropping Cobalt Strike. It is also genuinely undetected by every off-the-shelf signature, which is the entire point.
Tags