Find out which attacks your defenses actually stop
Project Achilles is a purple team platform for continuous security validation. It runs safe, real-world attack techniques on your own endpoints, every day, and shows which ones your EDR blocked, which it only saw, and which went through unnoticed.
- About 65 tests mapped to MITRE ATT&CK: ransomware chains, credential theft, EDR tampering, CIS hardening checks
- A small Go agent on Windows, Linux and macOS that only calls out over HTTPS
- EDR evidence pulled from Microsoft Defender, CrowdStrike, SentinelOne and Sophos and matched to each test
Security controls drift. An annual pentest sees one day of the year.
An EDR policy gets switched to detect-only during an outage. Someone adds a broad folder exclusion to fix a slow application. A new ransomware crew starts using a driver your sensor has never seen. Nothing announces these changes, so the coverage you assume and the coverage you have slowly move apart.
The gap is invisible without testing
The shaded area is risk nobody signed off on. Dashboards that count installed agents or enabled policies stay green the whole time.
Point-in-time is out of date by Monday
A pentest report describes the environment on the day it ran. Continuous validation re-runs the same techniques on a schedule and catches the drift within a day.
Measure outcomes, not configuration
Achilles asks one question per technique and host: did it get stopped, did the SOC see it, or did it run clean?
One loop, run over and over
Every run follows the same six steps, from picking a technique to fixing the gap it found. Pick a step to see what happens inside it.
Tests behave like the adversary, then report what happened
Each test is a binary built from a Git-synced library and mapped to ATT&CK techniques. It performs the technique for real, in a contained way, and exits with a code that says whether it was stopped.
Intel-driven attack chains
Multi-stage emulations of current threat actors, built from published threat intelligence. Each stage reports separately.
Akira BYOVD chain, SafePay UAC bypass, EDRSilencer, AMOS macOS infostealer, LSASS dumping with PPL bypassMITRE top-10 ransomware techniques
One test for each of the ten techniques MITRE ranks most common in ransomware attacks, from PowerShell and WMI execution to deleting backups and encrypting files.
T1059.001, T1047, T1490, T1486, T1489Cyber-hygiene bundles
Configuration checks against CIS and identity baselines. One bundle fans out into dozens of controls, each scored on its own.
CIS Windows L1, CIS Linux L1, Defender hardening, Entra ID tenant hygiene, AD identity| Exit code | Meaning | Counts as |
|---|---|---|
| 101 | The technique ran to completion. Nothing stopped it. | Unprotected |
| 105 | The payload was quarantined as it was written to disk. | Protected |
| 126 | Execution was blocked or prevented by AV or EDR. | Protected |
| 127 | The binary was quarantined when it tried to run. | Protected |
| 0, 1, 259, 999 | No result, test error, timeout, or prerequisites not met. | Error, never scored |
The agent: small, outbound-only, careful about updates
A single static Go binary runs as a system service. It never listens on a port. It asks the console for work, runs it, and reports back.
Enroll once, then poll
An installer uses a short-lived enrollment token, single-use by default. After that the agent sends heartbeats and asks for tasks over HTTPS with its own API key, stored only as a hash on the server, so it works behind NAT and strict firewalls.
Runs only the binary it was sent
Before running a test, the agent checks the binary's SHA-256 and size against the console's record, and runs it from a work folder locked to SYSTEM and Administrators. Windows builds are also Authenticode-signed with your certificate when one is configured.
Updates without bricking the fleet
A new version must report the version it was registered as. After swapping the binary the agent launches it once to check, and rolls back to the old one if that check fails.
Watched by the console
Missed heartbeats mark an agent offline. A task that never reports back is timed out, and if an EDR killed the agent mid-test, the console can prove that from the EDR's own alert.
Five verdicts, in order of strength
The exit code says what happened on the endpoint. EDR alerts say what the SOC saw. Achilles combines both and keeps the strongest result, so every run lands on exactly one verdict.
A stage was blocked on the endpoint (exit 105, 126 or 127). The attack did not finish.
An EDR confirms it killed, quarantined or blocked the test itself, as part of its own immediate response.
The technique ran, but an EDR raised an alert that matches this run: same host, the test's binary, within minutes of it. The SOC would have seen it.
A stage ran unblocked (exit 101) and no EDR alert matched. A real attacker would have succeeded quietly.
The test could not reach a conclusion: a timeout, a missing prerequisite, an agent that went offline. It is reported but never scored.
Why Detected is not the same as Protected
A detection gives an analyst a chance to respond, which still beats silence. But it depends on someone acting in time. The Defense Score counts blocked and EDR-confirmed results together, and a stricter blocked-only score sits next to it so the difference stays visible.
Multi-stage tests are judged stage by stage
In a five-stage chain, each stage has its own exit code and its own ATT&CK technique. A technique is never marked as covered because a sibling stage was blocked, and the chain-depth view shows how far each chain got before something stopped it.
Blocked before launch still counts
When CrowdStrike, SentinelOne or Sophos blocks the test before it starts, and its alert ties to that run, the result is rewritten from "not run" to Protected. Defender ASR blocks stay "not run".
Posture analytics: one number, and the detail behind it
Every result is indexed in Elasticsearch. More than 30 views slice it by technique, tactic, threat actor, host, test and time, so a single score can always be traced back to the runs that produced it.
Defense Score
Score trend, last 12 weeks
Example dataATT&CK coverage by tactic
How far attack chains get
Share of chains stopped at each stage, latest run per host
Scored on your current state
The default view keeps only the latest conclusive result for each test and host pair. Fixing a gap shows up as soon as the test re-runs, instead of being diluted by months of old failures.
Accepted risk stays honest
When the business accepts a gap on purpose, you can exclude it from the headline score. The original series is kept alongside, so the decision is visible rather than hidden.
Matching EDR alerts to the test that caused them
Alerts rarely fire on the test binary itself. They fire on the Windows program it started. Test binaries are named after the test's UUID, so Achilles looks for that name in the evidence the EDR attaches to the alert, then links the two.
Same host, same window, the test in the evidence
An alert is linked when it is on the test's host, inside the run's time window, and the test's UUID-named binary appears in its evidence: the triggering process, its parent or grandparent where the EDR reports them, or a file path.
The SOC queue stays clean
Once an alert is proven to be a test, Achilles can resolve it in the EDR console with a note naming the test. Dry-run mode shows what it would close before you let it write anything. The test results themselves are never edited.
The EDR's own posture, scored alongside
Microsoft Secure Score, CrowdStrike Zero Trust, and Achilles-computed scores for SentinelOne and Sophos are trended next to the Defense Score. Posture checks also flag exclusions that would quietly whitelist every test.
What changes for security operations and for risk owners
The same results answer two kinds of questions: "what should we tune this week?" and "how exposed are we, and is it getting better?"
For security operations
- A detection backlog ranked by evidenceEvery Unprotected technique is a concrete detection gap, with the exact host, binary and time to reproduce it.
- Proof that a fix workedChange a policy, re-run the test, and watch the verdict change the same day. No ticket gets closed on assumption.
- Regressions caught earlyA sensor update, a new exclusion or a policy rollback shows up as a score drop, with Slack or email alerts when it crosses a threshold.
- Purple teaming without a scheduling meetingPre-execution notices tell the SOC what will run and when, so red activity is expected and blue response can be observed.
For risk management
- Control effectiveness you can quote"Ransomware chains are stopped before encryption on 85% of hosts" is a measured statement, re-measured every week.
- Exposure to named threat actorsThreat-actor coverage shows, for each group your test library emulates, how many of its tests got through on your hosts today.
- Evidence for auditors and the boardCampaigns produce a tests-by-hosts evidence matrix, CSV exports and print-ready execution reports.
- Risk acceptance on the recordAccepted gaps are excluded explicitly and remain visible in the unadjusted score, so nothing disappears from view.
| Red-team principle | What it means | How Achilles applies it |
|---|---|---|
| Emulate the adversary | Test what real attackers do, not what is easy to test. | Intel-driven chains reproduce current crews' tradecraft, stage by stage, including BYOVD and EDR tampering. |
| Assume breach | Start from code already running on an endpoint. | Tests run post-compromise techniques on the host, where the EDR is the last line of defense. |
| Measure outcomes | Judge controls by what they stop, not by what is installed. | Every run ends in one verdict from exit codes plus matched EDR evidence. |
| Repeat continuously | Security is a moving target; one test is one snapshot. | Schedules and campaigns re-run the library, and the score always reflects the latest result per host. |
| Close the loop with blue | Findings only matter once defenders act on them. | Notices, alert correlation and auto-resolve put red activity and blue telemetry side by side. |
A year of findings: annual exercise against continuous validation
Guardrails for running attacks in production
Running offensive techniques on real endpoints only works if the platform is safe to operate. These protections are built in.
Announced before it runs
With pre-execution notices on, tests are held on the server until the email is accepted for every recipient, plus a lead time you choose. A broken mail server holds the tests rather than letting them run unannounced.
Hash-checked before it runs
A test binary runs only if its SHA-256 and size match the console's record. Windows builds are Authenticode-signed with your certificate when one is configured, and the Sophos posture checks flag an allow-list entry for that certificate, which would whitelist every test.
Roles and organizations
Admins, operators, analysts and read-only explorers get different permissions. Inside an install, agents, tasks, schedules and results are scoped to each organization; for full separation, run one install per organization.
Scoped API keys
Automation keys come in read, read-write and admin scopes. No key can create users or more API keys, so a leaked key can't mint console access that outlives it. Admin-scope keys can still run commands on agents, so treat them like root credentials.
Safe self-updates
Version checks, a launch test at the final path, automatic rollback and a repeat-install guard keep a bad build from knocking the fleet offline.
Deployed where you need it
Docker Compose, a single server behind Caddy with automatic TLS, an on-prem LAN installer with its own constrained CA, or managed cloud hosts.