
Linux kernel-space HID injection attack detector using eBPF. Monitors USB and Bluetooth HID devices for anomalous keystroke timing and automatically unbinds malicious devices before attack completion.
See Why This Was Archived below.
A Linux kernel-space security monitor for detecting and blocking HID injection attacks (Rubber Ducky, O.MG Cable, ESP32-based keyboard emulators) using eBPF HID-BPF struct_ops.
Malicious HID devices emulate keyboards and inject keystrokes far faster than any human typist. This tool detects that timing anomaly and unbinds the offending device from the kernel HID driver before the attack completes.
On startup, the tool snapshots all currently connected HID devices and ignores them — only newly connected devices are monitored. It supports both USB and Bluetooth HID devices.
main — Working Proof of ConceptFunctional end-to-end pipeline, tested against an ESP32-based keyboard emulator:
struct_ops program to the discovered deviceKnown limitations that triggered the rewrite:
hid_id derived from the sysfs minor number, which is not stable across rebootsv0.1 — Clean Rewrite (Halted)Portable foundation built before re-wiring the BPF layer:
/sys/bus/hid/devices/hid_desc_parse.c) — device type identification not completedBoth branches hit the same wall: HID-BPF operates on raw byte arrays, so all descriptor parsing and device-type verification has to live in userspace regardless of how the detection logic is split. Rather than keep building that scaffolding from scratch, I moved to [udev-hid-bpf].
Malicious HID devices emulate keyboards and inject keystrokes far faster than any human typist. This tool detects that timing anomaly and unbinds the offending device from the kernel HID driver before the attack completes.
On startup, the tool snapshots all currently connected HID devices and ignores them — only newly connected devices are monitored. It supports both USB and Bluetooth HID devices.
main — Working Proof of ConceptFunctional end-to-end pipeline, tested against an ESP32-based keyboard emulator:
struct_ops program to the discovered deviceKnown limitations that triggered the rewrite:
hid_id derived from the sysfs minor number, which is not stable across rebootsv0.1 — Clean Rewrite (Active Development)Portable foundation being built before re-wiring the BPF layer:
/sys/bus/hid/devices/hid_desc_parse.c) — will identify device type before attaching┌─────────────────────────────────────────────────────┐
│ Userspace │
│ │
│ udev monitor → descriptor parse → keyboard? │
│ ↓ │
│ populate BPF config maps (thresholds, device info) │
│ ↓ │
│ attach HID-BPF struct_ops to hid_id │
│ ↓ │
│ ring buffer consumer → sysfs unbind on attack │
└──────────────────────────┬──────────────────────────┘
│
┌──────────────────────────▼──────────────────────────┐
│ BPF (kernel side) │
│ │
│ hid_device_event → timing math (Welford's online │
│ variance, fixed-point) → per-key timestamp maps │
│ → ring buffer submit on anomaly │
└─────────────────────────────────────────────────────┘
Detection logic moves into BPF. Userspace handles descriptor parsing, config map population, and the unbind response. The enumeration window between device connection and BPF attachment is a documented, bounded limitation — real-world HID injection tools include deliberate post-enumeration delays that this window falls within.
libbpf development headerslibelf and zlib development headersmake
# Auto-detect: plug in or pair the device when prompted
sudo ./hid_guard
# Manual override with known hid_id
sudo ./hid_guard <hid_id>
# List available HID devices
ls /sys/bus/hid/devices/
main.c)| Parameter | Default | Meaning |
|---|---|---|
ATTACK_MAX_MS | 5 ms |
ESP32-S2 was used for BLE keystroke transmission. Next, test with hardware like rubber ducky or ESP32-S3, targetting usb ports
GPL v2
| Inter-keystroke interval indicating injection |
HUMAN_MIN_MS | 30 ms | Minimum interval for human typing |
ALERT_THRESHOLD | 3 | Consecutive suspicious events before blocking |
| Component | State |
|---|
| Device enumeration | Done |
| Report descriptor read | Done |
| Descriptor parser (keyboard identification) | In progress |
| BPF config map population | Planned |
| HID-BPF struct_ops attachment | Done (main branch) |
| Timing detection (Welford variance, BPF-side) | Planned |
| Sysfs unbind blocking | Done (main branch) |