Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
Pi-Zero-2W-Bad-USB — Richte deinen Pi Zero 2W als BadUSB ein | Kitploit
Tools/GitHubGitHub/psycostea/pi-zero-2w-bad-usb
Embedded-System-SicherheitExploitationScripting & AutomatisierungHardware-HackingCTFPenetrationstestsLernen & BildungRed TeamingPayload-Entwicklung
GitHubpsycostea/pi-zero-2w-bad-usb

Pi-Zero-2W-Bad-USB

Richte deinen Pi Zero 2W als BadUSB ein

372vor 2 MonatenVon Kitploit geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen
Repository anzeigen

Raspberry Pi Zero 2 W BadUSB HID Toolkit

Eine programmierbare BadUSB-/HID-Angriffsplattform auf Basis eines Raspberry Pi Zero 2 W. Der Pi präsentiert sich als USB-Verbundgerät (Composite Device) (Tastatur plus optionales, schreibgeschütztes Massenspeicher-Volume) und führt Ducky-Script-artige Payloads gegen den Host aus, an den er angeschlossen ist. Entwickelt für autorisierte Red-Team-Einsätze, Penetrationstests und CTFs.

⚠️ Rechtlicher Hinweis. Verwenden Sie das Gerät nur an Systemen, die Ihnen gehören oder für die Sie eine ausdrückliche schriftliche Testgenehmigung besitzen. Unbefugter Zugriff ist in den meisten Rechtsordnungen illegal, und so zu tun, als hätte man es nicht gewusst, hilft nicht weiter.


Inhaltsverzeichnis

  1. Funktionen
  2. So funktioniert es
  3. Hardware
  4. Installation
  5. Täglicher Betrieb
  6. Payloads schreiben
  7. Konfigurationsreferenz
  8. Architektur-Hinweise
  9. Tests
  10. Fehlerbehebung
  11. Repository-Struktur
  12. Danksagungen

Funktionen

  • Programmierbare Keystroke-Payloads in einem Ducky-Script-kompatiblen Dialekt.
  • Zuverlässige Host-Erkennung über den UDC-Zustand configured — keine fehlerhaften Payload-Auslösungen beim Booten.
  • „Reset zwischen Angriffen“, der auf Pi-Zero-2-W-Hardware tatsächlich funktioniert. Abziehen, wieder einstecken, erneut auslösen — kein Stromzyklus nötig.
  • Konfigurierbare Schutzmechanismen gegen Endlosschleifen, wenn das Gerät eingesteckt bleibt: Mindestintervall pro Auslösung und eine Ratenbegrenzung der Auslösungen pro Minute, beide per Umgebungsvariable überschreibbar.
  • Optionales Verbund-Massenspeicher-Gadget auf Basis einer flachen Image-Datei (standardmäßig schreibgeschützt — das Offenlegen Ihrer Live-SD-Karte war die alte, schwer zu debuggende Stolperfalle für Dateisystem-Korruption).
  • US- und UK-Tastaturlayouts, pro Payload über LAYOUT wählbar.
  • Variablen, IF / ELSE, WHILE, HOLD / RELEASE, INJECT_MOD, RANDOM_*-Generatoren, STRING_BLOCK / STRINGLN_BLOCK, DEFINE.
  • systemd-Integration mit ExecStop, das das Gadget sauber herunterfährt. Kein übrig gebliebener configfs-Zustand; ein Neustart des Dienstes funktioniert ohne Reboot.
  • udev-verwaltete Berechtigungen für /dev/hidg0 — keine weltweit beschreibbaren Geräteknoten.
  • pytest-Suite mit 34 Tests für den Ducky-Parser, auf jedem Host ohne angeschlossenen Pi ausführbar.
  • ACT-LED-Statusanzeige nach jedem Payload-Lauf.

So funktioniert es

root@kitploit:~
+----------------+        USB cable        +-------------+
|  Raspberry Pi  | ===================>>>  |  Host PC    |
|  Zero 2 W      |   (Pi emulates HID +    |  (target)   |
|  (this device) |    optional drive)      |             |
+----------------+                         +-------------+
        |
        |  /home/pi/pi-badusb/
        |
        +-- badusb.service ----> monitor_and_run.py
                                   |
                                   |  on `state == configured`:
                                   v
                                 run_payload.py
                                   |
                                   v
                                 /dev/hidg0  (USB HID gadget)
  1. Beim Booten führt die systemd-Unit badusb.service gadget_setup.sh aus, das über configfs/libcomposite ein USB-Gadget mit einer HID-Tastaturfunktion und (optional) einer Massenspeicher-LUN zusammensetzt, die von einer flachen Image-Datei unter /var/badusb/storage.img gespeist wird.
  2. Die Unit führt dann monitor_and_run.py aus. Sie pollt /sys/class/udc/<udc>/state und wartet auf configured — den USB-Spezifikationszustand, der bedeutet, dass ein Host das Gadget erfolgreich enummeriert hat. (Wir verwenden nicht die Existenz von /dev/hidg0 als Signal: die ist bereits in dem Moment gegeben, in dem das Gadget beim Booten an die UDC gebunden wird, unabhängig davon, ob etwas eingesteckt ist.)
  3. Wenn der Host angeschlossen wird, führt der Listener run_payload.py aus, das payload.txt parst und HID-Reports an /dev/hidg0 schreibt.
  4. Wenn der Payload abgeschlossen ist, der Listener das Gadget von der UDC (der Pi Zero 2 W kann ein physisches Trennen nicht per Software erkennen — siehe ), wartet eine Abklingzeit ab und bindet erneut. Das Gerät wartet dann auf den nächsten -Übergang.

Hardware

KomponenteHinweis
Raspberry Pi Zero 2 WGetestet mit der Hardware-Revision von 2026-05. Der ältere Pi Zero W mit dem BCM2835-dwc_otg-Treiber funktioniert prinzipiell ebenfalls, aber dieses README setzt den 2 W mit dwc2 voraus.
micro-USB-auf-USB-A-KabelOder ein Adapter im „USB-Stick“-Formfaktor, mit dem der Pi direkt in einen Host-Port gesteckt werden kann.
Optional: separates NetzteilWenn Sie den Pi aus einer Nicht-Host-Quelle mit Strom versorgen möchten, damit der Listener booten kann, bevor er in ein Zielgerät eingesteckt wird (andernfalls liefert der Host-Port den Strom).

Der Pi Zero 2 W hat zwei micro-USB-Ports:

  • PWR IN — nur Strom, legt keine USB-Datenleitungen an den dwc2-OTG-Block.
  • USB — der OTG-Datenport; hier stecken Sie das Gerät in das Zielgerät.

Software


Installation

Klonen oder kopieren Sie das Repository auf den Pi und führen Sie dann den Installer aus:

root@kitploit:~
git clone http://your-gitea/admin/Pi-Zero-2W-Bad-USB.git /home/pi/pi-badusb
cd /home/pi/pi-badusb
sudo ./install.sh
sudo reboot

Nach dem Neustart den Dienst aktivieren und starten:

root@kitploit:~
sudo systemctl enable --now badusb.service
journalctl -u badusb -f

install.sh ist idempotent — führen Sie es erneut aus, wenn Sie Projektdateien ändern. Es:

  • Erkennt /boot/firmware (Bookworm+) gegenüber /boot (älter).
  • Stellt sicher, dass dtoverlay=dwc2,dr_mode=otg unter einem [all]-Block in config.txt aktiv ist. Die Standardeinstellungen des Raspberry Pi Imagers setzen diese Zeile in einen [cm5]-Filter, der auf dem Pi Zero 2 W nicht greift; der Installer fügt einen mit Sentinel markierten Override hinzu, damit erneute Ausführungen ihn nicht duplizieren.
  • Stellt sicher, dass modules-load=dwc2 in cmdline.txt steht.
  • Warnt, wenn g_ether noch in cmdline.txt vorhanden ist (es entzieht libcomposite die UDC und bricht den Gadget-Modus).
  • Installiert die systemd-Unit unter /etc/systemd/system/badusb.service.
  • Installiert die udev-Regel unter , sodass von der Gruppe beschreibbar ist.

Täglicher Betrieb

root@kitploit:~
# Start / stop / restart
sudo systemctl start badusb
sudo systemctl stop badusb
sudo systemctl restart badusb              # safe to do while plugged in

# Watch live
journalctl -u badusb -f

# Disable autostart on boot
sudo systemctl disable badusb

# Tune timings (creates an override drop-in)
sudo systemctl edit badusb
# (paste an [Service] block with Environment="BADUSB_REARM_COOLDOWN_S=8" etc)
sudo systemctl restart badusb

Der Dienst hängt von sys-kernel-config.mount und dem Vorhandensein einer UDC ab, sodass er keine Payloads auslösen kann, bevor das Gadget tatsächlich bereit ist.

Das Bearbeiten des Payloads erfordert keinen Neustart — payload.txt wird bei jedem Einstecken neu gelesen.


Payloads schreiben

payload.txt liegt im Installationsverzeichnis. Die vollständige Befehlsreferenz finden Sie in payload_commands.md.

Minimalbeispiel

root@kitploit:~
REM Open Run dialog and type a greeting via Notepad
LAYOUT US
GUI r
DELAY 1500
STRING notepad
ENTER
DELAY 2500
STRINGLN Hello from the Pi Zero 2 W

Variablen, Bedingungen, Schleifen

root@kitploit:~
VAR $USER="alice"
VAR $COUNT=0
WHILE $COUNT < 3
  STRINGLN Hello $USER (iteration $COUNT)
  VAR $COUNT = $COUNT + 1
END_WHILE

IF $USER == "alice"
  STRINGLN matched
ELSE
  STRINGLN missed
END_IF

Mathematische Ausdrücke in VAR durchlaufen einen sicheren ast-Walker-Evaluator — keine Namen, keine Aufrufe, kein Attributzugriff, nur numerische Literale und + - * / // % **.

Modifikatoren gedrückt halten

root@kitploit:~
HOLD SHIFT
STRINGLN this line is in capitals
RELEASE SHIFT

Beliebige Modifikatorkombinationen senden

root@kitploit:~
REM Hold Ctrl+Shift (0x01 + 0x02) and tap A
INJECT_MOD 0x03
STRING a
REM Release all modifiers
INJECT_MOD 0x00

Zufallsgenerierung

root@kitploit:~
RANDOM_LETTER 12      # 12 random mixed-case letters
RANDOM_NUMBER 6       # 6 random digits
RANDOM_SPECIAL 4      # 4 random ASCII symbols

Tastaturlayout

root@kitploit:~
LAYOUT UK             # switch to UK ISO mappings for subsequent STRING/STRINGLN
STRING @ " # ~ £ \ |  # types correctly on a UK-locale host

Legen Sie eine weitere Datei in keymaps/ ab (neben us.py und uk.py), und die Direktive LAYOUT <name> wird sie über importlib übernehmen.


Konfigurationsreferenz

Massenspeicher-Gadget (oben in gadget_setup.sh)

Diese Werte können pro Aufruf überschrieben werden, indem Sie sie beim manuellen Ausführen von gadget_setup.sh in der Umgebung setzen, oder global über die Environment=-Direktiven der Unit.

Listener-Einstellungen (monitor_and_run.py)

Überschreiben mit:

root@kitploit:~
sudo systemctl edit badusb
# In the editor:
# [Service]
# Environment="BADUSB_REARM_COOLDOWN_S=8"
# Environment="BADUSB_MIN_INTER_FIRE_S=20"
sudo systemctl restart badusb

Architektur-Hinweise

Warum der Listener den UDC-state verwendet, nicht /dev/hidg0

Die vorherige Implementierung nutzte die Existenz und Beschreibbarkeit von /dev/hidg0 als Signal für „Host angeschlossen“. Dieser Geräteknoten wird in dem Moment erstellt, in dem das Gadget beim Booten an die UDC gebunden wird — lange bevor ein Host es tatsächlich enummeriert hat. Dadurch wurden Payloads sofort beim Einschalten ausgelöst, unabhängig davon, wo der Pi eingesteckt war.

Das zuverlässige Signal ist /sys/class/udc/<udc>/state, das den Gerätezustand gemäß USB-Spezifikation meldet. Nur configured bedeutet, dass der Host SetConfiguration(1) ausgeführt hat — das Gerät ist nun berechtigt, HID-Reports zu senden.

Warum wir nach jedem Payload ein erzwungenes Unbind durchführen

Ein physisches Trennen beim Pi Zero 2 W zu erkennen ist aus der Software heraus unmöglich: Das Board verbindet keine VBUS-Sense-Leitung mit dem dwc2-OTG-Block des SoC. Nach einem physischen Abziehen:

  • /sys/class/udc/<udc>/state bleibt bei configured.
  • current_speed bleibt bei high-speed.
  • Das dwc2-GOTGCTL-Register bleibt bei 0x000d0000 (BSesVld-Bit gesetzt).
  • Es werden keine udev-Ereignisse ausgelöst.

Statt also auf ein Signal zu warten, das niemals kommen wird, verursacht der Listener das Trennen aktiv: Nach jedem Payload schreibt er "" in die UDC-configfs-Datei des Gadgets (was der Kernel als Unbind interpretiert), wartet BADUSB_REARM_COOLDOWN_S und schreibt dann den UDC-Namen zurück, um neu zu binden. Das nächste Einstecken des Hosts erzeugt einen sauberen configured-Übergang, den der Listener erkennen kann.

Wenn der Anwender den Pi nach einem Payload eingesteckt lässt, führt das Rebind dazu, dass der Host das Gadget neu enummeriert. Um eine außer Kontrolle geratene Auslöseschleife zu verhindern, greifen zwei Schutzmechanismen:

  1. BADUSB_MIN_INTER_FIRE_S — wenn ein configured-Übergang innerhalb dieses Fensters nach der vorherigen Auslösung passiert, wird er unterdrückt und erneut entbunden. Das Gadget durchläuft den Zyklus still im Hintergrund.
  2. BADUSB_MAX_FIRES_PER_MINUTE — harte Obergrenze mit gleitendem Fenster. Über der Obergrenze pausiert der Listener für BADUSB_RATELIMIT_PAUSE_S und protokolliert eine Warnung.

Warum wir auf configfs niemals rm -rf verwenden

Die vom Kernel verwalteten Attributdateien von configfs (bcdUSB, idVendor, webusb/*, os_desc/*, …) können nicht mit rm(2) entfernt werden — der Kernel gibt EPERM zurück. Sie werden nur freigegeben, wenn ihr übergeordnetes Verzeichnis per rmdir entfernt wird. Sowohl gadget_setup.sh als auch teardown_gadget.sh durchlaufen den configfs-Baum in kanonischer libcomposite-Reihenfolge — nur rmdir, niemals rm auf Attributdateien — und der Kernel räumt den Rest automatisch auf.

Warum die Python-Helfer os.write statt file.write verwenden

Das Schreiben eines leeren Strings über open(path, "w").write("") ruft write(2) nicht mit null Bytes auf — CPythons TextIOWrapper verschluckt den Aufruf. Für das configfs-Unbind (das der Kernel aus einem Schreibvorgang ableitet, der nach dem Entfernen von Zeilenumbrüchen eine Länge von null aufweist) verwenden wir direkt os.write(fd, b"\n"), sodass der Syscall immer mit mindestens einem Byte ausgeführt wird.


Tests

Der Ducky-Parser verfügt über eine pytest-Suite mit 34 Tests, die gegen eine MockHIDEngine läuft (ein In-Memory-Ersatz für den echten HID-Writer). Sie benötigt also keinen Pi und keine USB-Hardware.

root@kitploit:~
cd /home/pi/pi-badusb
python3 -m pytest tests/

Die Abdeckung umfasst:

  • safe_eval_math, das Arithmetik akzeptiert und Namen / Aufrufe / Attributzugriffe / String-Konstanten ablehnt.
  • evaluate_condition für numerische und case-sensitive String-Vergleiche.
  • VAR mit =, +=, -=, *=, /=.
  • IF / ELSE / END_IF, das den korrekten Zweig nimmt.
  • WHILE / END_WHILE-Iterationszahlen für < und <=.

Fehlerbehebung

„Payload feuert beim Einstecken nicht“

  1. cat /sys/class/udc/*/state — muss configured erreichen, wenn der Host enummeriert. Wenn es bei not attached bleibt, kommuniziert der Host nicht: Probieren Sie ein anderes Kabel (manche sind reine Ladekabel) oder einen anderen Host-Port.
  2. lsmod | grep dwc2 — muss geladen sein. Wenn nur dwc_otg vorhanden ist, greift dtoverlay=dwc2,dr_mode=otg nicht; führen Sie install.sh erneut aus und starten Sie neu.
  3. journalctl -u badusb -f während des Einsteckens — sollte innerhalb von ~2 s nach der Host-Enumeration Host attached. Running payload. anzeigen.

„Payload feuert in einer Schleife mit blinkender LED, sogar im ausgesteckten Zustand“

Das war ein echter Bug, der inzwischen behoben ist. Wenn es passiert, haben Sie auf einen Stand vor os.write zurückgesetzt. Stellen Sie sicher, dass monitor_and_run.py dem aktuellen main-Branch entspricht (suchen Sie nach os.write(fd, payload)).

„Dienst lässt sich nicht neu starten — Operation not permitted“

Das gadget_setup.sh vor der Korrektur verwendete rm -rf auf configfs. Die aktuelle Version verwendet teardown_gadget() — wenn Sie diese Fehler sehen, haben Sie eine alte Kopie. Stellen Sie den aktuellen Stand von main bereit.

„Permission denied auf /dev/hidg0“

Die udev-Regel benötigt ein Hotplug-Ereignis, um wirksam zu werden, oder sudo udevadm trigger und eine erneute Anmeldung, damit der Benutzer pi die Gruppenmitgliedschaft in plugdev übernimmt.

„g_ether-Warnung während der Installation“

Entfernen Sie g_ether aus cmdline.txt; es beansprucht die UDC, bevor libcomposite binden kann.

„Der Host zeigt ein USB-Laufwerk an, aber nicht in der erwarteten Größe“

Die Massenspeichergröße wird über BACKING_SIZE_MB festgelegt und wirkt nur beim ersten Lauf, wenn das Backing-Image erstellt wird. Zum Ändern der Größe:

root@kitploit:~
sudo systemctl stop badusb
sudo rm /var/badusb/storage.img
sudo BACKING_SIZE_MB=256 /home/pi/pi-badusb/gadget_setup.sh
sudo systemctl start badusb

„Ich möchte den Pi eingesteckt lassen, ohne dass er den Host zuspammt“

Genau dafür gibt es BADUSB_MIN_INTER_FIRE_S und BADUSB_MAX_FIRES_PER_MINUTE. Erhöhen Sie sie über systemctl edit badusb. Mit den Standardwerten feuert ein eingesteckt gelassener Pi in der ersten Minute etwa alle ~15 s erneut, pausiert dann 60 s und setzt danach fort.


Repository-Struktur

root@kitploit:~
.
├── README.md                   This file
├── LICENSE                     MIT
├── install.sh                  Idempotent installer (firmware config, systemd, udev, plugdev)
├── gadget_setup.sh             Composes the USB gadget via configfs/libcomposite
├── teardown_gadget.sh          Canonical configfs teardown (wired as ExecStop)
├── reload_gadget.sh            Manual UDC unbind/rebind helper
├── autorun.sh                  Legacy manual-launch wrapper (systemd is preferred)
├── monitor_and_run.py          Listener: waits for host attach, runs payload, forces re-arm
├── run_payload.py              Ducky-Script-style interpreter
├── payload.txt                 Your payload — edit freely; re-read on each plug-in
├── payload_commands.md         Full command reference
├── etc/
│   ├── badusb.service          systemd unit
│   └── 99-badusb-hidg.rules    udev rule for /dev/hidg0 ownership
├── keymaps/
│   ├── __init__.py             Dynamic layout loader
│   ├── us.py                   US ANSI (default)
│   └── uk.py                   UK ISO
└── tests/
    ├── __init__.py
    ├── conftest.py             pytest path setup
    └── test_parser.py          34 parser tests against a MockHIDEngine

Danksagungen

  • Ursprüngliche Projektskripte und Inspiration: Psycostea.
  • USB-Gadget-Recherche: USB Rubber Ducky, Hak5, libcomposite-Dokumentation und der dwc2-Kerneltreiber.
  • Korrektur-Durchgang 2026-05: Host-Erkennung neu geschrieben, Massenspeicher sicher gemacht, mehrere Parser-Bugs behoben, eine Keymap-Abstraktion hinzugefügt, den Start auf systemd migriert, das Unit-Test-Gerüst ergänzt und die hardwarebedingte Unfähigkeit des Pi Zero 2 W, ein physisches Trennen zu erkennen, umgangen.

Lizenz

MIT — siehe LICENSE.

Tool herunterladen
entbindet
aktiv
Architektur-Hinweise
configured
AnforderungGrund
Raspberry Pi OS (Debian Bookworm oder Trixie, 64-Bit-Lite empfohlen)Das Installationsskript schreibt auf Bookworm+ nach /boot/firmware/... und fällt bei älteren Images auf /boot/... zurück.
Python 3Ist in Pi OS enthalten.
mkfs.vfatZum Formatieren des Massenspeicher-Backing-Images beim ersten Lauf. Überspringbar, wenn Sie Massenspeicher deaktivieren.
Root-Zugriff für die EinrichtungModifiziert systemd, udev und /boot/firmware/config.txt.
/etc/udev/rules.d/99-badusb-hidg.rules
/dev/hidg0
plugdev
  • Fügt den Benutzer pi zur Gruppe plugdev hinzu.
  • Erstellt /var/badusb/ für das Massenspeicher-Backing-Image.
  • VariableStandardBedeutung
    ENABLE_MASS_STORAGE10 für ein reines HID-Gadget.
    BACKING_FILE/var/badusb/storage.imgFlache Image-Datei, die dem Host präsentiert wird.
    BACKING_SIZE_MB64Wird beim ersten Lauf erstellt, falls sie fehlt.
    BACKING_LABELBADUSBFAT-Volume-Label.
    MASS_STORAGE_RO1Standardmäßig schreibgeschützt.
    UmgebungsvariableStandardBedeutung
    BADUSB_POST_PAYLOAD_FLUSH_S0.5Schlafen nach dem Payload vor dem Unbind, damit HID-Schreibvorgänge abfließen können.
    BADUSB_REARM_COOLDOWN_S5Wie lange das Gadget für den Host zwischen Unbind und Rebind unsichtbar bleibt.
    BADUSB_MIN_INTER_FIRE_S10Mindestsekunden zwischen zwei Payload-Auslösungen; darunter wird die Auslösung unterdrückt und das Gadget erneut entbunden.
    BADUSB_MAX_FIRES_PER_MINUTE6Harte Obergrenze; darüber Pause für BADUSB_RATELIMIT_PAUSE_S.
    BADUSB_RATELIMIT_PAUSE_S60Pausendauer nach Auslösen des Rate-Limits.
  • Korrekte Längen bei RANDOM_*; RANDOM_<unknown> als No-op + Warnung.
  • Persistenz des INJECT_MOD-Modifikator-Bytes über nachfolgende Tastenanschläge hinweg.
  • HOLD SHIFT, das jedes Zeichen in STRINGLN abc großschreibt.
  • LAYOUT US vs. LAYOUT UK, die für @ und " unterschiedliche Reports erzeugen; ein unbekanntes Layout fällt auf das vorherige zurück.
  • STRING_BLOCK, das Zeilen verbindet; STRINGLN_BLOCK, das die Mindesteinrückung berücksichtigt.