Skip to content

Repository files navigation

KeyWraith

Adaptive BadUSB/HID attack emulation + behavioral endpoint detection with the Flipper Zero.

A wraith typing at superhuman speed through the keyboard interface — the invisible injected-keystroke attacker. KeyWraith uses the Flipper Zero's USB-HID capability to build, then defeat, a keystroke-injection detector.

tests python license framing


One-line pitch

Turn a Flipper Zero into a controlled keystroke-injection adversary to build the labeled dataset nobody has, then train and stress-test a behavioral BadUSB detector — an end-to-end HID purple-team platform. The deliverable is a detector + explainable endpoint alert; the offensive emulation exists only to generate honest training data and to red-team the defense.

The problem

The Flipper Zero can present itself to a computer as a USB keyboard and "type" a scripted payload at machine speed (the classic Rubber Ducky / BadUSB attack). The OS trusts keyboards implicitly, so this bypasses most host defenses. The offensive side is well-trodden. The defensive side — reliably detecting that "the user" typing right now is actually an injection device, grounded in real behavioral data rather than device-ID allow-lists — is surprisingly thin.

KeyWraith builds both halves: a reproducible HID-injection emulator that manufactures a labeled injected-vs-human keystroke dataset, and a behavioral detector (the logic an EDR agent would run) that flags injection in real time from timing dynamics and produces an operator-readable alert. Then it closes the loop: can an adaptive attacker slow down and humanize the injection to evade the detector, and at what cost?

Why it's novel

  1. A labeled human-vs-injected keystroke dataset — including humanized attack variants — which is scarce. The methodology + dataset is itself a contribution.
  2. Behavioral BadUSB detection grounded in data, versus the usual device-ID/policy heuristics.
  3. The evasion arms race. Quantifying the detection-vs-humanization-cost tradeoff — how slow an attacker must go to look human, and whether that's still detectable — is a real research result, not just a classifier.
  4. Keystroke dynamics repurposed for defense, not biometrics. Usually studied for user authentication; here it distinguishes human vs machine injection.

Architecture

flowchart TB
    FZ["Flipper Zero<br/>BadUSB emulator<br/>(benign payloads)"] -->|HID keystrokes| HA
    HA["Host agent<br/>keystroke capture<br/>(timing, keycode class)"] --> CAP
    FZ -.->|emission log| CAP
    CAP["Capture + auto-labeling<br/>(align to Flipper ground truth)"] --> FE
    SYN["Synthetic stream generator<br/>human / burst / jittered / humanized"] --> FE
    FE["Feature extraction<br/>(IKI dist, cadence regularity,<br/>dwell, digraphs, corrections)"] --> DET
    ATK["Adaptive / humanized attacker"] -->|red-team| DET
    DET["Behavioral detector<br/>human vs injected"] --> ALERT["Endpoint alert +<br/>explanation (EDR-style)"]
    DET --> ARMS["Evasion cost study<br/>(arms race)"]
Loading

Full module map in docs/architecture.md.

Quickstart

# 1. install (Tier 1 needs no hardware, no human data)
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

# 2. end-to-end demo: trains the detector and prints live endpoint alerts
python -m keywraith.cli demo

# 3. regenerate every result artifact (metrics, figures, summary table)
python -m keywraith.cli report --outdir results

Or with make: make setup && make demo && make report. Run the tests with make test (30 tests).

Individual stages:

python scripts/generate_dataset.py --out data/sessions.ndjson --csv data/features.csv
python scripts/train_detector.py    --model random_forest --out models/detector.pkl
python scripts/evaluate.py          --out results/metrics.json
python scripts/evasion_arms_race.py --out results/arms_race.json
python scripts/make_figures.py      --outdir figures

More CLI commands:

python -m keywraith.cli adversarial   # evasion-aware retraining vs a standard detector (Tier 3)
python -m keywraith.cli stream        # real-time sliding-window detector: catch rate + time-to-detection
python -m keywraith.cli train --model gradient_boosting   # alternative model

Tiers

KeyWraith is scoped so the full research story runs in software, with hardware as an optional upgrade.

Tier Needs What it delivers
1 — software (default, in this repo) Python only Synthetic generator → features → detector → explainable alert, benchmarked against a naive speed-threshold baseline across humanization levels. A complete, novel result with no Flipper.
2 — hardware + human data Flipper Zero, consenting typists, pynput Wire in real injection (keywraith.host_agent + benign payloads, auto-labeled by keywraith.labeling) and real human captures; measure the sim-to-real gap. Same feature/detector code.
3 — research payoff Tier 1 The adaptive attacker and evasion arms race: sweep humanization, plot detection vs attacker throttle cost, test whether an evasion-aware retrained detector wins the round.

Headline results (Tier 1, seed 17)

Regenerate with python -m keywraith.cli report. Full numbers in results/results_summary.md and results/metrics.json.

Detection quality — behavioral detector vs the standard speed-threshold defense:

ROC and PR

Why it works — inter-key timing separates human from each injection mode:

IKI distributions

The evasion arms race (headline figure) — the detector holds full detection through humanization level 0.9 while the naive baseline collapses once the attacker slows down; full evasion costs the attacker a ~40× longer exposure window:

Evasion curve

Detection recall per injection mode — the baseline is defeated by humanization; the behavioral detector is not:

Per-mode recall

Winning the next round — evasion-aware retraining. A standard detector that only trained on weak humanization collapses once the attacker humanizes past ~0.5. An evasion-aware detector that also trained on strong humanization reclaims the lost region — up to 0.95 detection at humanization level 0.9 — with no increase in human false positives (both stay at FPR ≈ 0.00). Only full humanization (level 1.0, statistically indistinguishable from a human, at maximum attacker time cost) defeats both:

Evasion-aware retraining

Model ROC-AUC Precision Recall FPR
Behavioral detector 1.000 1.000 1.000 0.000
Speed-threshold baseline 0.997 0.995 0.951 0.004

On the fully-synthetic Tier 1 data the behavioral detector is near-perfect; the honest, interesting result is the arms-race curve, where it maintains detection long after the speed baseline is blind, and the cost the attacker pays to eventually evade it. Absolute numbers will move on real hardware — that sim-to-real gap is measured, not hidden.

Example endpoint alert

The defensive deliverable is an operator-readable alert. From keywraith.cli demo on a humanized injection (full sample):

========================================
  KEYWRAITH ENDPOINT ALERT  [CRITICAL]
========================================
verdict   : injected   (P(injected)=1.000)

summary:
  INJECTED keystroke stream: 240 keys in 40.49s (speed 5.9 cps), IKI CV 0.191
  vs human median 0.55, 0.0% corrections, 0% of keystrokes <20ms apart.

top contributing features:
  - dwell_std_ms      = 1.25    (pushes-injected)
  - dwell_mean_ms     = 9.42 ms (pushes-injected)
  - dwell_cv          = 0.13    (pushes-injected)
  - iki_iqr_ms        = 43.97   (pushes-injected)
  - typing_speed_cps  = 5.93    (pushes-human)     <- already looks human-paced

recommended action:
  Isolate the host session and review the connected HID device; correlate with
  USB enumeration logs at alert time.
========================================

Note how at humanization level 0.6 the speed already looks human (5.9 cps, a 40-second session) — a speed threshold is blind here — yet the machine-regular dwell time and low cadence variance still give the wraith away.

Real-time detection

Beyond scoring whole sessions, keywraith.stream.StreamDetector runs the detector the way an EDR would — over a sliding window of the most recent keystrokes, with alert debouncing so a single noisy window doesn't fire. Feed it live events one at a time (push) or scan a session offline (scan_session); the two paths are exactly equivalent. On the Tier 1 data it catches injection with a median time-to-detection of ~50 keystrokes, at a 0% human false-alarm rate (python -m keywraith.cli stream).

Feature set

19 timing/cadence features, chosen because human and injected typing separate along them. The scale-free regularity features (iki_cv, iki_autocorr_lag1, dwell_cv, digraph_var_ratio) are what keep the detector alive when an attacker simply slows down to beat a speed threshold. Full table: docs/feature_set.md.

Evaluation plan

  • Detection quality: ROC/PR and false-alarm rate vs a speed-threshold baseline.
  • Robustness: performance across injection modes and unseen humanization levels.
  • Sim-to-real: does a detector trained on synthetic hold up on shifted / real captures? Quantified (Tier 1 ships a shifted-profile proxy; Tier 2 uses real data).
  • Adversarial: the evasion arms race — attacker cost to evade, and whether retraining recovers detection.
  • False positives on real humans: fast/metronomic typists are the key deployability risk and are measured explicitly.

Security

Software-security posture (project responsible-use rules are in the threat model):

  • Tamper-evident models. scikit-learn models are pickles, and unpickling runs code. BehavioralDetector.save() writes a .sha256 sidecar; .load() verifies it by default and refuses a tampered, corrupt, or unverifiable model, and refuses trusted=False. Integrity, not authenticity — still only load models you trust.
  • Input validation on every prediction (shape + finite-value checks).
  • No network I/O, no secrets, no untrusted deserialization of data (datasets are plain numeric NDJSON/CSV). Raw human captures are git-ignored.
  • CI + CodeQL + Dependabot with least-privilege GITHUB_TOKEN permissions (.github/). See SECURITY.md for reporting.

Threat model & ethics

Defensive framing is central and binding. Injection is performed only against hosts the author owns; the repo ships no weaponized payloads (DuckyScripts are limited to benign, clearly-labeled marker strings), no turnkey attack tooling, and no real credentials. Human data is consented and stored only as de-identified timing features, never raw text. Read docs/threat_model.md before running any hardware.

Repository layout

keywraith/            core library (importable, tested)
  synthetic.py        human/machine keystroke stream generator
  attacker.py         adaptive humanized attacker + evasion cost
  features.py         behavioral feature extraction (19 features)
  detector.py         train / predict / explain / tamper-evident persist
  baseline.py         naive speed-threshold defense
  alert.py            EDR-style explainable endpoint alert
  stream.py           real-time sliding-window detector (online + offline)
  host_agent.py       Tier-2 live keystroke capture (optional pynput)
  labeling.py         Tier-2 emission-window auto-labeling
  experiments.py      train / evaluate / arms-race / adversarial / sim-to-real
  figures.py          all figures
  cli.py              command-line interface
scripts/              thin CLI wrappers for each stage
flipper/payloads/     benign, clearly-labeled DuckyScript test payloads
docs/                 threat model, feature set, dataset card, architecture
tests/                pytest suite (30 tests)
.github/              CI, CodeQL scanning, Dependabot
data/                 de-identified feature CSV + small session sample
figures/  results/    generated artifacts (regenerable)

Reading list

Flipper Zero BadUSB / DuckyScript documentation · HID keystroke injection (Rubber Ducky) attacks · keystroke-dynamics feature literature · USB/HID security and BadUSB mitigations · behavioral endpoint detection (EDR) concepts · adversarial evasion of behavioral detectors. This work sits where USB/HID hardware attacks meet behavioral ML detection meet endpoint defense.

Citation

See CITATION.cff.

Author

Krishita Sanjay Choksi (@Krishita17) — sole author and contributor. Released under the MIT License.

About

Adaptive BadUSB/HID attack emulation + behavioral endpoint detection with the Flipper Zero. Defensive-security research: build a labeled human-vs-injected keystroke dataset, train an EDR-style detector, and red-team it with an adaptive humanized attacker.

Topics

Resources

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages