Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

raspducky

Image Buildroot transformant un Raspberry Pi Zero W en outil d'injection HID type "USB Rubber Ducky" — utilisable avec ou sans HAT écran/joystick.

v1.1.18 — Release stable, validée device end-to-end. ~95 % de la spec DuckyScript 3.0 supportée. Voir docs/core/core-cheatsheet.md pour la couverture exhaustive.

  • Boot < 5 secondes entre alimentation et clavier USB énuméré
  • 🎯 DuckyScript 3.0 complet : STRING, IF, WHILE, VAR, FUNCTION, ATTACKMODE, etc.
  • ⌨️ 10 layouts clavier livrés (us, gb, fr, de, es, it, pt, br, jp, be) + override custom
  • 🪪 10 profils USB device émulables (Apple, IBM, Logitech, Dell, Microsoft, Cherry...)
  • 💾 Mode arming : joystick UP au boot → édit la SD comme clé USB FAT32 sans démontage
  • 🔒 Air-gapped total : zéro Wi-Fi, zéro SSH, zéro UART en runtime
  • 📦 Distribution .img.zst via GitHub releases (~24 MB compressé)

🛠️ Matériel

Strictement nécessaire :

Composant Modèle testé Notes
SBC Raspberry Pi Zero W Pi Zero (sans Wi-Fi) compatible. Pi Zero 2 W non testé. Le Pi 3/4/400 n'est pas supporté (USB OTG géré différemment).
Carte SD ≥ 256 MB, classe 10 L'image fait ~128 MB
Câble USB USB-A → micro-USB data Le port micro-USB du milieu (USB), pas celui d'alim (PWR)

Optionnel — pour le menu LCD interactif :

Composant Modèle Câblage
HAT écran/joystick Waveshare 1.3" LCD HAT (240×240, ST7789, joystick 5 positions + 3 boutons KEY1/2/3) Pose directe sur le GPIO 40-pin du Pi

Sans le HAT, le projet reste 100% utilisable : le mode arming (joystick UP au boot, ou simplement démonter la SD physiquement) permet d'éditer boot.conf côté PC. Les codes erreur sont signalés via la LED ACT verte (cf. section "Patterns LED" plus bas).


⚡ Quick start

1. Téléchargement et flash

Récupère la dernière raspducky-vX.Y.Z.img.zst depuis les releases.

Avec Raspberry Pi Imager 1.7+ (recommandé) :

  • "Use custom" → sélectionner le .img.zst directement (gère zstd nativement)
  • Choisir la SD cible → écrire

En CLI :

zstd -d raspducky-vX.Y.Z.img.zst    # → sdcard.img (~128 MB)
sudo dd if=sdcard.img of=/dev/sdX bs=4M status=progress conv=fsync
sync

2. Premier branchement

  1. Insère la SD dans le Raspberry Pi Zero W
  2. Connecte le Pi au PC via le port USB du milieu (data, pas le port d'alim seul)
  3. Attends ~5 secondes
  4. Le PC voit un nouveau clavier USB
  5. Le payload par défaut (demos/hello-notepad.ds3) ouvre Notepad et tape Hello, World! (layout FR par défaut)

🎮 Modifier ce que fait le Pi

Tout passe par un seul fichier sur la SD : /payloads/boot.conf

PAYLOAD=demos/hello-notepad.ds3
PROFILE=generic_keyboard
LAYOUT=fr
INTER_KEY=5
JITTER=0
OS=AUTO

Trois moyens équivalents de modifier ce fichier :

Méthode A — Mode arming (recommandé) ⭐

Plus besoin de démonter la SD :

  1. Maintiens le joystick UP (ou le bouton équivalent) sur le HAT
  2. Branche le Pi → la LED ACT clignote vite (signal "arming actif")
  3. Le PC voit une clé USB PAYLOADS (32 MB FAT32)
  4. Édite boot.conf (ou ajoute des .ds3, .kbd, .dev...) avec ton éditeur favori
  5. Éjecte proprement côté PC
  6. Débranche le Pi, rebranche sans toucher le joystick → mode HID normal avec tes modifs

Méthode B — Démontage SD

Sors la SD, mount sur ton PC (la partition PAYLOADS est en FAT32, lisible nativement Windows/macOS/Linux), édite, démonte, réinsère.

Méthode C — Menu LCD (si HAT fonctionnel)

Navigue dans le menu pour sélectionner script / profil → écrit boot.conf → propose reboot.


⌨️ Choisir un layout clavier

Selon le layout configuré sur ton PC cible :

LAYOUT=fr     # France (AZERTY)
LAYOUT=us     # États-Unis (QWERTY) — défaut
LAYOUT=de     # Allemagne (QWERTZ)
LAYOUT=es     # Espagne
LAYOUT=it     # Italie
LAYOUT=gb     # Royaume-Uni
LAYOUT=pt     # Portugal
LAYOUT=br     # Brésil
LAYOUT=jp     # Japon
LAYOUT=be     # Belgique

Pourquoi c'est important : le clavier USB envoie des keycodes physiques, pas des caractères. Si ton PC interprète A comme Q (cas FR vs US), le payload tapera n'importe quoi sans le bon LAYOUT.

Override par payload : un .ds3 peut commencer par LAYOUT us pour forcer un layout spécifique (utile si tu télécharges des scripts Hak5 conçus pour US sur un PC FR).


🪪 Émuler un clavier de marque

Permet de faire passer le Pi pour un clavier connu (cas d'usage : test compatibilité macOS, contournement de policies USB-whitelist, BIOS legacy, démo) :

PROFILE=apple_magic_keyboard         # → apparaît comme Apple Magic Keyboard
PROFILE=ibm_model_m                  # → IBM Enhanced Keyboard (Model M)
PROFILE=logitech_k120                # → Logitech K120 Standard
PROFILE=lenovo_thinkpad_compact      # → Lenovo ThinkPad Compact USB
PROFILE=dell_kb216                   # → Dell KB216 Wired
PROFILE=microsoft_sculpt             # → Microsoft Sculpt Comfort
PROFILE=cherry_g80_3000              # → Cherry G80-3000 Mechanical
PROFILE=generic_keyboard             # → "raspducky HID" (défaut anonyme)

Vérifier côté PC après reboot HID :

OS Commande
Linux/macOS lsusb → cherche VID:PID
Windows Win+X → Gestionnaire de périphériques → propriétés du clavier → onglet Détails → "ID matériels"
Tous (GUI) USBDeview (NirSoft, portable)

⚠️ Légal : usurper un VID/PID enregistré USB-IF viole leurs ToS — sans recours pratique pour usage personnel / pédagogique / pentest perso / test compatibilité (le scope de ce projet). Ne pas distribuer commercialement avec ces profils.


🦆 Écrire des payloads DuckyScript 3.0

Démos livrées

Deux scripts prêts à l'emploi dans br-external/board/raspducky/payloads/ — bons points de départ pour comprendre la syntaxe :

Script Effet Layout
demos/hello-notepad.ds3 Ouvre Notepad (Win+R) et tape Hello World FR
wifi/info-notepad.ds3 Dump des profils Wi-Fi Windows + clés en clair vers un fichier puis ouvre Notepad FR

Workflow

  1. Crée un fichier .ds3 dans /payloads/ (sur la SD côté arming, ou édit direct PC après démontage)
  2. Mets-le dans boot.conf : PAYLOAD=mon-script.ds3 (sous-dossiers OK : attaques/recon.ds3)
  3. Reboot le Pi → le script est exécuté

Exemple basique

REM_BLOCK
TITLE: Hello world
END_REM

LAYOUT fr
DELAY 1000
STRING bonjour le monde !
ENTER

Exemple avancé : recon Windows avec boucle

DELAY 1000
GUI r
DELAY 500
STRINGLN cmd
DELAY 500

VAR $i = 0
WHILE $i < 3
    IF $i == 0 THEN
        STRINGLN whoami
    END_IF
    IF $i == 1 THEN
        STRINGLN ipconfig
    END_IF
    IF $i == 2 THEN
        STRINGLN dir
    END_IF
    DELAY 300
    VAR $i = $i + 1
END_WHILE

Constructions supportées

Catégorie Exemples
Texte STRING bonjour, STRINGLN echo (avec $var interpolation)
Touches ENTER, TAB, F1-F12, ESC, BACKSPACE, DELETE, UP/DOWN/LEFT/RIGHT, HOME, END
Combos GUI r, CTRL c, CTRL-ALT t, ALT TAB, HOLD SHIFT / RELEASE
Délais DELAY 1000, DEFAULT_DELAY 50, JITTER 20
Variables VAR $count = 0, VAR $sum = $a + $b * 2
Conditions IF $x == 5 THEN ... ELSE ... END_IF
Boucles WHILE $i < 10 ... END_WHILE
Fonctions FUNCTION my_func ... END_FUNCTION puis my_func
Configuration LAYOUT fr, ATTACKMODE HID VID_05AC PID_024F, LED_ON
Commentaires REM ..., REM_BLOCK ... END_REM

Doc complète : docs/core/core-duckyscript.md


💡 Patterns LED ACT (sans LCD)

LED ACT Cadence Signification
mmc0 (irrégulier) activité SD Boot HID nominal
timer 150ms on/off (rapide régulier) 3 Hz Mode arming actif — clé USB exposée
timer 100ms on/off (très rapide) 5 Hz, agressif Erreur fataleboot.conf absent / corrompu / gadget HID KO
timer 300/700ms (asymétrique pulsé) lent Erreur soft — payload introuvable / parse error
timer 500ms on/off (régulier lent) 1 Hz Warning — fallback PROFILE automatique

L'utilisateur reconnaît visuellement le problème par la cadence sans LCD.


🛠️ Architecture

Couche Choix Pourquoi
OS de base Buildroot 2025.02.13 LTS (submodule) Boot < 5 s, pas de systemd, kernel custom
PID 1 raspducky-init en C statique (~570 KB stripped) Boot path ~600 ms, zéro dépendance shared
Runtime payload Python 3.10+ (ducky pipeline complet) Lexer/Parser/Analyzer/Runtime, ~190 tests pytest. CLI raspducky-play.
UI LCD Pillow + ST7789 SPI direct sur /dev/spidev0.0 7 écrans v1.1.0 : 5 config + 2 splash. Pas de driver kernel.
Inputs /dev/gpiochip0 ioctl direct (C init) + RPi.GPIO polling 50ms (UI Python) Zéro dep externe pour init, polling robuste pour UI
Build Buildroot + BR2_EXTERNAL (br-external/) Standard, reproductible
CI/CD Gitea Actions (3 workflows) tests / image / release

3 partitions sur la SD :

/dev/mmcblk0
├── p1  FAT32  32 MB    "boot"      bootloader Pi + kernel + DTB
├── p2  ext4   ~64 MB   (rootfs)    Buildroot + Python + libs (read-only)
└── p3  FAT32  32 MB    "PAYLOADS"  boot.conf, *.ds3, layouts/, devices/  (RW)

📁 Layout du repo

raspducky/
├── br-external/             # BR2_EXTERNAL : configs, packages, board files
│   ├── configs/raspducky_defconfig
│   ├── package/             # raspducky-init (C) + raspducky (Python)
│   └── board/raspducky/     # genimage.cfg, post-build.sh, payloads/, devices/, keyboard-layouts/
├── src/
│   ├── init/                # raspducky-init (C statique, PID 1)
│   └── raspducky/           # raspducky (Python applicatif)
│       ├── raspducky/
│       │   ├── ducky/       # Lexer/Parser/Analyzer/Runtime DuckyScript 3.0
│       │   ├── lcd/         # Driver ST7789 SPI direct
│       │   ├── ui/          # Renderer + 7 écrans (v1.1.0)
│       │   ├── app/         # State machine + boucle d'événements
│       │   ├── inputs/      # InputReader joystick + KEY1/2/3
│       │   ├── bootconf.py  # Parser/serializer boot.conf (atomique)
│       │   ├── loaders.py   # Énumération layouts/profiles/payloads
│       │   ├── boot_mode.py # Lecture /run/raspducky/boot_state
│       │   └── ...
│       └── tests/           # ~307 tests pytest
├── scripts/                 # gen-changelog, gen-manifest, gen-keyboard-layouts, ...
├── docs/                    # Documentation atomique (atomes)
│   ├── core/                # Logique métier (DuckyScript, arming flow, boot.conf)
│   ├── archi/               # Architecture (USB gadget, image build, layouts, ...)
│   └── management/          # workflow.md, retex.md, TODO.md
├── buildroot/               # Submodule Buildroot 2025.02.13
└── .gitea/workflows/        # CI/CD

🧪 Développement

Builder l'image localement

git clone --recurse-submodules https://github.com/NimpNaw/raspducky.git
cd raspducky/buildroot
make BR2_EXTERNAL=../br-external raspducky_defconfig
make -j$(nproc)
# → buildroot/output/images/sdcard.img (~128 MB)

Build complet : ~30-40 min première fois (toolchain + kernel + Python). Rebuild incrémental d'init C : ~5 s.

Lancer les tests

cd src/raspducky
python3 -m venv venv
source venv/bin/activate
pip install -e ".[test]"
pytest -v --cov=raspducky
# → ~307 tests, ~3s

Vérifier le fragment kernel

python3 scripts/check-kernel-config.py

Ajouter un layout clavier

# Télécharge depuis le repo Hak5 community + convertit en .kbd
python3 scripts/gen-keyboard-layouts.py --only ca-fr ch dk

📚 Documentation

Documentation atomique (un fichier par concept) dans docs/ :


⚠️ Sécurité et usage

Ce projet produit un outil d'injection HID. Usage personnel / pédagogique / pentest perso / test compatibilité uniquement. Voir LICENSE GPLv3 §7 (clause de non-garantie).

L'utilisateur final est seul responsable de l'usage qu'il fait de l'image.


📄 Licence

GPLv3.

About

Using a raspberry pi zero as a badusb compatible with ducky script 3.0

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages