Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
Pi-Zero-2W-Bad-USB — Configurez votre Pi Zero 2W en BadUSB | Kitploit
Outils/GitHubGitHub/psycostea/pi-zero-2w-bad-usb
Sécurité des Systèmes EmbarquésExploitationScripting et AutomatisationHacking MatérielCTFTests d'IntrusionApprentissage et ÉducationRed TeamingDéveloppement de Charges Utiles
GitHubpsycostea/pi-zero-2w-bad-usb

Pi-Zero-2W-Bad-USB

Configurez votre Pi Zero 2W en BadUSB

37218il y a 3 moisVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager
Voir le dépôt

Kit de Menace BadUSB HID pour Raspberry Pi Zero 2 W

Une plateforme programmable d'attaque BadUSB / HID construite sur un Raspberry Pi Zero 2 W. Le Pi s'énumère en tant que périphérique composite USB (clavier plus un volume de stockage de masse optionnel en lecture seule) et exécute des charges utiles de style Ducky-Script sur l'hôte auquel il est branché. Conçu pour des engagements d'équipe rouge autorisés, des tests de pénétration et des CTF.

⚠️ Avis légal. Utilisez uniquement sur des systèmes dont vous êtes propriétaire ou pour lesquels vous disposez d'une autorisation écrite explicite de test. L'accès non autorisé est illégal dans la plupart des juridictions, et faire semblant de l'ignorer ne vous aidera pas.


Table des matières

  1. Fonctionnalités
  2. Fonctionnement
  3. Matériel
  4. Installation
  5. Utilisation quotidienne
  6. Rédaction de charges utiles
  7. Référence de configuration
  8. Notes d'architecture
  9. Tests
  10. Dépannage
  11. Structure du dépôt
  12. Crédits

Fonctionnalités

  • Charges utiles de frappe programmables dans un dialecte compatible Ducky-Script.
  • Détection fiable de l'attachement hôte via l'état configured de l'UDC — pas de déclenchement intempestif de charge utile au démarrage.
  • "Réinitialisation entre les attaques" qui fonctionne réellement sur le matériel Pi Zero 2 W. Débranchez, rebranchez, tirez à nouveau — pas de cycle d'alimentation.
  • Protections configurables contre les boucles incontrôlées si l'appareil reste branché : intervalle minimum par tir et limite de tirs par minute, tous deux modifiables via des variables d'environnement.
  • Gadget de stockage de masse composite optionnel basé sur un fichier image plat (lecture seule par défaut — exposer votre carte SD live était l'ancien piège à corruption de système de fichiers difficile à déboguer).
  • Dispositions de clavier US et UK sélectionnables par charge utile avec LAYOUT.
  • Variables, IF / ELSE, WHILE, HOLD / RELEASE, INJECT_MOD, générateurs RANDOM_*, STRING_BLOCK / STRINGLN_BLOCK, DEFINE.
  • Intégration systemd avec ExecStop qui démonte proprement le gadget. Pas d'état résiduel de configfs, le redémarrage fonctionne sans redémarrer.
  • Permissions gérées par udev pour /dev/hidg0 — pas de nœuds de périphérique accessibles en écriture par tout le monde.
  • Suite de tests pytest de 34 tests pour l'analyseur Ducky, exécutable sur n'importe quel hôte sans Pi connecté.
  • Indicateur d'état via la LED ACT après chaque exécution de charge utile.

Fonctionnement

root@kitploit:~
+----------------+        Câble USB        +-------------+
|  Raspberry Pi  | ===================>>>  |  PC hôte    |
|  Zero 2 W      |   (Pi émule HID +       |  (cible)    |
|  (cet appareil)|    optionnel lecteur)   |             |
+----------------+                         +-------------+
        |
        |  /home/pi/pi-badusb/
        |
        +-- badusb.service ----> monitor_and_run.py
                                   |
                                   |  sur `state == configured` :
                                   v
                                 run_payload.py
                                   |
                                   v
                                 /dev/hidg0  (gadget HID USB)
  1. Au démarrage, l'unité systemd badusb.service exécute gadget_setup.sh, qui utilise configfs/libcomposite pour composer un gadget USB avec une fonction clavier HID et (optionnellement) un LUN de stockage de masse basé sur un fichier image plat à /var/badusb/storage.img.
  2. L'unité exécute ensuite monitor_and_run.py. Il interroge /sys/class/udc/<udc>/state et attend configured — l'état USB-spec qui signifie qu'un hôte a énuméré avec succès le gadget. (Nous n'utilisons pas l'existence de /dev/hidg0 comme signal : celui-ci est vrai dès que le gadget se lie à l'UDC au démarrage, qu'un câble soit branché ou non.)
  3. Lorsque l'hôte s'attache, l'écouteur exécute run_payload.py, qui analyse payload.txt et écrit des rapports HID vers /dev/hidg0.
  4. Lorsque la charge utile se termine, l'écouteur délie activement le gadget de l'UDC (le Pi Zero 2 W ne peut pas détecter une déconnexion physique par logiciel — voir ), attend un délai de refroidissement, puis relie. L'appareil attend ensuite la prochaine transition vers .

Matériel

ComposantRemarque
Raspberry Pi Zero 2 WTesté sur révision matérielle 2026-05. Les anciens Pi Zero W avec le pilote dwc_otg BCM2835 fonctionnent également en principe, mais ce README suppose un Zero 2 W avec dwc2.
Câble micro-USB vers USB-AOu un adaptateur au format "clé USB" qui permet de brancher le Pi directement sur un port hôte.
Optionnel : chargeur séparéSi vous voulez alimenter le Pi depuis une source non-hôte afin que l'écouteur puisse démarrer avant d'être branché sur une cible (sinon le port hôte fournit l'alimentation).

Le Pi Zero 2 W possède deux ports micro-USB :

  • PWR IN — alimentation uniquement, n'expose pas les lignes de données USB au bloc dwc2 OTG.
  • USB — le port de données OTG ; c'est là que vous branchez sur la cible.

Logiciel


Installation

Clonez ou copiez le dépôt dans le Pi, puis exécutez l'installateur :

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

Après redémarrage, activez et démarrez le service :

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

install.sh est idempotent — réexécutez-le à chaque modification des fichiers du projet. Il :

  • Détecte /boot/firmware (Bookworm+) vs /boot (plus ancien).
  • Vérifie que dtoverlay=dwc2,dr_mode=otg est actif sous un bloc [all] dans config.txt. Les valeurs par défaut de Raspberry Pi Imager placent cette ligne dans un filtre [cm5] qui ne s'applique pas sur Pi Zero 2 W ; l'installateur ajoute une surcouche marquée par un repère pour que les réexécutions ne la dupliquent pas.
  • Vérifie que modules-load=dwc2 est présent dans cmdline.txt.
  • Avertit si g_ether est toujours présent dans cmdline.txt (il vole l'UDC à libcomposite et casse le mode gadget).
  • Installe l'unité systemd dans /etc/systemd/system/badusb.service.
  • Installe la règle udev dans /etc/udev/rules.d/99-badusb-hidg.rules pour que soit accessible en écriture par le groupe .

Utilisation quotidienne

root@kitploit:~
# Démarrer / arrêter / redémarrer
sudo systemctl start badusb
sudo systemctl stop badusb
sudo systemctl restart badusb              # sûr à faire pendant que le câble est branché

# Voir les logs en direct
journalctl -u badusb -f

# Désactiver le démarrage automatique au boot
sudo systemctl disable badusb

# Régler les temporisations (crée un fichier de remplacement)
sudo systemctl edit badusb
# (collez un bloc [Service] avec Environment="BADUSB_REARM_COOLDOWN_S=8" etc.)
sudo systemctl restart badusb

Le service dépend de sys-kernel-config.mount et de la présence d'un UDC, il ne peut donc pas déclencher de charges utiles avant que le gadget ne soit effectivement prêt.

Modifier la charge utile ne nécessite pas de redémarrage — payload.txt est relu à chaque branchement.


Rédaction de charges utiles

payload.txt se trouve dans le répertoire d'installation. La référence complète des commandes se trouve dans payload_commands.md.

Exemple minimal

root@kitploit:~
REM Ouvrir la boîte de dialogue Exécuter et taper un message via le Bloc-notes
LAYOUT US
GUI r
DELAY 1500
STRING notepad
ENTER
DELAY 2500
STRINGLN Bonjour depuis le Pi Zero 2 W

Variables, conditionnelles, boucles

root@kitploit:~
VAR $USER="alice"
VAR $COUNT=0
WHILE $COUNT < 3
  STRINGLN Bonjour $USER (itération $COUNT)
  VAR $COUNT = $COUNT + 1
END_WHILE

IF $USER == "alice"
  STRINGLN correspondance
ELSE
  STRINGLN pas de correspondance
END_IF

Les expressions mathématiques dans VAR passent par un évaluateur sécurisé (ast walker) — pas de noms, pas d'appels, pas d'accès aux attributs, uniquement des littéraux numériques et + - * / // % **.

Maintenir des modificateurs

root@kitploit:~
HOLD SHIFT
STRINGLN cette ligne est en majuscules
RELEASE SHIFT

Envoyer des combinaisons de modificateurs arbitraires

root@kitploit:~
REM Maintenir Ctrl+Shift (0x01 + 0x02) et taper A
INJECT_MOD 0x03
STRING a
REM Relâcher tous les modificateurs
INJECT_MOD 0x00

Aléatoire

root@kitploit:~
RANDOM_LETTER 12      # 12 lettres aléatoires en minuscules/majuscules
RANDOM_NUMBER 6       # 6 chiffres aléatoires
RANDOM_SPECIAL 4      # 4 symboles ASCII aléatoires

Disposition du clavier

root@kitploit:~
LAYOUT UK             # passer aux mappings UK ISO pour les STRING/STRINGLN suivants
STRING @ " # ~ £ \ |  # tape correctement sur un hôte en disposition UK

Déposez un autre fichier dans keymaps/ (aux côtés de us.py et uk.py) et la directive LAYOUT <nom> le chargera via importlib.


Référence de configuration

Gadget de stockage de masse (haut de gadget_setup.sh)

Ces valeurs peuvent être remplacées par invocation en les définissant dans l'environnement lors de l'exécution manuelle de gadget_setup.sh, ou globalement via les directives Environment= de l'unité.

Paramètres réglables de l'écouteur (monitor_and_run.py)

Remplacez avec :

root@kitploit:~
sudo systemctl edit badusb
# Dans l'éditeur :
# [Service]
# Environment="BADUSB_REARM_COOLDOWN_S=8"
# Environment="BADUSB_MIN_INTER_FIRE_S=20"
sudo systemctl restart badusb

Notes d'architecture

Pourquoi l'écouteur utilise l'état state de l'UDC, pas /dev/hidg0

L'implémentation précédente testait l'existence + l'accessibilité en écriture de /dev/hidg0 comme signal "hôte attaché". Ce nœud de périphérique est créé dès que le gadget se lie à l'UDC au démarrage — bien avant qu'un hôte ne l'ait réellement énuméré. Ainsi, les charges utiles se déclenchaient immédiatement à la mise sous tension, indépendamment de l'endroit où le Pi était branché.

Le signal fiable est /sys/class/udc/<udc>/state, qui rapporte l'état du périphérique selon la spécification USB. Seul configured signifie que l'hôte a émis SetConfiguration(1) — le périphérique peut alors envoyer des rapports HID.

Pourquoi nous forçons le déliement après chaque charge utile

Détecter une déconnexion physique sur le Pi Zero 2 W est impossible par logiciel : la carte ne connecte pas VBUS sense au bloc OTG dwc2 du SoC. Après un débranchement physique :

  • /sys/class/udc/<udc>/state reste à configured.
  • current_speed reste à high-speed.
  • Le registre GOTGCTL de dwc2 reste à 0x000d0000 (bit BSesVld positionné).
  • Aucun événement udev n'est déclenché.

Donc au lieu d'attendre un signal qui ne viendra jamais, l'écouteur provoque activement la déconnexion : après chaque charge utile, il écrit "" dans le fichier UDC de configfs du gadget (que le noyau interprète comme un déliement), attend BADUSB_REARM_COOLDOWN_S, puis réécrit le nom de l'UDC pour relier. Le prochain branchement hôte produit une transition propre vers configured que l'écouteur peut détecter.

Si l'opérateur laisse le Pi branché après une charge utile, le reliement force l'hôte à réénumérer le gadget. Pour éviter une boucle de tir incontrôlée, deux protections s'appliquent :

  1. BADUSB_MIN_INTER_FIRE_S — si une transition configured se produit dans cette fenêtre après le tir précédent, elle est supprimée et le gadget est délié à nouveau. Le gadget effectue des cycles silencieux en arrière-plan.
  2. BADUSB_MAX_FIRES_PER_MINUTE — limite stricte à fenêtre glissante. Au-dessus du seuil, l'écouteur fait une pause de BADUSB_RATELIMIT_PAUSE_S et enregistre un avertissement.

Pourquoi nous n'utilisons jamais rm -rf sur configfs

Les fichiers d'attributs gérés par le noyau de configfs (bcdUSB, idVendor, webusb/*, os_desc/*, …) ne peuvent pas être supprimés par rm(2) — le noyau renvoie EPERM. Ils sont libérés uniquement lorsque leur répertoire parent est supprimé par rmdir. gadget_setup.sh et teardown_gadget.sh parcourent tous deux l'arbre configfs dans l'ordre canonique de libcomposite — uniquement des rmdir, jamais de rm sur des fichiers d'attributs — et le noyau nettoie le reste automatiquement.

Pourquoi les aides Python utilisent os.write et non file.write

Écrire une chaîne vide via open(path, "w").write("") n'invoque pas write(2) avec zéro octet — le TextIOWrapper de CPython l'élude. Pour le déliement de configfs (que le noyau interprète à partir d'une écriture de longueur nulle après suppression du saut de ligne), nous utilisons directement os.write(fd, b"\n") afin que l'appel système soit toujours émis avec au moins un octet.


Tests

L'analyseur Ducky dispose d'une suite pytest de 34 tests qui s'exécute contre un MockHIDEngine (un substitut en mémoire du véritable rédacteur HID), donc elle ne nécessite ni Pi ni matériel USB.

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

La couverture inclut :

  • safe_eval_math acceptant l'arithmétique, rejetant les noms / appels / accès aux attributs / constantes de chaînes.
  • evaluate_condition pour les comparaisons numériques et de chaînes sensibles à la casse.
  • VAR avec =, +=, -=, *=, /=.
  • IF / ELSE / END_IF prenant la bonne branche.
  • WHILE / END_WHILE comptage d'itérations pour < et <=.

Dépannage

"La charge utile ne se déclenche jamais lorsqu'on branche"

  1. cat /sys/class/udc/*/state — doit atteindre configured lorsque l'hôte énumère. S'il reste à not attached, l'hôte ne communique pas : essayez un autre câble (certains sont charge uniquement) ou un autre port hôte.
  2. lsmod | grep dwc2 — doit être chargé. Si seul dwc_otg est présent, dtoverlay=dwc2,dr_mode=otg ne s'applique pas ; réexécutez install.sh et redémarrez.
  3. journalctl -u badusb -f pendant le branchement — devrait montrer Host attached. Running payload. dans les ~2s suivant l'énumération de l'hôte.

"La charge utile se déclenche en boucle avec la LED qui clignote, même débranché"

C'était un vrai bug maintenant corrigé. Si cela se produit, vous êtes revenu à une version antérieure à os.write. Assurez-vous que monitor_and_run.py correspond à la branche main actuelle (cherchez os.write(fd, payload)).

"Le service ne redémarre pas — Operation not permitted"

Avant le correctif, gadget_setup.sh utilisait rm -rf sur configfs. La version actuelle utilise teardown_gadget() — si vous voyez ces erreurs, vous avez une vieille copie. Redéployez depuis main.

"Permission refusée sur /dev/hidg0"

La règle udev nécessite un hotplug pour s'appliquer, ou sudo udevadm trigger et une reconnexion pour que l'utilisateur pi récupère le groupe plugdev.

"Avertissement g_ether pendant l'installation"

Supprimez g_ether de cmdline.txt ; il réclame l'UDC avant que libcomposite ne puisse se lier.

"L'hôte montre un lecteur USB mais ce n'est pas la taille attendue"

La taille du stockage de masse est définie par BACKING_SIZE_MB et n'est effective que lors de la première exécution lorsque l'image est créée. Pour redimensionner :

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

"Je veux laisser le Pi branché sans qu'il spamme l'hôte"

C'est à cela que servent BADUSB_MIN_INTER_FIRE_S et BADUSB_MAX_FIRES_PER_MINUTE. Augmentez-les via systemctl edit badusb. Avec les valeurs par défaut, un Pi laissé branché retirera toutes les ~15s la première minute, puis fera une pause de 60s, puis reprendra.


Structure du dépôt

root@kitploit:~
.
├── README.md                   Ce fichier
├── LICENSE                     MIT
├── install.sh                  Installateur idempotent (config firmware, systemd, udev, plugdev)
├── gadget_setup.sh             Compose le gadget USB via configfs/libcomposite
├── teardown_gadget.sh          Démontage canonique de configfs (utilisé comme ExecStop)
├── reload_gadget.sh            Aide manuel pour délier/relier l'UDC
├── autorun.sh                  Ancien wrapper de lancement manuel (systemd est préféré)
├── monitor_and_run.py          Écouteur : attend l'attachement hôte, exécute la charge utile, force le réamorçage
├── run_payload.py              Interpréteur de style Ducky-Script
├── payload.txt                 Votre charge utile — modifiez librement ; relue à chaque branchement
├── payload_commands.md         Référence complète des commandes
├── etc/
│   ├── badusb.service          Unité systemd
│   └── 99-badusb-hidg.rules    Règle udev pour les droits sur /dev/hidg0
├── keymaps/
│   ├── __init__.py             Chargeur de dispositions dynamique
│   ├── us.py                   ANSI US (par défaut)
│   └── uk.py                   ISO UK
└── tests/
    ├── __init__.py
    ├── conftest.py             Configuration des chemins pytest
    └── test_parser.py          34 tests de l'analyseur contre un MockHIDEngine

Crédits

  • Scripts du projet original et inspiration : Psycostea.
  • Recherche sur les gadgets USB : USB Rubber Ducky, Hak5, documentation libcomposite, le pilote noyau dwc2.
  • 2026-05 correction de justesse : réécriture de la détection d'attachement hôte, sécurisation du stockage de masse, correction de plusieurs bugs de l'analyseur, ajout d'une abstraction de disposition de clavier, migration du démarrage vers systemd, ajout du cadre de tests unitaires, et contournement de l'incapacité matérielle du Pi Zero 2 W à détecter une déconnexion physique.

Licence

MIT — voir LICENSE.

Télécharger l’outil
Notes d'architecture
configured
PrérequisPourquoi
Raspberry Pi OS (Debian Bookworm ou Trixie, 64-bit Lite recommandé)Le script d'installation écrit dans /boot/firmware/... sur Bookworm+ et utilise /boot/... sur les images plus anciennes.
Python 3Fourni avec Pi OS.
mkfs.vfatPour formater l'image de stockage de masse lors de la première exécution. Désactivez si vous désactivez le stockage de masse.
Accès root pour l'installationTouche systemd, udev et /boot/firmware/config.txt.
/dev/hidg0
plugdev
  • Ajoute l'utilisateur pi au groupe plugdev.
  • Crée /var/badusb/ pour l'image de stockage de masse.
  • VariableDéfautSignification
    ENABLE_MASS_STORAGE10 pour un gadget HID uniquement.
    BACKING_FILE/var/badusb/storage.imgImage plate exposée à l'hôte.
    BACKING_SIZE_MB64Créée lors de la première exécution si manquante.
    BACKING_LABELBADUSBNom du volume FAT.
    MASS_STORAGE_RO1Lecture seule par défaut.
    Variable d'envDéfautSignification
    BADUSB_POST_PAYLOAD_FLUSH_S0.5Pause après la charge utile avant de délier pour permettre l'écoulement des écritures HID.
    BADUSB_REARM_COOLDOWN_S5Durée pendant laquelle le gadget reste invisible pour l'hôte entre le déliement et le reliement.
    BADUSB_MIN_INTER_FIRE_S10Secondes minimales entre deux tirs de charge utile ; en dessous, le tir est supprimé et le gadget est délié à nouveau.
    BADUSB_MAX_FIRES_PER_MINUTE6Limite stricte ; au-delà, pause de BADUSB_RATELIMIT_PAUSE_S.
    BADUSB_RATELIMIT_PAUSE_S60Durée de la pause après déclenchement de la limitation de débit.
  • RANDOM_* exactitude de longueur ; RANDOM_<inconnu> inopérant + avertissement.
  • INJECT_MOD persistance de l'octet de modificateur à travers les frappes suivantes.
  • HOLD SHIFT mettant chaque caractère en majuscule dans STRINGLN abc.
  • LAYOUT US vs LAYOUT UK produisant des rapports différents pour @ et " ; disposition inconnue revenant à la précédente.
  • STRING_BLOCK joignant les lignes ; STRINGLN_BLOCK respectant l'indentation minimale.