
Manul è un fuzzatore parallelo guidato dalla copertura per binari open-source e blackbox su Windows, Linux e MacOS

Manul è un fuzzer parallelo guidato dalla copertura per binari open-source e black-box su Windows, Linux e macOS (beta) scritto in puro Python.
pip3 install psutil
git clone https://github.com/mxmssh/manul
cd manul
mkdir in
mkdir out
echo "AAAAAA" > in/test
python3 manul.py -i in -o out -n 4 "linux/test/test_afl @@"
sudo apt-get install gcc make git wget
git clone https://gitlab.com/akihe/radamsa.git && cd radamsa && make && sudo make install
Non è necessario installare radamsa su Windows, Manul è distribuito con la libreria nativa di radamsa su questa piattaforma.
| CVE IDs | Prodotto | Rilevatore |
|---|---|---|
| CVE-2019-9631 CVE-2019-7310 CVE-2019-9959 | Poppler | Maksim Shudrak |
| CVE-2018-17019 CVE-2018-16807 CVE-2019-12175 | Bro/Zeek | Maksim Shudrak |
Se sei riuscito a trovare un nuovo bug usando Manul, contattami e ti aggiungerò all'elenco.

pip install pywin32) su piattaforma Windows (richiesto solo per la modalità di persistenza DBI).Attualmente, Manul supporta due tipi di strumentazione: basata su AFL (afl-gcc, afl-clang e afl-clang-fast) e DBI.
Strumenta il tuo target con afl-gcc o afl-clang-fast e Address Sanitizer (raccomandato per risultati migliori). Ad esempio:
CC=afl-gcc CXX=afl-g++ CFLAGS=-fsanitize=address CXXFLAGS=-fsanitize=address cmake <percorso_al_target>
make -j 8
USE_ASAN=1 CC=afl-clang-fast CXX=afl-clang-fast++ cmake <percorso_al_target>
make -j 8
Vedi queste istruzioni per maggiori dettagli.
In questa modalità non è necessario strumentare il target, ma è necessario scaricare l'ultima versione del framework DynamoRIO per Windows o Linux.
Manul è distribuito con client x86/x64 precompilati per Linux e Windows. Puoi trovarli nelle seguenti cartelle:
linux/dbi_32|dbi_64/libbinafl.so (client DynamoRIO)
win/dbi_32|dbi_64/binafl.dll
Purtroppo DynamoRIO non è ufficialmente supportato su MacOS.
Puoi trovare i pacchetti di rilascio più recenti di DynamoRIO alla pagina di download di DynamoRIO.
Devi decommentare le seguenti righe nel file manul.config e fornire il percorso corretto al launcher e al client di DynamoRIO.
# Scegli il framework DBI per fornire la copertura a Manul ("dynamorio" o "pin"). Esempio dbi = dynamorio
dbi = dynamorio
# Se il parametro dbi non è None, devono essere specificati il percorso del launcher del motore DBI e del client DBI.
dbi_root = /home/max/DynamoRIO/bin64/drrun
dbi_client_root = /home/max/manul/linux/dbi_64/libbinafl.so
dbi_client_libs = None
Inoltre, puoi aumentare le prestazioni della tua campagna di fuzzing black-box utilizzando il fuzzing persistente in memoria. In questa modalità, dovresti istruire Manul a strumentare una particolare funzione (sì, devi trovarla disassemblando il tuo binario) e la eseguirà in un ciclo decommentando le seguenti righe:
dbi_persistence_mode = 1
dbi_target_module = afl_test
dbi_target_method = open_file
#dbi_target_offset = 0x3198 # opzionalmente puoi fornire l'offset di questa funzione invece del nome
dbi_fuzz_iterations = 1000
Gli autori di winAFL forniscono una spiegazione molto chiara su come funziona effettivamente qui. Manul utilizza una larga porzione del codice della libreria di strumentazione di winAFL per comunicare e strumentare un target.
NOTA IMPORTANTE: Dovresti usare il launcher a 32 bit e il client a 32 bit per fare fuzzing di binari a 32 bit, e il launcher a 64 bit e il client a 64 bit per binari a 64 bit!
Per compilare la libreria di strumentazione, devi usare l'ultima versione di DynamoRIO. Il codice sorgente della libreria di strumentazione si trova in dbi_clients_src nella cartella principale di Manul.
Linux a 64 bit
cd dbi_clients_src
wget <DynamoRIO-x86_64-Linux-X.XX.XXXX-X.tar.gz> - scarica l'ultimo DynamoRIO
tar xvf DynamoRIO-x86_64-X.XX.XXXX-X.tar.gz
mkdir client_64
cd client_64
cmake ../dr_cov/ -DDynamoRIO_DIR=/home/max/manul/dbi_clients_src/DynamoRIO-x86_64-Linux-X.XX.XXXX-X.tar.gz/cmake
make
Linux a 32 bit
cd dbi_clients_src
wget <DynamoRIO-i386-Linux-X.XX.XXXX-X.tar.gz> - scarica l'ultimo DynamoRIO
tar xvf DynamoRIO-x86_64-X.XX.XXXX-X.tar.gz
mkdir client_64
cd client_64
CFLAGS=-m32 CXXFLAGS=-m32 cmake ../dr_cov/ -DDynamoRIO_DIR=/home/max/manul/dbi_clients_src/DynamoRIO-i386-Linux-X.XX.XXXX-X.tar.gz/cmake
make
Su Windows, il modo più semplice per compilare la libreria è installare Visual Studio (testato su versioni 2017 e 2013), avviare il Prompt dei comandi degli strumenti incrociati VS20XX ed eseguire i seguenti comandi:
Windows a 64 bit
cd dbi_clients_src
<Scarica ed estrai l'ultima versione di DynamoRIO>
mkdir client_64
cd client_64
cmake -G"Visual Studio 15 Win64" ..\dr_cov\ -DDynamoRIO_DIR=C:\Users\max\manul\dbi_clients_src\DynamoRIO-Windows-XXXX.XX.X.X\cmake
cmake --build . --config RelWithDebInfo (o Debug se necessario)
Windows a 32 bit
cd dbi_clients_src
<Scarica ed estrai l'ultima versione di DynamoRIO>
mkdir client_32
cd client_32
cmake -G"Visual Studio 15" ..\dr_cov\ -DDynamoRIO_DIR=C:\Users\max\manul\dbi_clients_src\DynamoRIO-Windows-XXXX.XX.X.X\cmake
cmake --build . --config RelWithDebInfo (o Debug se necessario)
Manul inizialmente supportava il fuzzing guidato dalla copertura con Intel PIN, ma a causa delle basse prestazioni e dell'elevato overhead di manutenzione, questo non è più supportato.
Le opzioni più frequentemente utilizzate possono essere fornite tramite riga di comando. Ulteriori opzioni sono supportate tramite file di configurazione (manul.config).
Esempio: python3 manul.py -i corpus -o out_dir -n 40 "target @@"
argomenti posizionali:
target_binary Il binario target e le opzioni da eseguire (non dimenticare le virgolette, es. "target e @@").
argomenti opzionali:
-h, --help mostra questo messaggio di aiuto ed esce
-n NFUZZERS Numero di fuzzer paralleli
-s Esegui fuzzing stupido (nessuna strumentazione del codice)
-c CONFIG Percorso del file di configurazione con opzioni aggiuntive (vedi la sezione Opzioni del File di Configurazione sotto)
-r Ripristina sessione precedente
Parametri richiesti:
-i INPUT Percorso della directory con il corpus iniziale
-o OUTPUT Percorso della directory di output
Manul è distribuito con il file predefinito manul.config in cui l'utente può trovare tutte le opzioni supportate ed esempi di utilizzo. Le opzioni devono essere specificate nel formato Formato: <nome_opzione> = <valore>. Il simbolo # può essere usato per ignorare una riga.
dict = /home/max/dictionaries/test.dict. La strategia di mutazione di AFL permette all'utente di specificare una lista di token personalizzati che possono essere inseriti in punti casuali del file fuzzato. Manul supporta questa funzionalità tramite questa opzione (preferiti percorsi assoluti).
mutator_weights=afl:7,radamsa:2,my_mutator:1. I pesi dei mutatori permettono all'utente di dire a Manul quante mutazioni per 10 esecuzioni devono essere eseguite da un certo fuzzer. In questo esempio, il mutatore AFL verrà eseguito in 7/10 mutazioni, Radamsa in 2/10 e un mutatore personalizzato my_mutator riceverà 1/10. Se si desidera disabilitare un certo mutatore, il peso deve essere impostato a 0 (es. mutator_weights=afl:0,radamsa:1,my_mutator:9).
deterministic_seed = False|True. Impostando True, le mutazioni di Radamsa diventeranno deterministiche, quindi ogni esecuzione di Manul porterà agli stessi output.
print_per_thread = False|True. Abilitando questa opzione, Manul stamperà un riepilogo per ogni thread eseguito invece del riepilogo totale.
disable_volatile_bytes = False|True Abilitando questa opzione, Manul non metterà in blacklist i percorsi volatili.
forkserver_on = False|True Abilita o disabilita il fork server di AFL.
dbi = dynamorio|pin. Questa opzione dice a Manul quale framework DBI verrà utilizzato per strumentare il target.
dbi_root = <percorso>. Questa opzione dice a Manul dove trovare il launcher principale del framework DBI.
dbi_client_root = <percorso>. Questa opzione dice a Manul dove trovare il client DBI per eseguire la strumentazione.
dbi_client_libs = nome_#1,nome_#2|None. Questa opzione può essere usata per specificare una lista di librerie che devono essere strumentate insieme al target principale (ad esempio, hai un eseguibile che carica la libreria target più altre in cui vuoi cercare bug).
dbi_persistence_mode = 0|1|2. Questa opzione viene utilizzata per scegliere tra le modalità di persistenza DBI. 0 - nessuna persistenza, 1 - persistenza standard (wrapping delle funzioni), 2 - non ancora supportata.
Se dbi-persistence_mode = 1|2 devono essere specificate le seguenti opzioni:
dbi_target_module = <nome modulo>. Manul cercherà di trovare la funzione target nel modulo specificato qui.
dbi_target_method = <nome funzione>. Nome della funzione da avvolgere per la persistenza.
dbi_target_offset = <offset della funzione, es. 0x3198>. Offset della funzione da avvolgere per la persistenza. Questa opzione può essere usata al posto di dbi_target_method se non sono disponibili simboli di debug.
dbi_fuzz_iterations = 500. Il numero di iterazioni di fuzzing da eseguire in memoria prima che l'intero programma riparta. Puoi giocare con questo argomento per trovare il valore che funziona meglio con il tuo target.
dbi_thread_coverage = False. Strumenta la copertura solo dal thread che ha eseguito la funzione target (non ancora supportato).
timeout = 10. Tempo di attesa prima di killare il target e inviare il caso di test successivo.
init_wait = 1. Questa opzione può essere usata per impostare un timeout necessario per l'inizializzazione del target.
Le opzioni net_config_master e net_config_slave sono utilizzate per distribuire istanze di Manul sulla rete. Devi eseguire i seguenti 3 passaggi per eseguire il fuzzing distribuito.
IP:porta dove verranno eseguiti i tuoi slave.net_config_slave = 0.0.0.0:1337. Manul avvierà l'istanza e attenderà una connessione in entrata dall'istanza master sulla porta 1337.net_config_master = nome_file.debug = False|True - stampa informazioni di debug.
logging_enable = False|True - salva informazioni di debug nel log.
manul_logo = False|True - stampa il logo di Manul all'inizio.
no_stats = False|True - salva le statistiche.
sync_freq = 10000. Permette all'utente di cambiare la frequenza di sincronizzazione della bitmap di copertura. Questa opzione dice a Manul quanto spesso deve sincronizzare la copertura tra le istanze di fuzzing parallele. Un valore più basso diminuisce le prestazioni ma aumenta la coordinazione tra le istanze.
#custom_path = test_path - questa opzione permette di salvare il caso di test in una cartella personalizzata (se il target vuole caricarlo da un posto predefinito).
cmd_fuzzing = True|False. Se questa opzione è abilitata, Manul fornirà l'input al target tramite linea di comando invece di salvarlo in un file.
user_signals = 6,2,1|None. L'utente può dire a Manul quali segnali dal target devono essere ignorati (non considerati come crash).
target_ip_port = 127.0.0.1:7715|None - utilizzato per specificare IP e PORTA del target.
target_protocol = tcp|tcp - utilizzato per specificare il protocollo per inviare l'input al target tramite rete.
net_sleep_between_cases = 0.0. Questa opzione può essere usata per definire un ritardo tra i casi di test inviati al target.
Attualmente, il fuzzing di rete è una funzionalità sperimentale (vedi issues per maggiori dettagli).
Un mutatore personalizzato può essere aggiunto nei seguenti tre passaggi: Passo 1. Crea un file Python (.py) e dagli un nome (es. example_mutator.py)
Passo 2. Crea due funzioni def init(fuzzer_id) e def mutate(data). Vedi example_mutator per maggiori dettagli. Manul chiamerà la funzione init durante l'inizializzazione del fuzzing e mutate per ogni file fornito nel target.
Passo 3. Abilita il mutatore specificandone il nome usando mutator_weights in manul.config. Ad esempio: mutator_weights=afl:2,radamsa:0,example_mutator:8.
NOTA: I mutatori AFL e Radamsa devono sempre essere specificati. Se vuoi disabilitare AFL e/o Radamsa, assegna loro peso 0.
TBD
