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
gdbfuzz — Fuzzing des systèmes embarqués à l'aide de points d'arrêt matériels | Kitploit
Outils/GitHubGitHub/boschresearch/gdbfuzz
Sécurité des Systèmes EmbarquésAnalyse des VulnérabilitésDébogueursFuzzingSécurité MatérielleAnalyse de BinairesArticles et RechercheApprentissage et ÉducationAnalyse de MicrologicielArchived
GitHubboschresearch/gdbfuzz

gdbfuzz

19420il y a 2 ansVé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

Fuzzing des systèmes embarqués à l'aide de points d'arrêt matériels

Voir le dépôt

GDBFuzz : Fuzzing piloté par débogueur

Ceci est le code compagnon pour l'article : « Fuzzing Embedded Systems using Debugger Interfaces ». Une prépublication de l'article peut être trouvée ici https://publications.cispa.saarland/3950/. Le code permet aux utilisateurs de reproduire et d'étendre les résultats rapportés dans l'article. Veuillez citer l'article ci-dessus lorsque vous rapporterez, reproduirez ou étendrez les résultats.

Structure du dossier

root@kitploit:~
.
    ├── benchmark               # Scripts pour construire la suite de tests de fuzzer de Google et exécuter les expériences
    ├── dependencies            # Contient un Makefile pour installer les dépendances de GDBFuzz
    ├── evaluation              # Données brutes d'expérience, présentées dans l'article
    ├── example_firmware        # Exemples d'applications embarquées, utilisées pour l'évaluation
    ├── example_programs        # Contient un exemple de programme compilé et des configurations pour tester GDBFuzz
    ├── src                     # Contient l'implémentation de GDBFuzz
    ├── Dockerfile              # Pour créer une image Docker avec toutes les dépendances GDBFuzz installées
    ├── LICENSE                 # Licence
    ├── Makefile                # Makefile pour créer l'image docker ou installer GDBFuzz localement
    └── README.md               # Ce fichier README

Objectif du projet

L'idée de GDBFuzz est d'exploiter les points d'arrêt matériels des microcontrôleurs comme retour pour le fuzzing guidé par couverture. Ainsi, GDB est utilisé comme interface générique pour permettre une large applicabilité. Pour l'analyse binaire du firmware, Ghidra est utilisé. Le code contient une configuration de benchmark pour évaluer la méthode. De plus, des fichiers de firmware d'exemple sont inclus.

Pour Commencer

GDBFuzz permet le fuzzing guidé par couverture pour les systèmes embarqués, mais - à des fins d'évaluation - peut aussi fuzzer des applications utilisateur arbitraires. Pour le fuzzing sur microcontrôleurs, nous recommandons une installation locale de GDBFuzz afin de pouvoir envoyer les données de fuzz au dispositif testé sans problème.

Installation locale

GDBFuzz a été testé sur Ubuntu 20.04 LTS et Raspberry Pi OS 32 bits. Les prérequis sont Java et Python 3. Tout d'abord, créez un nouvel environnement virtuel et installez toutes les dépendances.

root@kitploit:~
virtualenv .venv
source .venv/bin/activate
make
chmod a+x ./src/GDBFuzz/main.py

Exécution locale sur un exemple de programme

GDBFuzz lit les paramètres à partir d'un fichier de configuration avec les clés suivantes.

root@kitploit:~
[SUT]
# Chemin vers le fichier binaire du SUT.
# Cela peut être, par exemple, un fichier .elf ou .bin.
binary_file_path = <chemin>

# Adresse du nœud racine du CFG.
# Les points d'arrêt sont placés aux nœuds de ce CFG.
# ex. 'LLVMFuzzerTestOneInput' ou 'main'
entrypoint = <point d'entrée>

# Nombre d'entrées qui doivent être exécutées sans qu'un point d'arrêt ne soit déclenché avant
# que les points d'arrêt soient tournés.
until_rotate_breakpoints = <nombre>


# Nombre maximum de points d'arrêt pouvant être placés à tout moment.
max_breakpoints = <nombre>

# Liste noire des fonctions à ignorer.
# ignore_functions est une liste de noms de fonctions séparés par des espaces, ex. 'malloc free'.
ignore_functions = <liste séparée par des espaces>

# Un de {Hardware, QEMU, SUTRunsOnHost}
# Hardware : Un composant externe démarre un serveur gdb et GDBFuzz peut s'y connecter.
# QEMU : GDBFuzz démarre QEMU. QEMU émule binary_file_path et démarre gdbserver.
# SUTRunsOnHost : GDBFuzz démarre le programme cible dans GDB.
target_mode = <mode>

# Mettez ceci à False si vous voulez démarrer ghidra, analyser le SUT,
# et démarrer le pont ghidra bridge manuellement.
start_ghidra = True


# Liste séparée par des espaces des adresses où les points d'arrêt logiciels (pour le code de
# gestion des erreurs) sont placés. L'exécution de ceux-ci est considérée comme un crash.
# Exemple : software_breakpoint_addresses = 0x123 0x432
software_breakpoint_addresses = 


# Indique si tous les points d'arrêt logiciels déclenchés sont considérés comme des crashs
consider_sw_breakpoint_as_error = False

[SUTConnection]
# La classe 'SUT_connection_class' dans le fichier 'SUT_connection_path' implémente
# comment les entrées sont envoyées au SUT.
# Les entrées peuvent, par exemple, être envoyées via Wi-Fi, Série, Bluetooth, ...
# Cette classe doit hériter de ./connections/SUTConnection.py.
# Voir ./connections/SUTConnection.py pour plus d'informations.
SUT_connection_file = FIFOConnection.py

[GDB]
path_to_gdb = gdb-multiarch
# Écrit sous forme adresse:port
gdb_server_address = localhost:4242

[Fuzzer]
# En octets
maximum_input_length = 100000
# En secondes
single_run_timeout = 20
# En secondes
total_runtime = 3600

# Optionnel
# Chemin vers un répertoire où chaque fichier contient une seed. Si vous ne souhaitez pas
# utiliser de seeds, laissez la valeur vide.
seeds_directory = 

[BreakpointStrategy]
# Les stratégies pour choisir les blocs de base se trouvent dans
# 'src/GDBFuzz/breakpoint_strategies/'
# Pour l'article, nous utilisons les stratégies suivantes
# 'RandomBasicBlockStrategy.py' - Choisir aléatoirement des blocs de base non atteints
# 'RandomBasicBlockNoDomStrategy.py' - Comme la précédente, mais n'utilise pas les relations de dominance pour déduire les nœuds transitivement atteints.
# 'RandomBasicBlockNoCorpusStrategy.py' - Comme la première, mais empêche la croissance du corpus d'entrées et se comporte donc comme du fuzzing boîte noire avec mesure de couverture.
# 'BlackboxStrategy.py', - Ne place aucun point d'arrêt
breakpoint_strategy_file = RandomBasicBlockStrategy.py

[Dependencies]
path_to_qemu = dependencies/qemu/build/x86_64-linux-user/qemu-x86_64
path_to_ghidra = dependencies/ghidra


[LogsAndVisualizations]
# Un de {DEBUG, INFO, WARNING, ERROR, CRITICAL}
loglevel = INFO

# Chemin vers un répertoire où les fichiers de sortie (ex. graphiques, fichiers journaux) sont stockés.
output_directory = ./output

# Si mis à True, un client MQTT envoie des éléments d'interface utilisateur (ex. graphiques)
enable_UI = False

Un exemple de fichier de configuration se trouve dans ./example_programs/ accompagné d'un exemple de programme compilé à l'aide de notre harnais de fuzzing dans benchmark/benchSUTs/GDBFuzz_wrapper/common/. Lancez le fuzzing pendant une heure avec la commande suivante.

root@kitploit:~
chmod a+x ./example_programs/json-2017-02-12
./src/GDBFuzz/main.py --config ./example_programs/fuzz_json.cfg

Nous voyons d'abord la sortie de Ghidra analysant l'exécutable binaire, puis des messages lorsque les points d'arrêt sont relocalisés ou déclenchés.

Sortie du Fuzzing

Selon le output_directory spécifié dans le fichier de configuration, il devrait maintenant y avoir un dossier trial-0 avec la structure suivante

root@kitploit:~
.
    ├── corpus            # Un dossier qui contient le corpus d'entrées.
    ├── crashes           # Un dossier qui contient les entrées ayant causé un crash - le cas échéant.
    ├── cfg               # Le graphe de flot de contrôle sous forme de liste d'adjacence.
    ├── fuzzer_stats      # Statistiques de la campagne de fuzzing.
    ├── plot_data         # Tableau montrant à quel moment relatif dans la campagne de fuzzing quel bloc de base a été atteint.
    ├── reverse_cfg       # Le graphe de flot de contrôle inversé.

Utilisation de Ghidra en mode GUI

En définissant start_ghidra = False dans le fichier de configuration, GDBFuzz se connecte à une instance Ghidra fonctionnant en mode GUI. Pour cela, le plugin ghidra_bridge doit être démarré manuellement depuis le gestionnaire de scripts. Pendant le fuzzing, les blocs de programme atteints sont surlignés en vert.

GDBFuzz sur les programmes utilisateur Linux

Pour le fuzzing sur des applications utilisateur Linux, GDBFuzz utilise le point d'entrée standard LLVMFuzzOneInput utilisé par presque tous les fuzzers comme AFL, AFL++, libFuzzer,... Dans benchmark/benchSUTs/GDBFuzz_wrapper/common, il y a un wrapper qui peut être utilisé pour compiler tout harnais de fuzzing conforme en un programme autonome qui récupère l'entrée via un tube nommé à /tmp/fromGDBFuzz. Cela permet de simuler un dispositif embarqué qui consomme des données via une interface d'entrée bien définie et donc d'exécuter GDBFuzz sur n'importe quelle application. Pour plus de commodité, nous avons créé un script dans benchmark/benchSUTs qui compile tous les programmes de notre évaluation avec notre wrapper, comme expliqué plus tard.

REMARQUE : GDBFuzz n'est pas destiné à fuzzer des applications utilisateur Linux. Utilisez plutôt AFL++ ou d'autres fuzzers. Le wrapper existe uniquement à des fins d'évaluation pour permettre l'exécution de benchmarks et de comparaisons à grande échelle !

Installation et exécution dans un conteneur Docker

L'efficacité générale de notre approche est démontrée dans un benchmark à grande échelle déployé sous forme de conteneurs Docker.

root@kitploit:~
make dockerimage

Pour exécuter l'expérience ci-dessus dans le conteneur Docker (pendant une heure comme spécifié dans le fichier de configuration), mappez les dossiers example_programs et output comme volumes et démarrez GDBFuzz comme suit.

root@kitploit:~
chmod a+x ./example_programs/json-2017-02-12
docker run -it --env CONFIG_FILE=/example_programs/fuzz_json_docker_qemu.cfg -v $(pwd)/example_programs:/example_programs -v $(pwd)/output:/output gdbfuzz:1.0

Un dossier de sortie devrait apparaître dans le répertoire de travail actuel avec la structure expliquée ci-dessus.

Instructions Détaillées

Notre évaluation est divisée en deux parties.

  1. GDBFuzz sur sa configuration prévue, directement sur le matériel.
  2. GDBFuzz dans un environnement émulé pour permettre une analyse indépendante et des comparaisons des résultats.

GDBFuzz peut fonctionner avec n'importe quel serveur GDB et donc avec la plupart des sondes de débogage pour microcontrôleurs.

GDBFuzz vs. Blackbox (RQ1)

Concernant RQ1 de l'article, nous exécutons GDBFuzz sur différents microcontrôleurs avec différents firmwares situés dans example_firmware. Pour chaque expérience, nous exécutons GDBFuzz avec la stratégie RandomBasicBlock et avec la stratégie RandomBasicBlockNoCorpus. Cette dernière se comporte comme du fuzzing sans retour, mais nous pouvons toujours mesurer la couverture atteinte. Pour répondre à RQ1, nous comparons la couverture atteinte des stratégies RandomBasicBlock et RandomBasicBlockNoCorpus. Les fichiers de configuration respectifs se trouvent dans les sous-dossiers correspondants et nous expliquons maintenant comment configurer le fuzzing sur les quatre cartes de développement.

GDBFuzz sur la carte STM32 B-L4S5I-IOT01A

GDBFuzz nécessite l'accès à un serveur GDB. Dans ce cas, la carte B-L4S5I-IOT01A et son débogueur intégré sont utilisés. Ce débogueur intégré configure un serveur GDB via le programme 'st-util' et permet l'accès à ce serveur GDB via localhost:4242.

  • Installez le pilote STLINK lien
  • Connectez la carte MCU et le PC via USB (sur la carte MCU, connectez-vous au connecteur USB étiqueté 'USB STLINK')
root@kitploit:~
sudo apt-get install stlink-tools gdb-multiarch

Compilez et flashez un firmware pour la STM32 B-L4S5I-IOT01A, par exemple le projet arduinojson.

Prérequis : Installer platformio (pio)

root@kitploit:~
cd ./example_firmware/stm32_disco_arduinojson/
pio run --target upload

Pour info : platformio stocke un fichier .elf du SUT ici : ./example_firmware/stm32_disco_arduinojson/.pio/build/disco_l4s5i_iot01a/firmware.elf Ce fichier .elf est également utilisé ultérieurement dans la configuration utilisateur pour Ghidra.

Ouvrez un nouveau terminal et exécutez ce qui suit pour démarrer le serveur GDB :

root@kitploit:~
st-util

Exécutez GDBFuzz avec une configuration utilisateur pour arduinojson. Nous pouvons envoyer des données via le port USB au microcontrôleur. Le microcontrôleur transmet ces données via série au SUT. Dans notre cas, /dev/ttyACM0 est le périphérique USB de la carte microcontrôleur. Si votre système a attribué un autre périphérique à la carte microcontrôleur, changez /dev/ttyACM0 dans le fichier de configuration pour votre périphérique.

root@kitploit:~
./src/GDBFuzz/main.py --config ./example_firmware/stm32_disco_arduinojson/fuzz_serial_json.cfg

Les statistiques et journaux du fuzzer se trouvent dans le répertoire ./output/...

GDBFuzz sur la carte CY8CKIT-062-WiFi-BT

Installez pyocd :

root@kitploit:~
pip install --upgrade pip 'mbed-ls>=1.7.1' 'pyocd>=0.16'

Assurez-vous que 'KitProg v3' est sur le dispositif et mettez la carte en mode 'Arm DAPLink' en appuyant sur le bouton approprié. Démarrez le serveur GDB :

root@kitploit:~
pyocd gdbserver --persist

Flashez un firmware et lancez le fuzzing, par exemple avec

root@kitploit:~
gdb-multiarch
    target remote :3333
    load ./example_firmware/CY8CKIT_json/mtb-example-psoc6-uart-transmit-receive.elf
    monitor reset
./src/GDBFuzz/main.py --config ./example_firmware/CY8CKIT_json/fuzz_serial_json.cfg

GDBFuzz sur ESP32 et Segger J-Link

  • Installez le SDK ESP32

Compilez et flashez un firmware pour l'ESP32, par exemple l'exemple arduinojson avec platformio.

root@kitploit:~
cd ./example_firmware/esp32_arduinojson/
pio run --target upload

Ajoutez la ligne suivante au fichier de configuration d'openocd pour le débogueur J-Link : jlink.cfg

root@kitploit:~
adapter speed 10000

Ouvrez un nouveau terminal et exécutez ce qui suit pour démarrer le serveur GDB :

root@kitploit:~
get_idf
openocd -f interface/jlink.cfg -f target/esp32.cfg -c "telnet_port 7777" -c "gdb_port 8888"

Exécutez GDBFuzz avec une configuration utilisateur pour arduinojson. Nous pouvons envoyer des données via le port USB au microcontrôleur. Le microcontrôleur transmet ces données via série au SUT. Dans notre cas, /dev/ttyUSB0 est le périphérique USB de la carte microcontrôleur. Si votre système a attribué un autre périphérique à la carte microcontrôleur, changez /dev/ttyUSB0 dans le fichier de configuration pour votre périphérique.

root@kitploit:~
./src/GDBFuzz/main.py --config ./example_firmware/esp32_arduinojson/fuzz_serial.cfg

Les statistiques et journaux du fuzzer se trouvent dans le répertoire ./output/...

GDBFuzz sur MSP430F5529LP

Installez TI MSP430 GCC depuis https://www.ti.com/tool/MSP430-GCC-OPENSOURCE

Démarrez le serveur GDB

root@kitploit:~
./gdb_agent_console libmsp430.so

ou (plus stable). Compilez mspdebug depuis https://github.com/dlbeer/mspdebug/ et utilisez :

root@kitploit:~
until mspdebug --fet-skip-close --force-reset tilib "opt gdb_loop True" gdb ; do sleep 1 ; done

Ghidra ne parvient pas à analyser les binaires pour le contrôleur TI MSP430 par défaut. Pour y remédier, importez le fichier dans l'interface graphique Ghidra, choisissez MSP430X comme architecture et ignorez l'analyse automatique. Ensuite, ouvrez la 'Table des symboles', triez-les par nom et supprimez tous les symboles avec des noms comme $C$L*. Maintenant, l'analyse automatique peut être exécutée. Après analyse, démarrez le pont ghidra depuis l'interface graphique Ghidra manuellement, puis lancez GDBFuzz.

root@kitploit:~
./src/GDBFuzz/main.py --config ./example_firmware/msp430_arduinojson/fuzz_serial.cfg

Fuzzing USB

Pour accéder aux périphériques USB en tant qu'utilisateur non root avec pyusb, nous ajoutons des règles appropriées à udev. Collez les lignes suivantes dans /etc/udev/rules.d/50-myusb.rules :

root@kitploit:~
SUBSYSTEM=="usb", ATTRS{idVendor}=="1234", ATTRS{idProduct}=="5678" GROUP="usbusers", MODE="666"

Rechargez udev :

root@kitploit:~
sudo udevadm control --reload
sudo udevadm trigger

Comparaison avec Fuzzware (RQ2)

Dans RQ2 de l'article, nous comparons GDBFuzz avec l'approche basée sur l'émulation Fuzzware. D'abord, nous exécutons GDBFuzz et Fuzzware comme décrit précédemment sur les fichiers firmware fournis. Pour chaque expérience GDBFuzz, nous créons un fichier avec des blocs de base valides à partir des fichiers de graphe de flot de contrôle comme suit :

root@kitploit:~
cut -d " " -f1 ./cfg > valid_bbs.txt

Maintenant, nous pouvons rejouer la couverture par rapport au résultat fuzzware : fuzzware genstats --valid-bb-file valid_bbs.txt

Découverte de Bogues (RQ3)

Lorsque des entrées provoquant des crashs ou des blocages sont trouvées, elles sont stockées dans le dossier crashes. Lors de l'évaluation, nous avons trouvé les trois bogues suivants :

  1. Une boucle infinie dans la pile de périphériques USB STM32, causée par le comptage d'une variable d'index uint8_t à une variable uint32_t contrôlable par l'attaquant dans une boucle for.
  2. Un dépassement de tampon dans l'analyseur JSON Cypress, causé par l'absence de vérifications de longueur sur un tampon interne de taille fixe.
  3. Une déréférencement de pointeur nul dans l'analyseur JSON Cypress, causé par l'absence de contrôles de validation.

GDBFuzz sur un Raspberry Pi 4a (8 Go)

GDBFuzz peut également fonctionner sur un hôte Raspberry Pi avec des modifications mineures :

  1. Ghidra doit être modifié pour fonctionner sur un système d'exploitation 32 bits

Dans le fichier ./dependencies/ghidra/support/launch.sh:125, la variable JAVA_HOME doit être codée en dur, par exemple en JAVA_HOME="/usr/lib/jvm/default-java"

  1. STLink doit être en version >= 1.7 pour fonctionner correctement -> Compilation à partir des sources

GDBFuzz sur d'autres cartes

Pour fuzzer des logiciels sur d'autres cartes, GDBFuzz nécessite

  1. Un microcontrôleur avec des points d'arrêt matériels et une sonde de débogage compatible GDB.
  2. Le fichier firmware.
  3. Un serveur GDBServer en cours d'exécution et une application GDB adaptée.
  4. Un point d'entrée où le fuzzing doit commencer, par exemple une fonction d'analyse ou une adresse.
  5. Une interface d'entrée (voir src/GDBFuzz/connections) qui déclenche l'exécution du code au point d'entrée, par exemple une connexion série.

Toutes ces propriétés doivent être spécifiées dans le fichier de configuration.

Exécution du Benchmark Complet (RQ4 - 8)

Pour les RQ 4 à 8, nous exécutons un benchmark à grande échelle. D'abord, construisez l'image Docker comme décrit précédemment et compilez les applications de la Suite de tests de Fuzzer de Google avec notre harnais de fuzzing dans benchmark/benchSUTs/GDBFuzz_wrapper/common.

root@kitploit:~
cd ./benchmark/benchSUTs
chmod a+x setup_benchmark_SUTs.py
make dockerbenchmarkimage

Adaptez ensuite les paramètres du benchmark dans benchmark/scripts/benchmark.py et benchmark/scripts/benchmark_aflpp.py à vos besoins (en particulier number_of_cores, trials, et seconds_per_trial) et lancez le benchmark avec :

root@kitploit:~
cd ./benchmark/scripts
./benchmark.py $(pwd)/../benchSUTs/SUTs/ SUTs.json
./benchmark_aflpp.py $(pwd)/../benchSUTs/SUTs/ SUTs.json

Un dossier apparaît dans ./benchmark/scripts qui contient des fichiers de tracé (couverture en fonction du temps), des fichiers de statistiques du fuzzer et des fichiers de graphe de flot de contrôle pour chaque expérience, comme dans evaluation/fuzzer_test_suite_qemu_runs.

[Optionnel] Installation de la Visualisation et Exemple de Visualisation

GDBFuzz dispose d'une fonctionnalité optionnelle où il trace le graphe de flot de contrôle des nœuds couverts. Ceci est désactivé par défaut. Vous pouvez l'activer en suivant les instructions de cette section et en définissant 'enable_UI' à 'True' dans la configuration utilisateur.

Sur l'hôte :

Installez

root@kitploit:~
sudo apt-get install graphviz

Installez une version récente de node, par exemple Option 2 de ici. Utilisez l'Option 2 et pas l'option 1. Cela devrait installer à la fois node et npm. Pour référence, nos numéros de version sont (mais des versions plus récentes devraient aussi fonctionner) :

root@kitploit:~
➜ node --version
v16.9.1
➜ npm --version
7.21.1

Installez les dépendances de l'interface web :

root@kitploit:~
cd ./src/webui
npm install

Installez le courtier MQTT mosquitto, par exemple voir ici

Mettez à jour la configuration du courtier mosquitto : Remplacez le fichier /etc/mosquitto/conf.d/mosquitto.conf par le contenu suivant :

root@kitploit:~
listener 1883
allow_anonymous true

listener 9001
protocol websockets

Redémarrez le courtier mosquitto :

root@kitploit:~
sudo service mosquitto restart

Vérifiez que le courtier mosquitto est en cours d'exécution :

root@kitploit:~
sudo service mosquitto status

La sortie devrait inclure le texte 'Active: active (running)'

Démarrez l'interface web :

root@kitploit:~
cd ./src/webui
npm start

Votre navigateur web devrait s'ouvrir automatiquement sur 'http://localhost:3000/'.

Démarrez GDBFuzz et utilisez un fichier de configuration utilisateur où enable_UI est défini à True. Vous pouvez utiliser le conteneur Docker et le SUT arduinojson ci-dessus. Mais assurez-vous de définir 'enable_UI' à 'True'.

Les nœuds couverts en 'bleu' sont couverts. Les nœuds blancs ne sont pas couverts. Nous ne montrons que les nœuds non couverts si leur parent est couvert (dessiner le graphe de flot de contrôle complet prend trop de temps si le graphe est grand).

Licence

GDBFuzz est open source sous licence AGPL-3.0. Voir le fichier LICENSE pour plus de détails.

Pour une liste des autres composants open source inclus dans GDBFuzz, voir le fichier 3rd-party-licenses.txt.

Télécharger l’outil