Inocula: Weaponize the Trust Graph. Then Inoculate It.
Inspiration
Modern laptops are fortresses. Firewalls, sandboxing, and encrypted connections harden the perimeter.
But there is a blind spot nobody talks about: Bluetooth peripherals.
Once a device is paired, the operating system grants it permanent trust. No re-authentication. No verification. A mouse, keyboard, or headset all receive the same blind credential.
We set out to prove how fragile that assumption is, then build the system that fixes it.
The name comes from immunology. You expose the system to a controlled threat to build immunity. Inocula follows the same idea. We built the attack to build the defense.
What It Does
Inocula is a full-spectrum Bluetooth attack and defense lab running across three physical machines.
Raspberry Pi: The Scout
- Passive BLE scanning and classic Bluetooth probing
- GATT reads for device intelligence
- On-command MAC cloning using
btmgmt - Reports all scan data back to the C2
- Executes commands without hosting any inbound listener
Laptop B: The Attacker C2 (Inocula Orchestrator)
A Jac walker chain coordinates the entire operation:
- Polls the Pi for target liveness
- Selects attack strategy
- Enforces a 90-second cooldown
- Streams events to a live operator dashboard
Attack Tracks
Track NOISY
- Clones the victim mouse MAC address over BLE
- Creates two radios with the same identity
- Triggers duplicate-MAC and RSSI anomaly detectors
Track STEALTH
- Sends a network-triggered payload directly to the victim
- No Bluetooth activity
- No radio signals
- Bypasses all classical Bluetooth detection
Track BOTH
- NOISY triggers detection systems
- STEALTH delivers payload immediately after
- Simulates a real compound attack
Payload Behavior
- Opens Notepad with a prewritten file
- Launches Calculator
- Uses
SendInputwith focus-steal to bypass Windows 11 protections - Waits for 10 seconds of user inactivity before execution
Laptop A: The Victim (Inocula Sentinel)
The defended endpoint with a full SOC-style interface.
Each Bluetooth device becomes a node in a live trust graph. Detection logic is implemented as walkers traversing that graph.
Detection Signals
RSSI Anomaly
Detects signal strength deviation beyond ±2σTiming Anomaly
Flags abnormal reconnection latencyDuplicate Identity
Detects multiple devices using the same MACHID Profile Validation
Flags impossible behavior such as a mouse sending keyboard inputSleep Cycle Violation
Detects unrealistic wake timingNetworkSentinel
Identifies unauthorized inbound traffic and rogue listenersProcessSentinel
Detects suspicious process combinations and synthetic input bursts
Automated Response
When the threat score exceeds 0.70, the system executes:
BlockInput(True)to freeze HID inputpnputil /remove-deviceto unbind the deviceLockWorkStation()to secure the sessionnetsh advfirewallto block malicious portstaskkillto terminate rogue processes
Response time: ~15 ms from first malicious input
An attacker may land only 1 to 3 characters. That is not enough to execute a meaningful payload.
AI Threat Analysis
A Claude-powered ThreatAnalyst walker:
- Aggregates all signal scores
- Classifies the attack
- Estimates attacker proximity
- Produces remediation steps
This is implemented using by llm(), where the function signature defines the behavior. No manual prompt engineering is required.
How We Built It
Jac 0.13.5 End to End
- Graph traversal is the detection algorithm
- Walkers serve as both logic and API endpoints
walker:pubautomatically exposes endpoints- Frontend calls backend with
root spawn walker_name()
No REST boilerplate. One language across the entire stack.
jac-client Frontend
cl {}blocks compile directly to React- Shared component system across Sentinel and C2 dashboards
- Each machine runs a single
main.jacfile - Compiler separates client and server automatically
AI Integration
by llm()powers threat classification, risk scoring, and remediation- Each stage feeds into the next
- Type signatures define behavior instead of prompts
Real Hardware Integration
- Windows Bluetooth enumeration via WinRT APIs
- PowerShell STA adapter for async calls
- BLE scanning with
bleak - MAC cloning via
btmgmton Raspberry Pi - Tested with real devices (mouse and earbuds)
Cross-Machine Protocol
- Shared
X-Inocula-Tokenauthentication - Strict JSON contracts
- Retry logic in integration layer
Challenges
Jac Syntax Migration
- Major syntax changes caused 140+ errors
- Edge traversal and imports required full refactoring
- Graph initialization patterns changed completely
Root Isolation
- Each API request had its own root
- Graph state did not persist
- Solved with lazy initialization:
can ensure_graph() {
if not has_node(LaptopNode) {
rebuild_demo_graph();
}
}
Built With
- bleak
- bluetooth
- btmgmt
- byllm()
- claude
- claude-api
- jac
- jac-0.13.5
- jac-client
- jaseci
- lucide
- pnputil
- powershell
- python
- raspberry-pi
- react
- recharts
- sendinput
- vite
- windows-11
- winrt
Log in or sign up for Devpost to join the conversation.