The arithmetic, honestly
The installer implements nine standard Windows methods; the site says eight locations. That is not marketing rounding — it is a counting decision we will defend: Run and RunOnce are one row. Same hive, same telemetry class, same rule family catches both; the difference between them is a boolean in the installer and a sentence in the documentation. Counting them separately inflates a brochure. Counting them together keeps the audit honest — and the audit is the point, because each of the eight rows below is a bet placed against a defender's baseline.
| Location | It buys | It costs |
|---|---|---|
| Run + RunOnce (one row) | User-context survival of reboot; trivial install | The most-watched keys in the OS — registry telemetry, every baseline tool, every SOC's first query |
| Startup folder | Simplicity; user context; no API surface at all | Enumerated by everything; needs a file on disk with a name in it |
| Scheduled task | Flexible triggers; a SYSTEM option; plausible housekeeping | Task-creation events, an XML artifact on disk, a scheduler log with a long memory |
| Service | Boot-early start; SYSTEM; the host's own machinery | Service-install events; a new service name is a novelty, and novelty is the signal |
| WMI subscription | No entry in any autostart list; event-filter indirection | The subscription namespaces are a hunted class — defenders read them on schedule now |
| COM hijack | Execution inside legitimate host processes; per-user, no admin | Classes-hive diffs catch it; a host application update can silently break it |
| DLL sideload | Execution inside signed binaries; search-order confusion | Module loads from odd paths; targets age, so we keep two dozen vetted ones — several absent from the public LOLBAS lists — and auto-fallback when one dies |
| BITS job | The transfer service doubles as a trigger; resumes on its own | The BITS queue is readable by any admin; jobs have owners, timestamps, and a database |
Per-host generation: the multiplier
A location is a mechanism; an install is a specimen. Every AXIS install is generated per host — names, paths, files, and cover identities drawn from a rotating cast of fifty legitimate-looking system names — so two deployments never resemble each other. That kills the cheapest pivot in incident response: hash-and-name sweeps across the fleet. What it does not kill, honestly, is the mechanism class: a COM hijack is a Classes-hive anomaly on any host, whatever the specimen is called. Per-host generation forces the defender to hunt mechanisms instead of names. That is a real cost we impose — and a real limit we concede, because mechanism hunting is exactly what mature teams already do.
The Ghost family, above the list
The standard eight are for hosts that tolerate standard things. The Ghost installs are for the rest — capability names, category level, as always:
Ghost-Path is the multi-registration install: one install that registers through more than one standard mechanism at once, so a single cleanup pass doesn't have to end the agent. Status reports it as one install; remove clears it as one install — the operator never manages the combination by hand. Ghost-Svchost is the service-hosted install whose files are produced for that one machine; its launcher is exactly that — a launcher. The service starts, spawns the detached agent, and stops: C2 traffic never comes from a service-host process, and the running service nobody can find is the one that already exited. Its NLD variant pushes the same idea further down: the loader core exists only as shellcode in the registry, so the on-disk stub carries no loader IoC to signature. Ghost Write is the installer path that stages through file-system metadata streams and performs the install from inside a process the OS itself started — the install event never carries the stager's name, which breaks storyline attribution one event earlier. And for hosts where a kernel-level sensor blocks the primary path outright, a fallback stage exists — gated, per the doctrine from N.11: when the fingerprint says kernel-level, we route around rather than argue. There is also a persist-only build mode in which the stager's entire job is the install: it exits, and the first beacon belongs to the persisted agent, so the install event and the first connection never share a process.
Off Windows, the model holds. Ghost-Systemd builds a launcher per machine and reconstitutes the agent at boot rather than leaving a plain executable on disk; the launcher is sealed against the machine's own identity, which never transits to the server — a launcher copied to another machine is a launcher that doesn't work. Where systemd is absent — NAS and router-class devices — Ghost-Cron is the same package behind a cron trigger. On macOS, Ghost-Launchd splits by privilege: daemon at boot when root, agent at login when not. Across all three, status and removal never ask which method was used; a small on-disk pointer records the choice for whichever operator shows up next week.
Persistence is not where the implant hides. It is where the implant signs the register — the audit is whether anyone reads it.
The honest bill
Persistence is the loudest thing an implant does, because it is a write — to a registry, a scheduler, a queue, a unit directory — and writes land in tables defenders can read. Per-host uniqueness kills name-based pivots; mechanism classes remain, and every mechanism class above has had a detection paper written about it. The second honest cost is lifecycle: an install you cannot cleanly remove is not persistence, it is litter. That is why the feature is three actions on every OS — install, status, remove — why removal never asks which method was used, and why the panel separates remove the install from delete the record: deleting the record without removing the install is how fleets get haunted by agents nobody can task and nobody can find on purpose.
The defender's angle
Baseline autostarts per host role, then diff daily — the eight rows of Fig. A are eight diff targets, and the diff cares nothing about specimen names. Specifically:
// registry pair — the most-watched keys in the OS for a reason sysmon(12,13,14) where path like "\\Run" // both keys; they are one row // tasks, services, subscriptions, queue sec(4698,4699) + taskschd operational // task create/change, then read the XML sec(4697) + sysmon(6) // service install + driver loads wmi: enumerate __eventfilter/bindings // on a schedule, not after an alert bitsadmin /list /allusers // the queue is public reading // and the two that age best hkcu\software\classes diff per role // COM hijacks live here, per user image_load where path not in (system32, program files) // sideloads, odd paths
Then hunt the orphans: installs whose management record no longer exists anywhere. A service that starts, spawns, and stops; a task that fires into a process tree that immediately detaches; a registry value that points at a stub that points nowhere. The mechanisms are all documented — including by us. The register is public. Read it on a schedule and this entire note becomes a detection backlog, which is what it was for.
Next note: The costume is not the accent. Twenty-three traffic profiles, sealed sessions with rotating identity, edge fronting, and per-serve payload mutation — what each wire layer buys, and what a patient statistics hunter still hears.