Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
gdbfuzz — Fuzzing di sistemi embedded utilizzando breakpoint hardware | Kitploit
Strumenti/GitHubGitHub/boschresearch/gdbfuzz
Sicurezza Sistemi EmbeddedAnalisi delle VulnerabilitàDebuggerFuzzingSicurezza HardwareAnalisi di BinariPaper e RicercaApprendimento e FormazioneAnalisi del FirmwareArchived
GitHubboschresearch/gdbfuzz

gdbfuzz

Fuzzing di sistemi embedded utilizzando breakpoint hardware

194202 anni faRevisionato da Kitploit

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi
Vedi Repository

GDBFuzz: Fuzzing basato su Debugger

Questo è il codice di supporto per l'articolo: 'Fuzzing di Sistemi Embedded tramite Interfacce di Debugger'. Una prestampa dell'articolo è disponibile qui https://publications.cispa.saarland/3950/. Il codice consente agli utenti di riprodurre ed estendere i risultati riportati nell'articolo. Si prega di citare il suddetto articolo quando si riportano, riproducono o estendono i risultati.

Struttura delle cartelle

root@kitploit:~
.
    ├── benchmark               # Script per compilare la suite di test di Google e per eseguire gli esperimenti
    ├── dependencies            # Contiene un Makefile per installare le dipendenze di GDBFuzz
    ├── evaluation              # Dati grezzi degli esperimenti, presentati nell'articolo
    ├── example_firmware        # Applicazioni embedded di esempio, utilizzate per la valutazione
    ├── example_programs        # Contiene un programma di esempio compilato e le configurazioni per testare GDBFuzz
    ├── src                     # Contiene l'implementazione di GDBFuzz
    ├── Dockerfile              # Per creare un'immagine Docker con tutte le dipendenze di GDBFuzz installate
    ├── LICENSE                 # Licenza
    ├── Makefile                # Makefile per creare l'immagine docker o installare GDBFuzz localmente
    └── README.md               # Questo file README

Scopo del progetto

L'idea di GDBFuzz è sfruttare i breakpoint hardware dei microcontrollori come feedback per il fuzzing guidato dalla copertura del codice. A tale scopo, GDB viene utilizzato come interfaccia generica per garantire un'ampia applicabilità. Per l'analisi binaria del firmware viene utilizzato Ghidra. Il codice contiene un setup di benchmark per valutare il metodo. Inoltre, sono inclusi file firmware di esempio.

Per Iniziare

GDBFuzz consente il fuzzing guidato dalla copertura per sistemi embedded, ma - a fini di valutazione - può anche eseguire fuzzing su applicazioni utente arbitrarie. Per il fuzzing su microcontrollori, consigliamo un'installazione locale di GDBFuzz per poter inviare dati di input al dispositivo in test senza problemi.

Installazione locale

GDBFuzz è stato testato su Ubuntu 20.04 LTS e Raspberry Pi OS a 32 bit. I prerequisiti sono java e python3. Per prima cosa, creare un nuovo ambiente virtuale e installare tutte le dipendenze.

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

Esecuzione locale su un programma di esempio

GDBFuzz legge le impostazioni da un file di configurazione con le seguenti chiavi.

root@kitploit:~
[SUT]
# Percorso del file binario del SUT.
# Può essere, ad esempio, un file .elf o .bin.
binary_file_path = <percorso>

# Indirizzo del nodo radice del CFG.
# I breakpoint vengono posizionati sui nodi di questo CFG.
# es. 'LLVMFuzzerTestOneInput' o 'main'
entrypoint = <punto di ingresso>

# Numero di input da eseguire senza che venga trovato un breakpoint prima
# della rotazione dei breakpoint.
until_rotate_breakpoints = <numero>


# Numero massimo di breakpoint che possono essere posizionati contemporaneamente.
max_breakpoints = <numero>

# Elenco di funzioni da ignorare (blacklist).
# ignore_functions è un elenco di nomi di funzione separati da spazi, es. 'malloc free'.
ignore_functions = <elenco separato da spazi>

# Uno tra {Hardware, QEMU, SUTRunsOnHost}
# Hardware: un componente esterno avvia un server gdb e GDBFuzz può connettersi a questo server gdb.
# QEMU: GDBFuzz avvia QEMU. QEMU emula binary_file_path e avvia gdbserver.
# SUTRunsOnHost: GDBFuzz avvia il programma target all'interno di GDB.
target_mode = <modalità>

# Imposta a False se si desidera avviare ghidra, analizzare il SUT,
# e avviare il bridge ghidra manualmente.
start_ghidra = True


# Elenco separato da spazi di indirizzi dove vengono impostati breakpoint software (per
# codice di gestione degli errori). L'esecuzione di questi viene considerata un crash.
# Esempio: software_breakpoint_addresses = 0x123 0x432
software_breakpoint_addresses = 


# Se tutti i breakpoint software attivati devono essere considerati come crash
consider_sw_breakpoint_as_error = False

[SUTConnection]
# La classe 'SUT_connection_class' nel file 'SUT_connection_path' implementa
# come vengono inviati gli input al SUT.
# Gli input possono essere inviati, ad esempio, tramite Wi-Fi, Serial, Bluetooth, ...
# Questa classe deve ereditare da ./connections/SUTConnection.py.
# Vedere ./connections/SUTConnection.py per maggiori informazioni.
SUT_connection_file = FIFOConnection.py

[GDB]
path_to_gdb = gdb-multiarch
#Scritto in address:port
gdb_server_address = localhost:4242

[Fuzzer]
# In byte
maximum_input_length = 100000
# In secondi
single_run_timeout = 20
# In secondi
total_runtime = 3600

# Opzionale
# Percorso di una directory in cui ogni file contiene un seed. Se non si desiderano
# utilizzare seed, lasciare il valore vuoto.
seeds_directory = 

[BreakpointStrategy]
# Le strategie per scegliere i blocchi di base si trovano in
# 'src/GDBFuzz/breakpoint_strategies/'
# Nell'articolo utilizziamo le seguenti strategie
# 'RandomBasicBlockStrategy.py' - Scelta casuale di blocchi di base non raggiunti
# 'RandomBasicBlockNoDomStrategy.py' - Come il precedente, ma non utilizza le relazioni di dominanza per derivare i nodi raggiunti transitivamente.
# 'RandomBasicBlockNoCorpusStrategy.py' - Come il primo, ma impedisce la crescita del corpus di input e quindi si comporta come un fuzzing blackbox con misurazione della copertura.
# 'BlackboxStrategy.py', - Non imposta alcun breakpoint
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]
# Uno tra {DEBUG, INFO, WARNING, ERROR, CRITICAL}
loglevel = INFO

# Percorso di una directory in cui vengono salvati i file di output (es. grafici, file di log).
output_directory = ./output

# Se impostato a True, un client MQTT invia elementi UI (es. grafici)
enable_UI = False

Un file di configurazione di esempio si trova in ./example_programs/ insieme a un programma di esempio compilato utilizzando il nostro harness di fuzzing in benchmark/benchSUTs/GDBFuzz_wrapper/common/. Avviare il fuzzing per un'ora con il seguente comando.

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

Vedremo prima l'output di Ghidra che analizza il binario eseguibile e successivamente i messaggi quando i breakpoint vengono riposizionati o attivati.

Output del Fuzzing

A seconda della output_directory specificata nel file di configurazione, ora dovrebbe esserci una cartella trial-0 con la seguente struttura

root@kitploit:~
.
    ├── corpus            # Cartella che contiene il corpus di input.
    ├── crashes           # Cartella che contiene gli input che causano crash - se presenti.
    ├── cfg               # Il grafo di flusso di controllo come lista di adiacenza.
    ├── fuzzer_stats      # Statistiche della campagna di fuzzing.
    ├── plot_data         # Tabella che mostra a quale tempo relativo nella campagna di fuzzing è stato raggiunto un determinato blocco di base.
    ├── reverse_cfg       # Il grafo di flusso di controllo inverso.

Utilizzo di Ghidra in modalità GUI

Impostando start_ghidra = False nel file di configurazione, GDBFuzz si connette a un'istanza di Ghidra in esecuzione in modalità GUI. Pertanto, il plugin ghidra_bridge deve essere avviato manualmente dal gestore script. Durante il fuzzing, i blocchi di programma raggiunti vengono evidenziati in verde.

GDBFuzz su programmi Linux utente

Per il fuzzing su applicazioni Linux utente, GDBFuzz sfrutta il punto di ingresso standard LLVMFuzzOneInput utilizzato da quasi tutti i fuzzer come AFL, AFL++, libFuzzer,... In benchmark/benchSUTs/GDBFuzz_wrapper/common è presente un wrapper che può essere utilizzato per compilare qualsiasi harness di fuzzing conforme in un programma standalone che legge input da una named pipe in /tmp/fromGDBFuzz. Ciò consente di simulare un dispositivo embedded che consuma dati attraverso un'interfaccia di input ben definita e quindi eseguire GDBFuzz su qualsiasi applicazione. Per comodità, abbiamo creato uno script in benchmark/benchSUTs che compila tutti i programmi della nostra valutazione con il nostro wrapper, come spiegato in seguito.

NOTA: GDBFuzz non è progettato per fare fuzzing su applicazioni Linux utente. Utilizzare AFL++ o altri fuzzer a tale scopo. Il wrapper esiste solo a scopo di valutazione per poter eseguire benchmark e confronti su larga scala!

Installazione ed esecuzione in un contenitore Docker

L'efficacia generale del nostro approccio è mostrata in un benchmark su larga scala distribuito come contenitori docker.

root@kitploit:~
make dockerimage

Per eseguire l'esperimento sopra nel contenitore docker (per un'ora come specificato nel file di configurazione), mappare le cartelle example_programs e output come volumi e avviare GDBFuzz come segue.

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

Una cartella di output dovrebbe apparire nella directory di lavoro corrente con la struttura spiegata sopra.

Istruzioni Dettagliate

La nostra valutazione è suddivisa in due parti.

  1. GDBFuzz sul suo setup previsto, direttamente sull'hardware.
  2. GDBFuzz in un ambiente emulato per consentire un'analisi indipendente e confronti dei risultati.

GDBFuzz può funzionare con qualsiasi server GDB e quindi con la maggior parte delle sonde di debug per microcontrollori.

GDBFuzz vs. Blackbox (RQ1)

Per quanto riguarda RQ1 dell'articolo, eseguiamo GDBFuzz su diversi microcontrollori con diversi firmware situati in example_firmware. Per ogni esperimento eseguiamo GDBFuzz con la strategia RandomBasicBlock e con RandomBasicBlockNoCorpus. Quest'ultima si comporta come un fuzzing senza feedback, ma possiamo comunque misurare la copertura raggiunta. Per rispondere a RQ1, confrontiamo la copertura raggiunta dalla strategia RandomBasicBlock e RandomBasicBlockNoCorpus. I file di configurazione corrispondenti si trovano nelle rispettive sottocartelle e ora spieghiamo come impostare il fuzzing su quattro schede di sviluppo.

GDBFuzz su scheda STM32 B-L4S5I-IOT01A

GDBFuzz richiede l'accesso a un server GDB. In questo caso vengono utilizzati la B-L4S5I-IOT01A e il suo debugger integrato. Questo debugger integrato configura un server GDB tramite il programma 'st-util' e consente l'accesso a questo server GDB tramite localhost:4242.

  • Installare il driver STLINK link
  • Collegare la scheda MCU e il PC tramite USB (sulla scheda MCU, collegarsi al connettore USB etichettato come 'USB STLINK')
root@kitploit:~
sudo apt-get install stlink-tools gdb-multiarch

Compilare e caricare un firmware per la STM32 B-L4S5I-IOT01A, ad esempio il progetto arduinojson.

Prerequisito: Installare platformio (pio)

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

Per tua informazione: platformio memorizza un file .elf del SUT qui: ./example_firmware/stm32_disco_arduinojson/.pio/build/disco_l4s5i_iot01a/firmware.elf Questo file .elf verrà utilizzato anche successivamente nella configurazione utente per Ghidra.

Avviare un nuovo terminale ed eseguire quanto segue per avviare il server GDB:

root@kitploit:~
st-util

Eseguire GDBFuzz con una configurazione utente per arduinojson. Possiamo inviare dati tramite la porta USB al microcontrollore. Il microcontrollore inoltra questi dati tramite seriale al SUT. Nel nostro caso /dev/ttyACM0 è il dispositivo USB della scheda microcontrollore. Se il tuo sistema ha assegnato un altro dispositivo alla scheda microcontrollore, modifica /dev/ttyACM0 nel file di configurazione con il tuo dispositivo.

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

Le statistiche e i log del fuzzer si trovano nella directory ./output/...

GDBFuzz sulla scheda CY8CKIT-062-WiFi-BT

Installare pyocd:

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

Assicurarsi che 'KitProg v3' sia presente sul dispositivo e mettere la scheda in modalità 'Arm DAPLink' premendo l'apposito pulsante. Avviare il server GDB:

root@kitploit:~
pyocd gdbserver --persist

Caricare un firmware e avviare il fuzzing, ad esempio con

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 su ESP32 e Segger J-Link

  • Installare ESP32 SDK

Compilare e caricare un firmware per ESP32, ad esempio l'esempio arduinojson con platformio.

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

Aggiungere la seguente riga al file di configurazione di openocd per il debugger J-Link: jlink.cfg

root@kitploit:~
adapter speed 10000

Avviare un nuovo terminale ed eseguire quanto segue per avviare il server GDB:

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

Eseguire GDBFuzz con una configurazione utente per arduinojson. Possiamo inviare dati tramite la porta USB al microcontrollore. Il microcontrollore inoltra questi dati tramite seriale al SUT. Nel nostro caso /dev/ttyUSB0 è il dispositivo USB della scheda microcontrollore. Se il tuo sistema ha assegnato un altro dispositivo alla scheda microcontrollore, modifica /dev/ttyUSB0 nel file di configurazione con il tuo dispositivo.

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

Le statistiche e i log del fuzzer si trovano nella directory ./output/...

GDBFuzz su MSP430F5529LP

Installare TI MSP430 GCC da https://www.ti.com/tool/MSP430-GCC-OPENSOURCE

Avviare il server GDB

root@kitploit:~
./gdb_agent_console libmsp430.so

oppure (più stabile). Compilare mspdebug da https://github.com/dlbeer/mspdebug/ e utilizzare:

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

Ghidra non riesce ad analizzare i binari per il controller TI MSP430 immediatamente. Per risolvere, importare il file nella GUI di Ghidra, scegliere MSP430X come architettura e saltare l'analisi automatica. Successivamente, aprire la 'Tabella dei simboli', ordinarli per nome ed eliminare tutti i simboli con nomi come $C$L*. Ora l'analisi automatica può essere eseguita. Dopo l'analisi, avviare il bridge ghidra manualmente dalla GUI di Ghidra e quindi avviare GDBFuzz.

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

Fuzzing USB

Per accedere ai dispositivi USB come utente non root con pyusb, aggiungiamo regole appropriate a udev. Incollare le seguenti righe in /etc/udev/rules.d/50-myusb.rules:

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

Ricarica udev:

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

Confronto con Fuzzware (RQ2)

In RQ2 dell'articolo, confrontiamo GDBFuzz con l'approccio basato su emulazione Fuzzware. Prima eseguiamo GDBFuzz e Fuzzware come descritto in precedenza sui file firmware forniti. Per ogni esperimento GDBFuzz, creiamo un file con i blocchi di base validi dai file del grafo di flusso di controllo come segue:

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

Ora possiamo riprodurre la copertura rispetto al risultato di fuzzware fuzzware genstats --valid-bb-file valid_bbs.txt

Trovare Bug (RQ3)

Quando vengono trovati input che causano crash o blocchi, vengono salvati nella cartella crashes. Durante la valutazione, abbiamo trovato i seguenti tre bug:

  1. Un loop infinito nello stack del dispositivo USB STM32, causato dal conteggio di una variabile indice uint8_t in una variabile uint32_t controllabile dall'attaccante all'interno di un ciclo for.
  2. Un buffer overflow nel parser JSON Cypress, causato da controlli di lunghezza mancanti su un buffer interno a dimensione fissa.
  3. Una dereferenza di puntatore nullo nel parser JSON Cypress, causata da controlli di validazione mancanti.

GDBFuzz su un Raspberry Pi 4 (8Gb)

GDBFuzz può essere eseguito anche su un host Raspberry Pi con piccole modifiche:

  1. Ghidra deve essere modificato in modo che funzioni su un sistema operativo a 32 bit

Nel file ./dependencies/ghidra/support/launch.sh:125 la variabile JAVA_HOME deve essere hard-coded, ad esempio a JAVA_HOME="/usr/lib/jvm/default-java"

  1. STLink deve essere almeno versione 1.7 per funzionare correttamente -> Compilare dai sorgenti

GDBFuzz su altre schede

Per eseguire il fuzzing su altre schede, GDBFuzz richiede

  1. Un microcontrollore con breakpoint hardware e una sonda di debug compatibile con GDB
  2. Il file del firmware.
  3. Un GDBServer in esecuzione e un'applicazione GDB adatta.
  4. Un punto di ingresso da cui iniziare il fuzzing, ad esempio una funzione parser o un indirizzo
  5. Un'interfaccia di input (vedi src/GDBFuzz/connections) che attivi l'esecuzione del codice al punto di ingresso, ad esempio una connessione seriale

Tutte queste proprietà devono essere specificate nel file di configurazione.

Eseguire il Benchmark completo (RQ4 - 8)

Per le RQ 4 - 8 eseguiamo un benchmark su larga scala. Prima, costruire l'immagine Docker come descritto in precedenza e compilare le applicazioni della Fuzzer Test Suite di Google con il nostro harness di fuzzing in benchmark/benchSUTs/GDBFuzz_wrapper/common.

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

Successivamente, adattare le impostazioni del benchmark in benchmark/scripts/benchmark.py e benchmark/scripts/benchmark_aflpp.py alle proprie esigenze (in particolare number_of_cores, trials e seconds_per_trial) e avviare il benchmark con:

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

Una cartella appare in ./benchmark/scripts che contiene i file di plot (copertura nel tempo), i file di statistiche del fuzzer e i file del grafo di flusso di controllo per ogni esperimento, come in evaluation/fuzzer_test_suite_qemu_runs.

[Opzionale] Installare la Visualizzazione e un Esempio di Visualizzazione

GDBFuzz ha una funzionalità opzionale in cui traccia il grafo di flusso di controllo dei nodi coperti. È disabilitata per impostazione predefinita. Puoi abilitarla seguendo le istruzioni di questa sezione e impostando 'enable_UI' a 'True' nella configurazione utente.

Sull'host:

Installare

root@kitploit:~
sudo apt-get install graphviz

Installare una versione recente di node, ad esempio Opzione 2 da qui. Utilizzare Opzione 2 e non Opzione 1. Questo dovrebbe installare sia node che npm. Per riferimento, i nostri numeri di versione sono (ma versioni più recenti dovrebbero funzionare):

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

Installare le dipendenze dell'interfaccia web:

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

Installare il broker MQTT mosquitto, ad esempio vedere qui

Aggiornare la configurazione del broker mosquitto: Sostituire il file /etc/mosquitto/conf.d/mosquitto.conf con il seguente contenuto:

root@kitploit:~
listener 1883
allow_anonymous true

listener 9001
protocol websockets

Riavviare il broker mosquitto:

root@kitploit:~
sudo service mosquitto restart

Verificare che il broker mosquitto sia in esecuzione:

root@kitploit:~
sudo service mosquitto status

L'output dovrebbe includere il testo 'Active: active (running)'

Avviare l'interfaccia web:

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

Il browser web dovrebbe aprirsi automaticamente su 'http://localhost:3000/'.

Avviare GDBFuzz e utilizzare un file di configurazione utente in cui enable_UI è impostato su True. Puoi utilizzare il contenitore Docker e il SUT arduinojson di cui sopra. Ma assicurati di impostare 'enable_UI' su 'True'.

I nodi coperti in 'blu' sono coperti. I nodi bianchi non sono coperti. Mostriamo solo i nodi non coperti se il loro genitore è coperto (disegnare il grafo di flusso di controllo completo richiede troppo tempo se il grafo è grande).

Licenza

GDBFuzz è open-source sotto la licenza AGPL-3.0. Vedi il file LICENSE per i dettagli.

Per un elenco di altri componenti open source inclusi in GDBFuzz, vedi il file 3rd-party-licenses.txt.

Scarica lo strumento