Research note N.14 · 2026-10-16

The costume is not the accent.

The wire is the one place an implant cannot encrypt its way to invisibility: TLS hides content, not shape. A C2 profile is a costume for a conversation — and the conversation still has rhythm, sizes, and a first packet. This note walks our wire stack the way N.12 walked the host: twenty-three profiles, sealed sessions with rotating identity, edge fronting, and per-serve payload mutation — what each layer buys, and what a patient statistics hunter still hears underneath.

READ TIME ≈ 8 MIN AUTHOR THE AXIS TEAM

What a profile actually is

AXIS ships twenty-three C2 profiles — Microsoft Graph, Microsoft Update, GitHub's API, Google Cloud, AWS S3, Dropbox, Slack webhooks, Docker and npm registries, the Kubernetes API, DNS-over-HTTPS, Firebase, Salesforce, WordPress, Prometheus remote write, and others — each a complete stage play rather than a paint job. A profile shapes the paths the agent requests, the headers both sides send, and the response disguise the server performs: the listener answers as the imitated service would, down to redirecting a stray 404 the way the real thing would. The profile is baked into the agent at build time, so the costume is tailored, not rented by the hour. What it buys: the conversation reads as legitimate SaaS traffic to category filters, allowlists, and a human skimming a proxy log. What it costs: a costume is fixed per build, and nothing in a costume changes how much the actor talks, when, or for how long. Behavior analytics do not read costumes.

Sealed sessions and rotating identity

Every agent session is sealed: an X25519 exchange, an HKDF-derived session key, AES-GCM on the beacons — the respectable minimum, and we treat it as the floor rather than the feature. The feature is what happens to identity: the session identifier rotates on a fixed cadence — every fifty beacons, with a short grace window so an in-flight reply is never orphaned — so a defender correlating sessions by ID watches the actor change name tags mid-conversation. What it buys: session-level correlation by identifier dies on schedule; key hygiene stops depending on an operator remembering to rotate. What it costs: as the previous note put it — rotation resets the implant's identity, not its behavior. Fifty beacons of rhythm, then fifty more of the same rhythm under a fresh tag. The hunter who follows the session's shape instead of its name loses nothing at the rotation boundary. We know; we wrote that rule.

Fronting at the edge

Above the listener sits optional edge fronting: a generated worker script puts the C2 behind a mainstream edge network, with multiple labeled URLs per deployment and the WebSocket tunnel riding the same path as everything else. What it buys: borrowed reputation — the agent talks to an IP range the enterprise already trusts, infrastructure churn stops touching the agents, and a burned URL is a label edit rather than a rebuild. What it costs: a dependency we do not control, and a costume again: the destination is reputable, the conversation still has to be. A long-lived WebSocket to a service that humans use in bursts is a shape, and shape is the subject of this note. Fronting moves the conversation to a nicer neighborhood. It does not change the accent.

A different payload every serve

Delivery gets the same treatment as transport. The server keeps dual payload pools — normal and persist-only — picks per delivery, appends a random overlay, and mutates every Windows PE it serves: a backdated build timestamp, a fabricated compiler provenance header, a recomputed checksum, padding within a fixed budget. Every download is a unique hash; shellcode payloads skip mutation because there is no PE metadata to mutate. What it buys: hash blocklists are dead before they are written — yesterday's sample matches nothing served today. What it costs: uniqueness is a property of the file, not of the behavior. A sandbox does not care that the hash is new; it scores what the specimen does, and what it does is the product working as intended. Mutation wins against the signature pipeline. It is not an argument against the behavioral one, and we do not present it as one.

WINS AGAINST STILL AUDIBLE PROFILE — 23 PRESETS paths · headers · response bodies content filters, skimmers behavior SEALED SESSION X25519 · HKDF · AES-GCM content readers handshake metadata IDENTITY ROTATION every 50 beacons + grace ID correlation rhythm — see N.12 EDGE FRONTING labeled URLs · grey-cloud WebSocket reputation lookups shape PER-SERVE MUTATION timestamp · provenance · checksum · overlay hash blocklists sandboxes THE STATISTICAL FLOOR the layer every layer pays into — patient hunters listen here
Fig. A — six layers, one floorEach layer wins its layer; none wins the layer above
Wire layerIt buysStill audible
Profile (23 presets)Reads as legitimate SaaS to filters and skimmersVolume, timing, session length — the costume fits, the accent stays
Sealed sessionsPer-session keys; respectable crypto floorHandshake sizes and cadence are metadata, not content
Identity rotationSession-ID correlation dies on scheduleRhythm survives the name change — N.12's rule
Edge frontingBorrowed reputation; churn absorbed; URL burns are editsLong-lived tunnels to burst-shaped services
Per-serve mutationHash blocklists dead on arrivalBehavior is not hashed; sandboxes score verbs, not bytes
mTLS (optional)Only enrolled agents complete the handshakeClient-auth TLS is rare in SaaS clothing — a tuxedo at a beach party
Fig. B — the wire ledgerEvery layer wins its layer; none wins the layer above

The honest bill

Stack the layers and a pattern emerges that we think is the actual law of C2 traffic: each layer defeats the detector aimed at it, and none defeats the detector one layer up. Profiles defeat content inspection and lose to behavior. Rotation defeats ID correlation and loses to rhythm. Mutation defeats hash lists and loses to sandboxes. Fronting defeats reputation lookups and loses to shape analysis. This is the conservation law from N.12 wearing a wire: evidence is not deleted, it is relocated — and on the wire, it is relocated into statistics, because statistics are the only layer left. We spend real engineering there: jitter and working-hours gates are live controls, delivery and tasking take different pools, keepalives are tuned. And then we publish the limit, because it is the same limit everyone has and only some admit: a C2 that talks on a schedule is a metronome with a costume on. The costume is worth wearing. The metronome is what you are actually defending, and what a patient hunter is actually hearing.

A profile changes what the conversation looks like. Statistics change nothing — they are what the conversation sounds like.

The defender's angle

Everything expensive in this note is expensive to us, not to you — the statistical layer is the cheapest hunt in the series to run and the hardest for us to answer:

wire hunt — listening for the accentcategory level, as always
// rhythm over identity — the rule from N.12, applied to the wire
autocorr(sessions, 30d) per host   // distributions, not intervals
// costume mismatches
k8s-api paths from hosts that never run kubectl
saas destinations holding long-lived websockets   // burst service, marathon session
tls client-auth where the profile implies public api  // the tuxedo
// and the cheapest signal on this page
byte-count cadence per destination  // payloads mutate; sizes cluster anyway

None of this requires reading a single byte of content, which is precisely why it works — and why we publish it. A customer should hear the accent in the demo before they read about it in someone else's incident report.

That closes the shelf for now — twelve notes on how the product works and what it costs, plus these two on what the other side sees. The lab breaks something every quarter, and the notes follow; announcements ship with the quarterly release notes.