Skip to content

Replicant v0.7.0 — catalog defect fixes

Choose a tag to compare

@404SecNotFound 404SecNotFound released this 30 Aug 10:53
· 27 commits to main since this release
79db2dc

A defect release. Unlike v0.6.0, this one does change the emitted telemetry: plans for REP-002, REP-013, REP-014, REP-016 and REP-024 differ from every prior release at the same seed. Determinism is intact and no golden CEF line changed, but if you have tuned a detection against any of those five, read on before upgrading.

It also carries the v0.6.1 web UI fix, so there is no reason to install that tag separately.

Three techniques emitted telemetry their own catalog text denied

This is the class of defect that matters most here. Replicant's whole claim is that the telemetry is what the catalog says it is, so a detection validated against the wrong signal does not fail. It passes, and tells you nothing.

  • REP-024's relay lag was a constant one second at every preset. A floor-divide collapsed the shipped millisecond ranges to zero and a clamp made them one, so the technique whose stated purpose is defeating naive fixed-window timing correlation emitted precisely the fixed window it exists to defeat. Its benign foil used a fixed one-second offset on top of that. The lag is now drawn in float seconds with the sub-second remainder dithered onto the integer-second timeline, so the drawn variance survives with its expected value intact. Measured after the fix: gaps of 1, 2 and 3 seconds where only 1 existed.
  • REP-002 ignored its own window_s preset and --duration entirely. The builder read the port count and the inter-probe gap and nothing else, so the low preset finished in about six seconds against a declared 120-second window, roughly twenty times more aggressive than documented, and a one-hour duration override returned a byte-identical plan. Probes now spread across the window. Measured: spans of 119, 59 and 29 seconds against declared windows of 120, 60 and 30, and --duration 12s yields 20 probes across 11 seconds.
  • REP-014's benign foil was trivially separable on the technique's own primary feature. The catalog makes long session duration the property the miner and its foil share, and byte burstiness the thing that separates them. The foil topped out at a few minutes against a twelve-hour miner session, so a duration threshold alone scored perfectly, which is the shortcut the foil exists to deny. Measured after the fix: the foil spans 0.92 of one pool session at every preset, against 0.37, 0.046 and 0.010 before.

Two ATT&CK mappings that would mislead a detection engineer

  • REP-007 mapped T1110.004 Credential Stuffing, which MITRE defines as replaying breached credential pairs. Nothing in the builder models that. One user against many attempts is T1110.001 Password Guessing.
  • REP-012 mapped T1029 Scheduled Transfer, an Exfiltration technique, on a C2 beacon entry listing neither that tactic nor any transfer behavior. Wrong technique and wrong tactic; T1071 already carries the periodicity.

Three tactic lists also claimed a tactic none of their own techniques carry, and are corrected: REP-009, REP-017 and REP-018.

Smaller defects of the same family

REP-016's benign NXDOMAIN trickle ran past the window it is meant to blend into. REP-013's baseline servers could be drawn from the worm's own seed set, so a control could grow like the worm. Jitter above 100 percent produced negative intervals and backward timestamps. DNS labels were not clamped to the RFC 1035 63-octet limit. Catalog text had drifted from code in six places, and the README showed a different ATT&CK mapping for REP-007 than the catalog and CLI did.

The finding behind the findings

None of this was caught by 952 passing tests, because no test asserted that the code does what the catalog text promises. Every defect above sat in the gap between a documented distribution and the one actually emitted. Fourteen tests now close it, including one that fails CI if the README and the catalog disagree on any of the 24 entries.

Two conventions came out of it. The seed is part of a guard: a regression test whose seed happens to avoid the defect has never failed and is worth nothing, which is exactly what one of the incoming tests turned out to be. And a benign foil is a correctness requirement of the technique, not a decoration: two of the three behavioral defects were foils a detection could separate for free, on the very feature the foil exists to make indistinguishable. A foil that is trivially separable is worse than no foil, because it reports as coverage.

Also in this release, from v0.6.1

Every technique now draws its own signal path diagram in the web UI. The diagram previously mapped only REP-001 through REP-011 and silently fell back to the periodic-beacon glyph for everything newer, so a DGA cluster or an inbound perimeter scan rendered as a fixed-interval beacon with full confidence. Eight new glyphs, six honest reuses whose captions state their own story, and no fallback: an unmapped id renders a labelled gap, and a test reading the real catalog fails on any technique added without deciding its diagram.

Known behavior change

replicant run REP-002 --intensity low now occupies its full 120 seconds instead of finishing in about six. That is what the preset always declared.

Verified

968 Python tests and 170 frontend tests, black, ruff, mypy and tsc clean. Every new guard was run against the unfixed code and observed to fail before being trusted. The wheel attached here was built from a clean checkout of this tag and smoke-tested in an empty virtualenv outside the repository: version, catalog, a real FortiGate and Check Point CEF render, and the packaged UI, fonts and license texts all resolving from site-packages.

The credentials for every claim about timing and delivery remain loopback only. Replicant has still not been tested against a live LogRhythm collector.