
Framework di analisi statica che identifica bersagli di funzioni fuzzabili in codice sorgente e binari, genera modelli di harness e si integra con AFL++ e libFuzzer per la scoperta automatizzata di vulnerabilità.
Framework per l'automazione della scoperta di target fuzzabili con l'analisi statica

I ricercatori di vulnerabilità che conducono valutazioni della sicurezza del software spesso sfruttano le capacità del fuzzing guidato dalla copertura attraverso strumenti potenti come AFL++ e libFuzzer. Ciò è importante poiché automatizza il processo di caccia ai bug e rivela rapidamente condizioni sfruttabili nei target. Tuttavia, quando si incontrano codebase grandi e complesse o binari closed-source, i ricercatori devono dedicare tempo notevole per revisionare manualmente e fare reverse engineering per identificare funzioni in cui l'esplorazione basata sul fuzzing può essere utile.
Fuzzable è un framework che si integra sia con codice sorgente C/C++ che con binari per assistere i ricercatori di vulnerabilità nell'identificare funzioni target che sono valide per il fuzzing. Ciò viene fatto applicando diverse euristiche basate sull'analisi statica per individuare comportamenti rischiosi nel software e le funzioni che li eseguono. I ricercatori possono quindi utilizzare il framework per generare modelli di harness di base, che possono poi essere usati per cacciare vulnerabilità, o essere integrati come parte di una pipeline di fuzzing continuo, come il progetto oss-fuzz di Google.
Oltre a funzionare come strumento autonomo, Fuzzable è anche integrato come plugin per il disassemblatore Binary Ninja, con supporto per altri backend di disassemblaggio in fase di sviluppo.
Consulta il post originale del blog che descrive lo strumento qui, che evidenzia le specifiche tecniche delle euristiche di analisi statica e come è nato questo strumento. Questo strumento è anche presentato al Black Hat Arsenal USA 2022.
Alcuni target binari potrebbero richiedere una certa sanificazione (ad esempio, corrispondenza delle firme o identificazione delle funzioni da inlining), e quindi fuzzable utilizza principalmente Binary Ninja come backend di disassemblaggio per la sua capacità di risolvere efficacemente questi problemi. Pertanto, può essere utilizzato sia come strumento autonomo che come plugin.
Poiché Binary Ninja non è accessibile a tutti e potrebbe esserci una richiesta di utilizzo per valutazioni di sicurezza e potenzialmente di scalare nel cloud, è supportato anche un backend fallback angr. Prevedo di incorporare anche altri disassemblatori in futuro (priorità: Ghidra).
Se possiedi Binary Ninja Commercial, assicurati di installare l'API per l'uso headless standalone:
$ python3 /Applications/Binary\ Ninja.app/Contents/Resources/scripts/install_api.py
Installa con pip:
$ pip install fuzzable
Usiamo poetry per la gestione delle dipendenze e il build. Per fare un build manuale, clona il repository con i moduli di terze parti:
$ git clone --recursive https://github.com/ex0dus-0x/fuzzable
Per installare manualmente:
$ cd fuzzable/
# without poetry
$ pip install .
# with poetry
$ poetry install
# with poetry for a development virtualenv
$ poetry shell
Ora puoi analizzare binari e/o codice sorgente con lo strumento!
# analyzing a single shared object library binary
$ fuzzable analyze examples/binaries/libbasic.so
# analyzing a single C source file
$ fuzzable analyze examples/source/libbasic.c
# analyzing a workspace with multiple C/C++ files and headers
$ fuzzable analyze examples/source/source_bundle/
fuzzable può essere facilmente installato tramite il marketplace dei plugin di Binary Ninja andando su Binary Ninja > Gestisci Plugin e cercandolo. Ecco un esempio del plugin fuzzable in esecuzione, che identifica con precisione i target per il fuzzing e ulteriori valutazioni di vulnerabilità:

fuzzable viene fornito con varie opzioni per aiutarti a ottimizzare l'analisi. Altre saranno supportate in piani futuri e in base a eventuali richieste di funzionalità.
Per determinare la fuzzabilità, fuzzable utilizza diverse euristiche per determinare quali target sono i più validi per l'analisi dinamica. Queste euristiche vengono tutte ponderate in modo diverso utilizzando la libreria scikit-criteria, che utilizza l'analisi decisionale multi-criterio per determinare i migliori candidati. Queste metriche e i loro pesi possono essere visti qui:
| Euristiche | Descrizione | Peso |
|---|---|---|
| Fuzz Friendly Name | Il nome del simbolo implica un comportamento che assume input da file/buffer | 0.3 |
| Risky Sinks | Argomenti che fluiscono in chiamate rischiose (es. memcpy) | 0.3 |
| Natural Loops | Numero di cicli rilevati con la frontiera di dominanza | 0.05 |
| Cyclomatic Complexity | Complessità della funzione target basata su archi + nodi | 0.05 |
| Coverage Depth | Numero di callee che il target attraversa | 0.3 |
Come detto, consulta il post tecnico del blog per un approfondimento su perché e come vengono utilizzate queste metriche.
Molte metriche sono state ampiamente ispirate dal lavoro originale di Vincenzo Iozzo nel fuzzing a conoscenza zero.
Ogni target che vuoi analizzare è diverso, e fuzzable non sarà in grado di tenere conto di ogni comportamento borderline nel programma target. Pertanto, durante l'analisi potrebbe essere importante regolare questi pesi in modo appropriato per vedere se risultati diversi hanno più senso per il tuo caso d'uso. Per regolare questi pesi nella CLI, specifica semplicemente l'argomento --score-weights:
$ fuzzable analyze <TARGET> --score-weights=0.2,0.2,0.2,0.2,0.2
Per impostazione predefinita, fuzzable filtrerà i target di funzione in base ai seguenti criteri: