Introduction
USB Human Interface Devices (HID), such as keyboards and mice, are implicitly trusted by modern operating systems.
This trust model enables seamless user interaction but also introduces a critical attack surface when abused.
This post documents an educational laboratory project based on a Raspberry Pi Pico, designed to study USB HID-based attack techniques in a controlled, ethical environment.
Rather than focusing on real-world exploitation, the goal is to understand the underlying mechanics, trust assumptions, and architectural decisions that make this attack vector possible.
Understanding these concepts is essential for both offensive and defensive security roles.
What is a USB HID device?
A USB HID device is a peripheral that sends input events directly to the operating system, such as:
- Keyboard keystrokes
- Mouse movements and clicks
- Media and system control commands
From the operating system’s perspective:
- HID devices are considered low-risk
- They do not require user confirmation
- They do not require additional drivers
This means that once a device identifies itself as a keyboard, its input is treated as legitimate user interaction.
This design choice prioritizes usability, but it also creates an implicit trust boundary between hardware and software.
Why HID-based attacks are possible
HID-based attacks exploit design assumptions, not software vulnerabilities.
The attack surface exists because:
- Physical devices are trusted by default
- No distinction exists between human and automated input
- Execution speed exceeds human capability
A device emulating a keyboard can execute complex command sequences before the user can react.
Educational lab setup
This lab uses a Raspberry Pi Pico / Pico W configured with:
- CircuitPython firmware
- Adafruit HID libraries
- Custom Python logic for payload parsing and execution
All experiments were conducted on owned systems in isolated environments.
Architecture overview
The project is logically divided into three execution phases.
Boot and setup phase
A GPIO-controlled setup mode determines whether the device exposes its filesystem or executes payload logic.
Main execution flow
Device boot
→ Check setup mode
→ Select payload
→ Parse instructions
→ Execute keystrokes
if not setup_mode:
payload = select_payload()
execute_payload(payload)
else:
wait_for_user_configuration()
Payload parsing and execution
for instruction in payload:
if instruction.type == STRING:
keyboard.write(instruction.value)
elif instruction.type == KEY_COMBO:
keyboard.press(instruction.keys)
elif instruction.type == DELAY:
sleep(instruction.duration)
What this technique demonstrates
This lab highlights trust boundaries, physical access risks, and design assumptions in operating systems.
Mitigations and defensive measures
- USB device control policies
- Endpoint protection
- Physical security
- User awareness
Ethical considerations
All experiments were conducted responsibly in controlled environments.
Additional resources
The complete project, including implementation details and supporting files, is available on GitHub:
- GitHub repository: https://github.com/lameiro0x/pico-hid-security-lab
The repository contains the full lab setup and source code used for this educational study.
Credits
Inspired by https://github.com/dbisu/pico-ducky
Disclaimer
Educational purposes only.