Les deux révisions précédentesRévision précédenteProchaine révision | Révision précédente |
prog:fuzzer:afl [2019/03/14 07:35] – [Sanitizers] : ajout des options de compilation sans configure ni cmake root | prog:fuzzer:afl [2023/10/06 09:55] (Version actuelle) – [Sanitizers] : mise à jour avec afl++ root |
---|
[[http://lcamtuf.coredump.cx/afl/|Américan Fuzzy Lop]] cherche à vérifier l'intégrité d'un logiciel ou d'une librairie dans le cas d'ouverture de fichiers. | [[https://aflplus.plus/|AFL++]] cherche à vérifier l'intégrité d'un logiciel ou d'une librairie dans le cas d'ouverture de fichiers. |
| |
Dans les cas ci-dessous, le dossier ''testcases'' contient les cas de base qui seront altérés et le dossier ''findings'' contient les cas altérés ayant eux un chemin unique dans le programme. | Il est le successeur de [[https://lcamtuf.coredump.cx/afl/|AFL]] qui a été abandonné. |
| |
=====Compilation à l'application===== | =====Compilation de AFL++===== |
| |
| La compilation nécessite Python et donc l'utilisation d'un environnement virtuel. |
| |
| <code bash> |
| cd AFLplusplus |
| python3 -m venv .venv |
| source .venv/bin/activate |
| pip install wheel |
| make distrib |
| </code> |
| |
| [[https://github.com/AFLplusplus/AFLplusplus/blob/stable/docs/INSTALL.md|INSTALL.md]] {{ :prog:fuzzer:afl:aflplusplus_docs_install.md_at_stable_aflplusplus_aflplusplus_05_10_2023_11_29_47_.html |Archive du 19/09/2023 le 05/10/2023}} |
| =====Programme à tester===== |
====Cas général==== | ====Cas général==== |
| |
| ===Configurer la compilation=== |
| |
<code bash> | <code bash> |
cd program | cd program |
</code> | </code> |
| |
puis compiler au choix en fonction du programme : | puis compiler au choix en fonction du programme : |
| |
| * configure |
| |
<code bash> | <code bash> |
CC=afl-gcc CXX=afl-g++ ./configure | CC=afl-clang-lto CXX=afl-clang-lto++ RANLIB=llvm-ranlib AR=llvm-ar AS=llvm-as ./configure |
CC=afl-gcc CXX=afl-g++ cmake . | |
</code> | </code> |
et finissez par | |
| * cmake |
<code bash> | <code bash> |
make | mkdir build |
mkdir findings testcases | cd build |
afl-fuzz -i testcases -o findings -- program/bin/executable @@ | CC=afl-clang-lto CXX=afl-clang-lto++ RANLIB=llvm-ranlib AR=llvm-ar AS=llvm-as cmake .. |
</code> | </code> |
Ici, le double arobase ''@@'' représente le fichier altéré généré par AFL. | |
| |
====Sanitizers==== | ===Compiler=== |
Un programme compilé peut ne pas forcément planter en cas d'accès à une zone en dehors d'un tableau (par exemple) si cette zone reste dans la même page mémoire ou si la page suivante est aussi allouée par le même processus. | |
| |
<note important>Les sanitizers en 64 bits demandent une taille de mémoire virtuelle de 20To. Il ne sera pas possible de sécuriser AFL en cas de bug d'allocation mémoire.</note> | <code bash> |
| make -j 8 |
| </code> |
| |
L'usage de variables d'environnement ''AFL_USE_ASAN'' / ''AFL_USE_MSAN'' / ''AFL_HARDEN'' ne donnent pas le même résultat que ''-fsanitizer''. L'usage des variables d'environnement est préférable. | ===Lancer le fuzzing=== |
| |
* ''AFL_USE_ASAN'' : ''-U_FORTIFY_SOURCE -fsanitize=address'' | Il faut mettre une liste de fichiers de base dans le dossier ''testcases''. |
* ''AFL_USE_MSAN'' : ''-U_FORTIFY_SOURCE -fsanitize=memory'' | |
* ''AFL_HARDEN'' : ''-fstack-protector-all -D_FORTIFY_SOURCE=2'' | |
| |
Comme on est dans un environnement multithread, on compile une version de programme pour chaque sanitizer qui serviront lors du fuzzing (voir ci-après). | Dans le dossier ''findings'' seront listés tous les cas altérés ayant eux un chemin unique dans le programme. |
| |
<code bash> | <code bash> |
CC=afl-gcc CXX=afl-g++ AFL_USE_ASAN=1 AFL_INST_RATIO=100 CFLAGS="-g -fno-omit-frame-pointer" CXXFLAGS="-g -fno-omit-frame-pointer" ./configure | mkdir findings testcases |
CC=afl-clang CXX=afl-clang++ AFL_USE_MSAN=1 AFL_INST_RATIO=100 CFLAGS="-g -fno-omit-frame-pointer" CXXFLAGS="-g -fno-omit-frame-pointer" LDFLAGS="-lgcc_s" ./configure | afl-fuzz -i testcases -o findings -- program/bin/executable @@ |
CC=afl-gcc CXX=afl-g++ AFL_HARDEN=1 CFLAGS="-g -fno-omit-frame-pointer" CXXFLAGS="-g -fno-omit-frame-pointer" ./configure | </code> |
CC=afl-gcc CXX=afl-g++ CFLAGS="-fsanitize=undefined -U_FORTIFY_SOURCE -g -fno-omit-frame-pointer" CXXFLAGS="-fsanitize=undefined -U_FORTIFY_SOURCE -g -fno-omit-frame-pointer" LDFLAGS="-lgcc_s" ./configure | |
CC=afl-clang CXX=afl-clang++ CFLAGS="-fsanitize=cfi -U_FORTIFY_SOURCE -flto -fvisibility=hidden -g -fno-omit-frame-pointer" CXXFLAGS="-fsanitize=cfi -U_FORTIFY_SOURCE -flto -fvisibility=hidden -g -fno-omit-frame-pointer" LDFLAGS="-lgcc_s" ./configure | |
| |
CC=afl-gcc CXX=afl-g++ AFL_USE_ASAN=1 AFL_INST_RATIO=100 cmake . | Ici, le double arobase ''@@'' représente le fichier altéré généré par AFL. |
CC=afl-clang CXX=afl-clang++ AFL_USE_MSAN=1 AFL_INST_RATIO=100 cmake . | |
CC=afl-gcc CXX=afl-g++ AFL_HARDEN=1 cmake . | |
CC=afl-gcc CXX=afl-g++ cmake -DCMAKE_C_FLAGS="-fsanitize=undefined -U_FORTIFY_SOURCE" -DCMAKE_CXX_FLAGS="-fsanitize=undefined -U_FORTIFY_SOURCE" . | |
CC=afl-clang CXX=afl-clang++ cmake -DCMAKE_C_FLAGS="-fsanitize=cfi -U_FORTIFY_SOURCE -flto -fvisibility=hidden" -DCMAKE_CXX_FLAGS="-fsanitize=undefined -U_FORTIFY_SOURCE -flto -fvisibility=hidden" . | |
| |
AFL_USE_ASAN=1 AFL_INST_RATIO=100 afl-g++ -g -fno-omit-frame-pointer -O2 main.cc -o main_asan | |
LDFLAGS="-lgcc_s" AFL_USE_MSAN=1 AFL_INST_RATIO=100 afl-clang++ -g -fno-omit-frame-pointer -O2 main.cc -o main_msan | |
AFL_HARDEN=1 afl-g++ -g -fno-omit-frame-pointer -O2 main.cc -o main_harden | |
LDFLAGS="-lgcc_s" afl-g++ -fsanitize=undefined -U_FORTIFY_SOURCE -g -fno-omit-frame-pointer -O2 main.cc -o main_undefined | |
LDFLAGS="-lgcc_s" afl-clang++ -fsanitize=cfi -U_FORTIFY_SOURCE -flto -fvisibility=hidden -g -fno-omit-frame-pointer -O2 main.cc -o main_cli | |
</code> | |
| |
<note important>Si ''AFL_USE_ASAN'' ou ''AFL_USE_MSAN'' est utilisé, automatiquement, afl ne surveille de 33% (aléatoirement) des branches que ''AFL_INST_RATIO'' ne peut pas surcharger.</note> | <WRAP center round alert 60%> |
| Toutes les informations après ce tag concerne l'ancienne version de afl. |
| </WRAP> |
| |
Pour que ''AFL_INST_RATIO'' ne soit pas divisé par 3, il faut appliquer le patch : | ====Sanitizers==== |
<file diff afl-as-AFL_INST_RATIO.patch> | Un programme compilé peut ne pas forcément planter en cas d'accès à une zone en dehors d'un tableau (par exemple) si cette zone reste dans la même page mémoire ou si la page suivante est aussi allouée par le même processus. |
--- afl-2.52b/afl-as.c.old 2018-02-11 22:05:48.636563804 +0100 | |
+++ afl-2.52b/afl-as.c 2018-02-11 22:07:04.035919083 +0100 | |
@@ -525,7 +525,8 @@ int main(int argc, char** argv) { | |
| |
if (getenv("AFL_USE_ASAN") || getenv("AFL_USE_MSAN")) { | |
sanitizer = 1; | |
- inst_ratio /= 3; | |
+ if (!getenv("AFL_INST_RATIO")) | |
+ inst_ratio /= 3; | |
} | |
| |
if (!just_version) add_instrumentation(); | |
</file> | |
| |
''AFL_USE_ASAN'' et ''AFL_USE_MSAN'', : nécessite ''-m none''. | <WRAP center round important 60%> |
| Les sanitizers en 64 bits demandent une taille de mémoire virtuelle de 20To. Il ne sera pas possible de sécuriser AFL en cas de bug d'allocation mémoire. |
| </WRAP> |
| |
Dans ces cas, 20 To est nécessaire. Mais cette taille n'est pas l'espace mémoire utile en RAM qui sera nécessaire mais seulement la mémoire virtuelle : | |
| |
PID UTIL. PR NI VIRT RES SHR S %CPU %MEM TEMPS+ COM. | * ''AFL_USE_ASAN'' : ''-U_FORTIFY_SOURCE -fsanitize=address''. Incompatible avec ''AFL_USE_MSAN'' et ''AFL_HARDEN''. |
14810 legarrec 20 0 20,000t 5916 3392 R 19,5 0,0 0:01.89 main | * ''AFL_USE_MSAN'' : ''-U_FORTIFY_SOURCE -fsanitize=memory''. Incompatible avec ''AFL_USE_ASAN'' et ''AFL_HARDEN''. |
| * ''AFL_HARDEN'' : ''-fstack-protector-all -D_FORTIFY_SOURCE=2'' |
| * ''AFL_USE_UBSAN'' : ''-fsanitize=undefined -fsanitize-undefined-trap-on-error -fno-sanitize-recover=all -fno-omit-frame-pointer'' |
| * ''AFL_USE_TSAN'' : ''-fsanitize=thread -fno-omit-frame-pointer'' |
| * ''AFL_USE_LSAN'' : ''-fsanitize=leak'' |
| * ''AFL_USE_CFISAN'' : ''-fcf-protection=full'' pour gcc, ''-fsanitize=cfi -fvisibility=hidden'' pour clang |
| |
<note important>Une chute de performance est à prévoir.</note> | Comme on est dans un environnement multithread, on compile une version de programme pour chaque sanitizer qui serviront lors du fuzzing (voir ci-après). |
| |
| <code bash> |
| CC=afl-clang-lto CXX=afl-clang-lto++ RANLIB=llvm-ranlib AR=llvm-ar AS=llvm-as AFL_USE_ASAN=1 AFL_INST_RATIO=100 CFLAGS="-g -fno-omit-frame-pointer" CXXFLAGS="-g -fno-omit-frame-pointer" cmake .. |
| CC=afl-clang-lto CXX=afl-clang-lto++ RANLIB=llvm-ranlib AR=llvm-ar AS=llvm-as AFL_USE_MSAN=1 AFL_INST_RATIO=100 CFLAGS="-g -fno-omit-frame-pointer" CXXFLAGS="-g -fno-omit-frame-pointer" cmake .. |
| CC=afl-clang-lto CXX=afl-clang-lto++ RANLIB=llvm-ranlib AR=llvm-ar AS=llvm-as AFL_HARDEN=1 CFLAGS="-g -fno-omit-frame-pointer" CXXFLAGS="-g -fno-omit-frame-pointer" cmake .. |
| CC=afl-clang-lto CXX=afl-clang-lto++ RANLIB=llvm-ranlib AR=llvm-ar AS=llvm-as AFL_USE_UBSAN=1 CFLAGS="-g -fno-omit-frame-pointer" CXXFLAGS="-g -fno-omit-frame-pointer" cmake .. |
| CC=afl-clang-lto CXX=afl-clang-lto++ RANLIB=llvm-ranlib AR=llvm-ar AS=llvm-as AFL_USE_TSAN=1 CFLAGS="-g -fno-omit-frame-pointer" CXXFLAGS="-g -fno-omit-frame-pointer" cmake .. |
| CC=afl-clang-lto CXX=afl-clang-lto++ RANLIB=llvm-ranlib AR=llvm-ar AS=llvm-as AFL_USE_LSAN=1 CFLAGS="-g -fno-omit-frame-pointer" CXXFLAGS="-g -fno-omit-frame-pointer" cmake .. |
| CC=afl-clang-lto CXX=afl-clang-lto++ RANLIB=llvm-ranlib AR=llvm-ar AS=llvm-as AFL_USE_CFISAN=1 CFLAGS="-g -fno-omit-frame-pointer" CXXFLAGS="-g -fno-omit-frame-pointer" cmake .. |
| </code> |
| |
Les valeurs ci-dessous sont basées sur l'utilisation du logiciel ''pdftohtml'' de ''poppler''. | Si ''AFL_USE_ASAN'' ou ''AFL_USE_MSAN'' est utilisé, automatiquement, afl ne surveille de 33% (aléatoirement) des branches. Il faut mettre ''AFL_INST_RATIO'' à 100 pour surveiller toutes les branches. |
^ Sanitizer ^ Performance ^ Chute ^ | |
| - | 100% |Vitesse maximale| | |
|address | 40% |Division par 2,5| | |
|undefined | 20% |Division par 5 | | |
|address,undefined| 8% |Division par 12 | | |
| |
Je conseille donc de lancer une version ''AFL_USE_ASAN'', ''AFL_USE_MSAN'', ''AFL_HARDEN'', ''-fsanitizer=undefined'' et ''-fsanitizer=undefined'' (soit 5 au total) et toutes les autres instances en parallèle sans ces optimisations. | Une chute de performance est à prévoir. Je conseille donc de lancer une exécution de afl-fuzz en mode esclave de chaque sanitizer et toutes les autres instances en parallèle sans ces vérifications. |
| |
====Dictionnaire==== | ====Dictionnaire==== |
Et on l'ajoute à afl-fuzz avec l'argument ''-x''. | Et on l'ajoute à afl-fuzz avec l'argument ''-x''. |
| |
<note important>Le dictionnaire n'est géré que par le maitre. | <WRAP center round tip 60%> |
| Le dictionnaire n'est géré que par le maitre. |
| |
Si on analyse des fichiers texte, ajouter la variable d'environnement ''AFL_NO_ARITH=1'' à afl-fuzz pour le maître évite les manipulations de nombres binaires ''arith'' et ''interest''.</note> | Si on analyse des fichiers texte, ajouter la variable d'environnement ''AFL_NO_ARITH=1'' à afl-fuzz pour le maître évite les manipulations de nombres binaires ''arith'' et ''interest''. |
| </WRAP> |
| |
<note important>Si on dépasse 200 mots-clés (''MAX_DET_EXTRAS'' du fichier ''config.h''), afl-fuzz ne travaille plus de façon déterministe. Les 200 premiers plus fréquents sont pris puis les suivants ont une probabilité de 200/n d'être analyser.</note> | <WRAP center round important 60%> |
| Si on dépasse 200 mots-clés (''MAX_DET_EXTRAS'' du fichier ''config.h''), afl-fuzz ne travaille plus de façon déterministe. Les 200 premiers plus fréquents sont pris puis les suivants ont une probabilité de 200/n d'être analyser. |
| </WRAP> |
| |
====memcmp, strcmp et ses dérivées==== | ====memcmp, strcmp et ses dérivées==== |
===Hack du préprocesseur=== | ===Hack du préprocesseur=== |
La solution, modifier le préprocesseur pour surcharger ces fonctions : | La solution, modifier le préprocesseur pour surcharger ces fonctions : |
[[http://stackoverflow.com/questions/3545875/custom-gcc-preprocessor|Source]], {{ prog:fuzzer:afl:custom_gcc_preprocessor_-_stack_overflow.htm.maff |Archive}} | [[https://stackoverflow.com/questions/3545875/custom-gcc-preprocessor|Custom gcc preprocessor]] {{ :prog:fuzzer:afl:custom_gcc_preprocessor_-_stack_overflow_2020-04-27_10_50_12_am_.html |Archive du 23/08/2010 le 27/04/2020}} |
| |
Ci-dessous pour la version 7.3.0 de gcc. | Ci-dessous pour la version 7.3.0 de gcc. |
| |
<note important>Le script ci-dessous peut poser des problèmes si ''configure'' ou autre utilise ''gcc -E''. Il faudrait corriger ça quand le problème sera identifié.</note> | <WRAP center round important 60%> |
| Le script ci-dessous peut poser des problèmes si ''configure'' ou autre utilise ''gcc -E''. Il faudrait corriger ça quand le problème sera identifié. |
| </WRAP> |
| |
<file bash cc1> | <file bash cc1> |
Le dictionnaire est beaucoup plus gros (tous les strings sont répertoriés et pas seulement ceux utilisés dans les ''strcmp*'') mais ça peut être une méthode alternative. | Le dictionnaire est beaucoup plus gros (tous les strings sont répertoriés et pas seulement ceux utilisés dans les ''strcmp*'') mais ça peut être une méthode alternative. |
| |
<note tip>Je conseille donc d'utiliser ''libtokencap'' quand on possède le code source et une base de données d'exemples suffisamment remplie et d'utiliser les autres commandes si l'une des deux conditions n'est pas respectée.</note> | <WRAP center round tip 60%> |
| Je conseille donc d'utiliser ''libtokencap'' quand on possède le code source et une base de données d'exemples suffisamment remplie et d'utiliser les autres commandes si l'une des deux conditions n'est pas respectée. |
| </WRAP> |
====Sans code source==== | ====Sans code source==== |
''afl-fuzz'' utilise [[http://www.qemu.org|qemu]]. | ''afl-fuzz'' utilise [[http://www.qemu.org|qemu]]. |
Sur le plan théorique, ça marche, je n'ai jamais testé. | Sur le plan théorique, ça marche, je n'ai jamais testé. |
| |
<note warning>TODO</note> | <WRAP center round important 60%> |
| TODO |
| </WRAP> |
| |
====Application Windows : Wine==== | ====Application Windows : Wine==== |
Cela ne marche pas encore c'est un bon début. Wine version 2.6. | Cela ne marche pas encore c'est un bon début. Wine version 2.6. |
| |
<note warning>TODO : à mettre à jour.</note> | <WRAP center round important 60%> |
| TODO : à mettre à jour. |
| </WRAP> |
| |
===Préparation=== | ===Préparation=== |
===Conclusion=== | ===Conclusion=== |
Mais l'exécution de la commande de fuzzing ne trouve qu'un seul chemin car l'exécutable n'est pas instrumenté. | Mais l'exécution de la commande de fuzzing ne trouve qu'un seul chemin car l'exécutable n'est pas instrumenté. |
afl-fuzz -t 500 -i testcases -o findings -- /home/legarrec/info/programmation/tmp/wine-afl/build/loader/wine main.exe @@ | afl-fuzz -t 500 -i testcases -o findings -- .../wine-afl/build/loader/wine main.exe @@ |
| |
et malgré le plantage avec succès de wine, il n'y a pas d'information de debug. | et malgré le plantage avec succès de wine, il n'y a pas d'information de debug. |
| |
===Résultat=== | ===Résultat=== |
{{:prog:fuzzer:afl:str_cmp_fuzzing.png?478|}} {{:prog:fuzzer:afl:str_cmp_plot.png?478|}} | {{:prog:fuzzer:afl:str_cmp_fuzzing.png|}} {{:prog:fuzzer:afl:str_cmp_plot.png|}} |
| |
<note important>Trouver un texte de plus de 32 caractères est compliqué : | <WRAP center round important 60%> |
| Trouver un texte de plus de 32 caractères est compliqué : |
* Ça a demandé plus de 3 millions de test !! Une autre exécution a trouvé le crash en 1,3 million de test, ce qui reste beaucoup. | * Ça a demandé plus de 3 millions de test !! Une autre exécution a trouvé le crash en 1,3 million de test, ce qui reste beaucoup. |
* Il faut patcher le programme. Par défaut, ''afl'' bloque la taille des chaînes de caractères à 32. Il faut modifier le ''#define MAX_AUTO_EXTRA 32'' à une valeur plus grande. Par exemple ''#define MAX_AUTO_EXTRA 40''. | * Il faut patcher le programme. Par défaut, ''afl'' bloque la taille des chaînes de caractères à 32. Il faut modifier le ''#define MAX_AUTO_EXTRA 32'' à une valeur plus grande. Par exemple ''#define MAX_AUTO_EXTRA 40''. |
</note> | </WRAP> |
| |
Cependant, il est possible d'accélérer le processus en utilisant un dictionnaire qui contient 26 entrées : {{ prog:fuzzer:afl:dict_alphabet.txt |les lettres de l’alphabet}}. Résultat : 850k de tests. | Cependant, il est possible d'accélérer le processus en utilisant un dictionnaire qui contient 26 entrées : {{ prog:fuzzer:afl:dict_alphabet.txt |les lettres de l’alphabet}}. Résultat : 850k de tests. |
Dans l'idéal, il faudrait attendre que le ''pending paths'' atteigne 0 mais là, il faudrait peut-être attendre plusieurs années. | Dans l'idéal, il faudrait attendre que le ''pending paths'' atteigne 0 mais là, il faudrait peut-être attendre plusieurs années. |
| |
<note warning>TODO | <WRAP center round important 60%> |
| TODO |
| |
calibration | calibration |
splice | splice |
sync | sync |
| </WRAP> |
</note> | |
| |
===Environnement multithread=== | ===Environnement multithread=== |
Si l'option ''-e'' n'est pas utilisé, deux fichiers génèrent une couverture identique en fonction des lignes couvertes et du nombre de passes de chaque ligne. Dans ce cas, le nombre de cas unique va être beaucoup plus important. | Si l'option ''-e'' n'est pas utilisé, deux fichiers génèrent une couverture identique en fonction des lignes couvertes et du nombre de passes de chaque ligne. Dans ce cas, le nombre de cas unique va être beaucoup plus important. |
| |
<note important> | |
''afl-cmin'' utilise des commandes shell pour trier des fichiers. | ''afl-cmin'' utilise des commandes shell pour trier des fichiers. |
| |
ls | cat -n | while read n f; do mv "$f" "$n"; done | ls | cat -n | while read n f; do mv "$f" "$n"; done |
</code> | </code> |
[[https://stackoverflow.com/questions/3211595/renaming-files-in-a-folder-to-sequential-numbers/37826687|Renaming files in a folder to sequential numbers]] {{ prog:fuzzer:afl:bash_-_renaming_files_in_a_folder_to_sequential_numbers_-_stack_overflow.mhtml |Archive}} | [[https://stackoverflow.com/questions/3211595/renaming-files-in-a-folder-to-sequential-numbers/37826687|Renaming files in a folder to sequential numbers]] {{ :prog:fuzzer:afl:bash_-_renaming_files_in_a_folder_to_sequential_numbers_-_stack_overflow_2020-04-26_7_09_25_pm_.html |Archive du 09/07/2010 le 26/04/2020}} |
| |
Ou sinon, on peut décommenter ''#define SIMPLE_FILES'' dans le fichier config.h de afl avant l'analyse. | Ou sinon, on peut décommenter ''#define SIMPLE_FILES'' dans le fichier config.h de afl avant l'analyse. |
</note> | |
| |
<code bash> | <code bash> |
</code> | </code> |
| |
<note tip>Par défaut, ''afl-cmin'' tri les fichiers pour favoriser les cas les plus petits. Si on souhaite favoriser les fichiers ayant la plus grande couverture de code (en espérant avoir une liste plus petite), il faut appliquer le patch suivant au ''STEP 3'' de ''afl-cmin''. | <WRAP center round tip 60%> |
| Par défaut, ''afl-cmin'' tri les fichiers pour favoriser les cas les plus petits. Si on souhaite favoriser les fichiers ayant la plus grande couverture de code (en espérant avoir une liste plus petite), il faut appliquer le patch suivant au ''STEP 3'' de ''afl-cmin''. |
<code> | <code> |
-done < <(ls -rS "$IN_DIR") | -done < <(ls -rS "$IN_DIR") |
+done < <(ls -S "$TRACE_DIR") | +done < <(ls -S "$TRACE_DIR") |
</code> | </code> |
</note> | </WRAP> |
| |
<code> | <code> |
find testcase.cov/ -exec ./pdftohtml {} /tmp/iie \; | find testcase.cov/ -exec ./pdftohtml {} /tmp/iie \; |
</code> | </code> |
<note important>Ne pas utiliser ''parallel'' sinon l'écriture des informations de couverture de code sera corrompu. | |
| |
[[https://stackoverflow.com/questions/14643589/code-coverage-using-gcov-on-parallel-run|Code coverage using gcov on parallel run]] {{ prog:fuzzer:afl:c_-_code_coverage_using_gcov_on_parallel_run_-_stack_overflow.mhtml |Archive}} | <WRAP center round important 60%> |
</note> | Ne pas utiliser ''parallel'' sinon l'écriture des informations de couverture de code sera corrompu. |
| |
| [[https://stackoverflow.com/questions/14643589/code-coverage-using-gcov-on-parallel-run|Code coverage using gcov on parallel run]] {{ :prog:fuzzer:afl:c_-_code_coverage_using_gcov_on_parallel_run_-_stack_overflow_2020-04-26_7_09_43_pm_.html |Archive du 01/02/2013 le 26/04/2020}} |
| </WRAP> |
Le rapport final s'obtient en lançant depuis le dossier de compilation : | Le rapport final s'obtient en lançant depuis le dossier de compilation : |
<code bash> | <code bash> |
firefox out_html/index.html | firefox out_html/index.html |
</code> | </code> |
<note>Il est aussi possible d'afficher les différentes branches de chaque ligne en ajoutant ''%%--%%rc lcov_branch_coverage=1'' à ''lcov'' et ''%%--%%branch-coverage'' à ''genhtml''</note> | |
| <WRAP center round tip 60%> |
| Il est aussi possible d'afficher les différentes branches de chaque ligne en ajoutant ''%%--%%rc lcov_branch_coverage=1'' à ''lcov'' et ''%%--%%branch-coverage'' à ''genhtml'' |
| </WRAP> |
====Fuites mémoire==== | ====Fuites mémoire==== |
Les trois dossiers contenant un nombre important d'exemples, il est intéressant de lancer l'application sous surveillance de Valgrind. Si l'application de base possède déjà des fuites mémoires ou est difficilement analysable (GTK, Qt, …), je recommande d'enregistrer tous les logs ''valgrind'' et de faire un ''diff -pu'' avec le programme de base. | Les trois dossiers contenant un nombre important d'exemples, il est intéressant de lancer l'application sous surveillance de Valgrind. Si l'application de base possède déjà des fuites mémoires ou est difficilement analysable (GTK, Qt, …), je recommande d'enregistrer tous les logs ''valgrind'' et de faire un ''diff -pu'' avec le programme de base. |
cd findings | cd findings |
# version hardcore | # version hardcore |
find . -name "id:*" | LD_LIBRARY_PATH="/home/legarrec/info/programmation/tmp/afl-popple/poppler-0.53.0/poppler/.libs:$LD_LIBRARY_PATH" parallel "valgrind --trace-children=yes --track-fds=yes --num-callers=500 --error-limit=no --show-below-main=yes --max-stackframe=2000000 --smc-check=all --read-var-info=yes -v --leak-check=full --show-possibly-lost=yes --leak-resolution=high --show-reachable=yes --undef-value-errors=yes --track-origins=yes ../poppler-0.53.0/utils/.libs/pdftohtml {} /tmp/ &> {}.log" | find . -name "id:*" | LD_LIBRARY_PATH=".../afl-popple/poppler-0.53.0/poppler/.libs:$LD_LIBRARY_PATH" parallel "valgrind --trace-children=yes --track-fds=yes --num-callers=500 --error-limit=no --show-below-main=yes --max-stackframe=2000000 --smc-check=all --read-var-info=yes -v --leak-check=full --show-possibly-lost=yes --leak-resolution=high --show-reachable=yes --undef-value-errors=yes --track-origins=yes ../poppler-0.53.0/utils/.libs/pdftohtml {} /tmp/ &> {}.log" |
# version plus rapide sans read-var-info, track-origins surtout : | # version plus rapide sans read-var-info, track-origins surtout : |
find . -name "id:*" | LD_LIBRARY_PATH="/home/legarrec/info/programmation/tmp/afl-popple/poppler-0.53.0/poppler/.libs:$LD_LIBRARY_PATH" parallel "valgrind -v --leak-check=full --show-leak-kinds=all ../poppler-0.53.0/utils/.libs/pdftohtml {} /tmp/ &> {}.log" | find . -name "id:*" | LD_LIBRARY_PATH=".../afl-popple/poppler-0.53.0/poppler/.libs:$LD_LIBRARY_PATH" parallel "valgrind -v --leak-check=full --show-leak-kinds=all ../poppler-0.53.0/utils/.libs/pdftohtml {} /tmp/ &> {}.log" |
</code> | </code> |
| |
mkdir build | mkdir build |
cd build | cd build |
CC=afl-gcc CXX=afl-g++ cmake DCMAKE_C_FLAGS="-no-integrated-cpp -g -fno-omit-frame-pointer" DCMAKE_CXX_FLAGS="-no-integrated-cpp -g -fno-omit-frame-pointer" .. | CC=afl-gcc CXX=afl-g++ CFLAGS="-no-integrated-cpp -g -fno-omit-frame-pointer" CXXFLAGS="-no-integrated-cpp -g -fno-omit-frame-pointer" cmake .. |
</code> | </code> |
| |
* ''-fno-omit-frame-pointer'' : pour que les informations de débogage soient optimales. | * ''-fno-omit-frame-pointer'' : pour que les informations de débogage soient optimales. |
| |
<note important> | <WRAP center round important 60%> |
''-fsanitize=address,undefined'' : n'est pas utilisé car il ralenti de façon non négligeable les délais d'exécution. | ''-fsanitize=address,undefined'' : n'est pas utilisé car il ralenti de façon non négligeable les délais d'exécution. |
| |
Les options seront utilisées sur les cas retenus par ''afl-fuzz''. Il n'est pas impossible que certains cas qui génèrent des violations de mémoire possèdent la même empreinte que les cas n'en générant pas et soient donc ignorés. | Les options seront utilisées sur les cas retenus par ''afl-fuzz''. Il n'est pas impossible que certains cas qui génèrent des violations de mémoire possèdent la même empreinte que les cas n'en générant pas et soient donc ignorés. |
</note> | </WRAP> |
| |
<code bash> | <code bash> |
Pour des raisons de simplicité, l'outil pdftohtml sera utilisé. Il décode les textes, images, formes, etc… | Pour des raisons de simplicité, l'outil pdftohtml sera utilisé. Il décode les textes, images, formes, etc… |
| |
<note tip>Problème si le logiciel a été compilé avec make : | <WRAP center round tip 60%> |
| Problème si le logiciel a été compilé avec make : |
| |
''utils/pdftohtml'' est un wrapper shell. Pour permettre l'exécution correct du programme (qui se trouve dans un dossier caché ''utils/.libs'') par ''afl-fuzz'', il faut modifier la variable d'environnement ''LD_LIBRARY_PATH''. Pour avoir la bonne modification, lire la fin du wrapper et obtenir la ligne | ''utils/pdftohtml'' est un wrapper shell. Pour permettre l'exécution correct du programme (qui se trouve dans un dossier caché ''utils/.libs'') par ''afl-fuzz'', il faut modifier la variable d'environnement ''LD_LIBRARY_PATH''. Pour avoir la bonne modification, lire la fin du wrapper et obtenir la ligne |
<code bash> | <code bash> |
# Add our own library path to LD_LIBRARY_PATH | # Add our own library path to LD_LIBRARY_PATH |
LD_LIBRARY_PATH="/home/legarrec/info/programmation/tmp/afl-2lgc/poppler-0.53.0/poppler/.libs:$LD_LIBRARY_PATH" | LD_LIBRARY_PATH=".../afl-2lgc/poppler-0.53.0/poppler/.libs:$LD_LIBRARY_PATH" |
</code> | </code> |
</note> | |
| </WRAP> |
| |
Enfin, exécution du maitre et des slaves en multithread : | Enfin, exécution du maitre et des slaves en multithread : |
Exemple de rendu en cas d'application en mode multithread : | Exemple de rendu en cas d'application en mode multithread : |
| |
{{prog:fuzzer:afl:afl-multithread.png?400|afl-multithread}} | {{prog:fuzzer:afl:afl-multithread.png|afl-multithread}} |
| |
On constate que le maître est beaucoup plus lent que les autres puisqu'à mon avis, il s'occupe d'approfondir les cas étudiés par ses esclaves. | On constate que le maître est beaucoup plus lent que les autres puisqu'à mon avis, il s'occupe d'approfondir les cas étudiés par ses esclaves. |
<code> | <code> |
Groupe 0 | Groupe 0 |
/home/legarrec/info/programmation/retdec/build/src/fileinfo/crash/fuzzer02/crashes/id_000063_06.btfull | .../retdec/build/src/fileinfo/crash/fuzzer02/crashes/id_000063_06.btfull |
Groupe 1 | Groupe 1 |
/home/legarrec/info/programmation/retdec/build/src/fileinfo/crash/fuzzer02/crashes/id_000419_06.btfull | .../retdec/build/src/fileinfo/crash/fuzzer02/crashes/id_000419_06.btfull |
Groupe 2 | Groupe 2 |
/home/legarrec/info/programmation/retdec/build/src/fileinfo/crash/fuzzer02/crashes/id_000384_06.btfull | .../retdec/build/src/fileinfo/crash/fuzzer02/crashes/id_000384_06.btfull |
Groupe 3 | Groupe 3 |
/home/legarrec/info/programmation/retdec/build/src/fileinfo/crash/fuzzer02/crashes/id_000241_06.btfull | .../retdec/build/src/fileinfo/crash/fuzzer02/crashes/id_000241_06.btfull |
Groupe 4 | Groupe 4 |
/home/legarrec/info/programmation/retdec/build/src/fileinfo/crash/fuzzer02/crashes/id_000356_06.btfull | .../retdec/build/src/fileinfo/crash/fuzzer02/crashes/id_000356_06.btfull |
Groupe 5 | Groupe 5 |
/home/legarrec/info/programmation/retdec/build/src/fileinfo/crash/fuzzer02/crashes/id_000016_06.btfull | .../retdec/build/src/fileinfo/crash/fuzzer02/crashes/id_000016_06.btfull |
</code> | </code> |
| |