v1.4 Copyright (C) 2020 Andrea Fioraldi [email protected]
Publié sous la licence Apache v2.0
Ce fuzzer expérimental est destiné à être utilisé pour le fuzzing en mémoire de l'API.
Le design est très inspiré et basé sur AFL/AFL++.
ATM, le mutateur est assez simple, juste les étapes de ravages et d'épissage de l'AFL.
J'ai testé uniquement les exemples sous tests/, il s'agit d'un projet WIP mais il est connu pour fonctionner au moins sur GNU/Linux x86_64 et Android x86_64.
Vous avez besoin de Frida >= 12.8.1 pour exécuter ceci ( pip3 install -U frida
) et de frida-tools pour compiler le harnais.
La bibliothèque fuzz
doit être importée dans un harnais personnalisé puis compilée avec frida-compile
pour générer l'agent que frida-fuzzer
injectera dans l'application cible.
La majorité de la logique du fuzzer se trouve dans l'agent.
Un harnais a le format suivant :
var fuzz = require("./fuzz");var TARGET_MODULE = "test_linux64";var TARGET_FUNCTION = DebugSymbol.fromName("target_func").address;;var RET_TYPE = "void";var ARGS_TYPES = ['pointer', ' int'];var func_handle = new NativeFunction(TARGET_FUNCTION, RET_TYPE, ARGS_TYPES, { pièges : 'tous' });fuzz.target_module = TARGET_MODULE;var payload_mem = Memory.alloc(fuzz.config.MAX_FILE);fuzz.fuzzer_test_one_input = function (/* Uint8Array */ payload) { Memory.writeByteArray (payload_mem, payload, payload.length); func_handle(payload_mem, payload.length);}
fuzz.fuzzer_test_one_input
est obligatoire. Si vous ne spécifiez pas fuzz.target_module
, tout le code exécuté sera instrumenté.
Vous pouvez également définir fuzz.manual_loop_start = true
pour indiquer au fuzzer que vous appellerez fuzz.fuzzing_loop()
dans un rappel et qu'il ne doit donc pas l'appeler à votre place (par exemple pour commencer à fuzzer lorsqu'un bouton est cliqué dans l'application Android).
Le rappel fuzz.init_callback
peut être configuré pour exécuter du code lorsque le fuzzer est prêt à démarrer. Voir tests/test_java.js
pour un exemple.
fuzz.dictionary
est un dictionnaire fuzzer classique, un tableau dans lequel vous pouvez ajouter des éléments (les types acceptés sont Array, ArrayBuffer, Uint8Array, String) qui sont utilisés comme valeurs supplémentaires dans le mutateur. Voir tests/test_libxml2.js
pour un exemple.
frida-fuzzer
accepte les arguments suivants :
-i DOSSIER | Dossier avec les graines initiales |
-o DOSSIER | Dossier de sortie avec graines intermédiaires et plantages |
-U | Connectez-vous à USB |
-frayer | Générer et attacher au lieu de simplement attacher |
-script SCRIPT | Nom du fichier de script (la valeur par défaut est fuzzer-agent.js) |
Si vous ne spécifiez pas le dossier de sortie, un dossier temporaire est créé sous /tmp. Si vous ne spécifiez pas le dossier avec la graine initiale, une graine non informée 0000
est utilisée comme graine de départ.
Si vous fuzzez une application locale, vous souhaiterez peut-être exécuter system-config
avant frida-fuzzer
pour régler les paramètres de votre système et accélérer les choses.
En exécutant ./frida-fuzzer -spawn ./tests/test_linux64
vous verrez quelque chose comme l'écran d'état suivant sur votre terminal :
Vous pouvez également facilement ajouter une étape personnalisée dans fuzz/fuzzer.js
et l'ajouter à la liste des étapes dans fuzz/index.js
.
Pour personnaliser le fuzzer, éditez fuzz/config.js
. Les variables que vous souhaiterez peut-être modifier sont MAP_SIZE (si le code que vous fuzzez est petit, vous pouvez le réduire et gagner un peu de vitesse), MAX_FILE (la taille maximale de l'entrée générée) et QUEUE_CACHE_MAX_SIZE (augmenter la taille du cache de file d'attente pour plus de vitesse, surtout sur Android).
Fuzzons la bibliothèque partagée native dans l'exemple d'application Android dans tests
.
Assurez-vous d'avoir root sur votre appareil virtuel :
host$ adb root
Téléchargez le serveur frida Android x86_64 à partir de la page de version du dépôt et copiez-le sur l'appareil sous /data/local/tmp (utilisez adb push).
Démarrez un shell et exécutez le serveur frida :
device# cd /data/local/tmp device# ./frida-server
Installez maintenant l'application de test tests/app-debug.apk
en utilisant le glisser-déposer dans la fenêtre de l'émulateur.
Ensuite, ouvrez l'application.
Compilez le script de l'agent avec frida-compile :
host$ frida-compile -x tests/test_ndk_x64.js -o fuzzer-agent.js
Ouvrez l'application dans l'émulateur.
Fuzzez la fonction test_func
de la bibliothèque libnative-lib.so
livrée avec l'application de test avec la commande :
host$ ./frida-fuzzer -U -o output_folder/ com.example.ndktest1
Les cas de test et les crashs intéressants sont tous deux enregistrés dans output_folder.
Apprécier.
Salut la communauté OSS, il y a beaucoup de TODO si quelqu'un veut contribuer.
Fuzzing du code Java (attendre des méthodes exposées supplémentaires dans frida-java-bridge, devrait être facile, presque terminé)
étape d'épissage (fusionner deux cas de test dans la file d'attente et y faire des ravages)
prendre en charge les dictionnaires (et ainsi modifier également les ravages)
sélection des graines
instrumentation en ligne pour arm64
notation des performances (explorer le calendrier de l'AFL)
mutateur structurel (mutation d'octets basée sur une grammaire écrite en JSON)
CompareCoverage (profilage de sous-instructions pour contourner les obstacles fuzzing)
réécrivez frida-fuzzer en C avec frida-core pour pouvoir exécuter tout ce qui se passe sur l'appareil mobile
Si vous avez des doutes sur l'une de ces fonctionnalités, n'hésitez pas à m'envoyer un message privé sur Twitter.
Pour les propositions de fonctionnalités, il y a la section Problèmes.