Completes Phase 5. Half of a Linux compromise is not a file on disk, it is a line added to a startup file — a curl in a shell profile, a systemd unit with a dull name, one extra key in authorized_keys. The payload is often unremarkable; what makes it an incident is that it survives a reboot and nobody reads those files from one year to the next. So this is not a scanner but an inventory with a memory. It records systemd units (system and per-user), cron in all its locations, autostart entries, shell profiles, authorized_keys and ld.so.preload, then reports what CHANGED. Three decisions, all of which are the difference between a report people read and one they turn off: * Content is hashed, not stat'd. An mtime can be set backwards with one touch, and someone editing a startup file is exactly the person who would. Verified: a backdated edit is still caught. * A first run reports no changes and says so. Everything would be a change, and a first-run report full of alarms is one nobody reads. What a first run can honestly say is how many entries no package claims — 97 of 1,026 on this machine — because that is true regardless of history. * Writing the baseline is an explicit act (`--accept`, or update_baseline on the wire). A plain check must never quietly record whatever is currently installed as normal; that is how a compromise becomes the new baseline. Package ownership decides what is ordinary: a unit that arrived with a package is the system working, the same unit unowned is somebody's decision. Reuses the merged-/usr-aware index from the rootkit rewrite, with a test asserting most units resolve to a package — if that ratio collapses, ownership lookup has broken and the whole report is noise. Exercised end to end against this machine: baseline of 1,026 items, a planted user unit caught as ADDED, an in-place edit with a backdated mtime caught as CHANGED, and its deletion caught as REMOVED. The test artifact was removed afterwards. Cross-distro verification of the rootkit rewrite is now MET. Henry ran the suite on the Ubuntu box (26.04, glibc 2.43): 20/20, including both unowned_setuid_does_not_fire_on_a_healthy_system and no_false_positives_on_system_binaries. 214 tests pass across the workspace. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
20 MiB
Executable file
20 MiB
Executable file