{"id":51595170,"url":"https://github.com/securityronin/usb-forensic","last_synced_at":"2026-07-11T18:01:38.457Z","repository":{"id":370632296,"uuid":"1295324380","full_name":"SecurityRonin/usb-forensic","owner":"SecurityRonin","description":"USB device-history forensic correlation engine — reconstructs USB connection history from Windows registry/SetupAPI/event-log/LNK artifacts and scores cross-source timestamp consistency. Pipeline-native, reproducible, panic-free.","archived":false,"fork":false,"pushed_at":"2026-07-10T01:01:49.000Z","size":693,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-10T01:09:46.698Z","etag":null,"topics":["dfir","digital-forensics","forensics","incident-response","registry","rust","timeline","usb","usb-forensics","windows"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SecurityRonin.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":"docs/roadmap.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-07-09T13:54:57.000Z","updated_at":"2026-07-10T01:01:38.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/SecurityRonin/usb-forensic","commit_stats":null,"previous_names":["securityronin/usb-forensic"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/SecurityRonin/usb-forensic","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SecurityRonin%2Fusb-forensic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SecurityRonin%2Fusb-forensic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SecurityRonin%2Fusb-forensic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SecurityRonin%2Fusb-forensic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SecurityRonin","download_url":"https://codeload.github.com/SecurityRonin/usb-forensic/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SecurityRonin%2Fusb-forensic/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35370428,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-11T02:00:05.354Z","response_time":104,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dfir","digital-forensics","forensics","incident-response","registry","rust","timeline","usb","usb-forensics","windows"],"created_at":"2026-07-11T18:01:36.673Z","updated_at":"2026-07-11T18:01:38.450Z","avatar_url":"https://github.com/SecurityRonin.png","language":"Rust","funding_links":["https://github.com/sponsors/h4x0r"],"categories":[],"sub_categories":[],"readme":"# usb-forensic\n\n[![CI](https://github.com/SecurityRonin/usb-forensic/actions/workflows/ci.yml/badge.svg)](https://github.com/SecurityRonin/usb-forensic/actions)\n[![Rust 1.81+](https://img.shields.io/badge/rust-1.81%2B-orange.svg)](https://www.rust-lang.org)\n[![unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance)\n[![License: Apache-2.0](https://img.shields.io/badge/License-Apache--2.0-blue.svg)](LICENSE)\n[![Sponsor](https://img.shields.io/badge/sponsor-h4x0r-ea4aaa?logo=github-sponsors)](https://github.com/sponsors/h4x0r)\n\n**The first USB-history correlation engine built for pipelines and courtrooms rather than a viewer window — USB Detective-grade Windows artifact depth, running headless on any OS at fleet scale, with every timestamp traceable to its raw bytes and every conclusion re-derivable by anyone, including the other side's expert.**\n\n\u003e **Status: working alpha.** The correlation core, two sources (`setupapi.dev.log` via\n\u003e `peripheral-core`, `.lnk` via `lnk-core`), `forensicnomicon` findings output, and the\n\u003e `usb4n6` CLI all run and are tested. The registry decoder (USBSTOR/SCSI/USB) is\n\u003e [validated and in review](https://github.com/SecurityRonin/peripheral-forensic/pull/1);\n\u003e event-log, macOS/Linux, and court-report output are next (`docs/roadmap.md`,\n\u003e `docs/feature-parity.md`). `Cargo.toml` keeps `publish = false` until the source set\n\u003e and validation are release-ready; crates.io / docs.rs / coverage badges join then.\n\n## Run it\n\n```console\n$ usb4n6 path/to/setupapi.dev.log path/to/RecentItem.lnk\n{\"device\":\"7\u002612a3b4c5\u00260\u00260000\",\"attributes\":[{\"attribute\":\"FirstConnected\",\"consistency\":\"SingleSource\",\"values\":[{\"value\":{\"Timestamp\":1681760520},\"provenance\":{\"source\":\"SetupApi\",\"locator\":\"setupapi.dev.log:27\"}}]}]}\n{\"device\":\"DEAD-BEEF\",\"attributes\":[{\"attribute\":\"AccessedFile\",\"consistency\":\"SingleSource\",\"values\":[{\"value\":{\"Text\":\"E:\\\\payload.exe\"},\"provenance\":{\"source\":\"Lnk\",\"locator\":\"RecentItem.lnk\"}}]}]}\nusb4n6: 6 device(s) from 6 source record(s), 0 finding(s)\n```\n\nEach device history is one JSONL object carrying every value with its source and\nlocator; findings (cross-source conflicts and corroborations) print to stderr.\n\n## What this is\n\nA thin **orchestration / correlation** crate — it parses no raw format itself. It\nconsumes the fleet's already-built reader crates, normalizes their output into one\nuniform USB-device-history event, and cross-correlates the timestamps across sources,\nreporting each value as *consistent with* or *not consistent with* the others so an\nexaminer can tell a reliable first-connected time from a partial or contradicted one.\n\nUSB history is a **multi-source artifact domain**, not a single-parser job. On Windows\nthe evidence is spread across:\n\n- **Registry** — `USBSTOR`, `Enum\\USB`, `MountedDevices` (SYSTEM); Windows Portable\n  Devices / `WPDBUSENUM`, `VolumeInfoCache` (SOFTWARE); `MountPoints2` (NTUSER.DAT);\n  `Amcache.hve` (execution / first-seen signal)\n- **`Enum\\SCSI`** — UASP / USB-3 drives (`uaspstor.sys`, Win8+) enumerate here, **not**\n  under `USBSTOR`; a correlator reading only `USBSTOR` silently misses the modern drives\n  most likely to matter in an exfiltration case\n- **SetupAPI** device-install logs (`setupapi.dev.log`) — local time, no TZ marker\n- **Event Logs** (the Partition/Diagnostic log for volume serial numbers)\n- **LNK files, jump lists, shellbags** — files opened and directories touched on the device\n\n## Where it sits in the fleet\n\nAn **artifact-domain analyzer**, a layer above the data-source parsers — it **consumes**\nthem rather than reimplement them, and emits `forensicnomicon::report::Finding`s that\nIssen renders alongside every other analyzer.\n\n```\nusb-forensic  ── correlates USB device history, scores cross-source timestamp consistency\n   ├── consumes winreg-artifacts  ── USBSTOR / MountedDevices / WPDBUSENUM / Amcache / …\n   ├── consumes peripheral-core   ── setupapi.dev.log device-install events\n   ├── consumes winevt-forensic   ── Partition/Diagnostic event log (volume serials)\n   └── consumes lnk-core          ── recent-file LNK volume-serial join\n```\n\nIt is the deep, USB-specific sibling of\n[`useract-forensic`](https://github.com/SecurityRonin/useract-forensic): that crate\ntreats a device connection as one input to a broad user-activity timeline;\n`usb-forensic` is the focused consistency-scoring engine for the USB domain itself.\n\n## Why build it — the whitespace (adversarially pressure-tested)\n\nThe reference product is [USB Detective](https://usbdetective.com/): Windows-only,\nclosed-source, GUI, ~6 years mature. Its moat is **cross-source timestamp consistency\nscoring + per-value provenance** — the defensibility an expert witness needs.\n\nAn earlier draft of this thesis claimed we could go *cross-platform with the same\nconfidence model* and be \"better.\" A deep analysis (Fable 5) and a hostile critique\n(Codex) both rejected that. What survives:\n\n**Rejected — not the wedge:**\n\n1. **\"Same confidence model on macOS/Linux\" is illusory.** Consistency scoring needs\n   several *independent, persistent* sources with different update semantics to\n   cross-check — a Windows-specific property. macOS ≈ one strongly timestamped source\n   (unified logs / USBMSC, days-to-weeks retention) plus name-only plists; Linux ≈\n   single-source journald. With 1–2 sources there is nothing to score against.\n2. **\"Match USB Detective on Windows\" is not a cheap phase 1.** The scoring *algorithm*\n   is a weekend; the semantic model under it (per-build timestamp-rewrite quirks,\n   `Enum\\SCSI`/UASP coverage, Win10 30-day cleanup, local-vs-UTC traps) is ~12–24 months\n   of corpus-driven differential validation.\n3. **\"Open-source = court-defensible\" is narrow.** Courts admit closed tools under\n   Daubert routinely; source availability aids *testimony*, not admissibility (and it\n   hands the opposing expert your bug tracker).\n\n**The actual wedge — structural, not feature gaps the incumbent can patch:**\n\n1. **Form factor USB Detective cannot match without ceasing to be itself:** headless,\n   library-embeddable, pipeline-native, diffable JSONL, running on any OS to analyse\n   *Windows* evidence at fleet scale. Nothing open does scored multi-source USB\n   correlation as a CLI/library (RegRipper = raw plugins; USBFT = unscored GUI).\n2. **Reproducibility by construction** — a `--reproduce` mode re-deriving every value\n   from `hive → key → raw bytes → decoding rule`, hashable and runnable by the opposing\n   expert. The durable half of \"court-ready\"; the PDF/DOCX *format* is a weekend feature.\n3. **The customer is the pipeline operator, not the GUI examiner** (who has a free\n   Community edition and zero switching pressure): lab automation, Velociraptor/KAPE,\n   fleet integration. Smaller, quieter market — infrastructure, not a hero product.\n\nFull landscape, sources, and competitor matrix:\n[`docs/competitive-landscape.md`](docs/competitive-landscape.md). Build sequence:\n[`docs/roadmap.md`](docs/roadmap.md).\n\n## Kill criteria — build only if none of these trip\n\n1. **The 80%-clone trap.** Community edition is free; a 90%-of-Windows clone offers the\n   examiner nothing. The only viable sequencing is the **inverse**: ship the\n   pipeline/library form factor first (zero incumbent there), let Windows depth accrete\n   under differential test.\n2. **No sustained validation corpus.** An unvalidated correlator is a liability\n   generator — a miscorrelation that flags a legitimate timestamp, in a report with the\n   examiner's name on it, is worse than no tool. v1 must say \"consistent with / not\n   consistent with\" and **refuse** \"spoofed.\" Requires a maintained XP→11 image corpus\n   with documented ground truth.\n3. **Can't generalize past USB.** Rational only as the fleet's **first general\n   artifact-domain correlation engine**, not a one-off USB tool.\n\nUseful lever: **USB Detective Community edition is a free differential oracle** — run\nboth over the same evidence; every disagreement is either a bug or a documentable edge\ncase, converting the incumbent's moat into the test suite.\n\n## Trust, but verify\n\n`#![forbid(unsafe_code)]`, panic-free (the workspace denies `unwrap`/`expect` in\nproduction), and gated on 100% library line coverage. The correlation logic will be\nvalidated **differentially against an independent oracle** (USB Detective Community\nedition, RegRipper) on real disk images — see\n[`docs/validation.md`](docs/validation.md). Findings are **observations**, never\nverdicts: \"consistent with …\", the examiner draws the conclusions.\n\n---\n\n[Privacy Policy](https://securityronin.github.io/usb-forensic/privacy/) · [Terms of Service](https://securityronin.github.io/usb-forensic/terms/) · © 2026 Security Ronin Ltd\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsecurityronin%2Fusb-forensic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsecurityronin%2Fusb-forensic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsecurityronin%2Fusb-forensic/lists"}