
Fuzzer pour pilotes du noyau Linux
Ce dépôt contient toutes les sources (scripts d'installation inclus) dont vous avez besoin pour faire fonctionner difuze.
Ubuntu >= 14.04.5 LTS
Consultez le readme
Comme expliqué dans notre article, il y a deux composants principaux de difuze : Récupération d'interface et Moteur de fuzzing
Le mécanisme de récupération d'interface est basé sur les passes d'analyse LLVM. Chaque étape de la récupération d'interface est écrite sous forme de passes individuelles. Suivez les instructions ci-dessous pour faire fonctionner la Récupération d'interface.
Cette étape s'occupe de l'installation de LLVM et de c2xml :
Tout d'abord, assurez-vous d'avoir libxml (nécessaire pour c2xml) :
sudo apt-get install libxml2-dev
sudo pip install lxml
Ensuite, nous avons créé un script unique qui télécharge et construit tous les outils nécessaires.
cd helper_scripts
python setup_difuze.py --help
usage: setup_difuze.py [-h] [-b TARGET_BRANCH] [-o OUTPUT_FOLDER]
optional arguments:
-h, --help show this help message and exit
-b TARGET_BRANCH Branch (i.e. version) of the LLVM to setup. Default:
release_38 e.g., release_38
-o OUTPUT_FOLDER Folder where everything needs to be setup.
Exemple :
python setup_difuze.py -o difuze_deps
Pour terminer la configuration, vous devez également modifier votre variable d'environnement locale PATH. Le script de configuration vous indiquera exactement les modifications à effectuer.
Cela dépend de la réussite de la Configuration. Nous avons un seul script qui compile tout, de rien.
cd InterfaceHandlers
./build.sh
Cela dépend de la réussite de la Compilation. Pour exécuter les composants de récupération d'interface sur les pilotes du noyau, nous devons d'abord convertir les pilotes en bitcode LLVM.
Tout d'abord, nous avons besoin d'un noyau compilable. Cela signifie que vous devez pouvoir compiler le noyau en utilisant la configuration de compilation habituelle, c'est-à-dire make.
Nous capturons d'abord la sortie de la commande make, à partir de laquelle nous extrayons la commande de compilation exacte.
makebear make <all the options to make>
Exemple : bear make -j8Cela générera un fichier compile_commands.json dans le répertoire courant.
Il suffit de passer V=1 et de rediriger la sortie vers le fichier.
Exemple :
make V=1 O=out ARCH=arm64 > makeout.txt 2>&1
NOTE : N'UTILISEZ PAS DE PROCESSUS MULTIPLES, c'est-à-dire -j. L'exécution en mode multi-processus perturbera le fichier de sortie car plusieurs processus tentent d'écrire dans le fichier de sortie.
Voilà. Ensuite, dans l'étape suivante, notre script prend le makeout.txt généré et exécute la récupération d'interface sur tous les pilotes reconnus.
Toutes les différentes étapes de la récupération d'interface sont regroupées dans un seul script helper_scripts/run_all.py
Comment exécuter :
cd helper_scripts
python run_all.py --help
usage: run_all.py [-h] [-l LLVM_BC_OUT] [-a CHIPSET_NUM] [-m MAKEOUT]
[-c COMPJSON] [-g COMPILER_NAME] [-n ARCH_NUM] [-o OUT]
[-k KERNEL_SRC_DIR] [-isclang] [-clangp CLANG_PATH]
[-llvmlinkp LLVMLINK_PATH] [-skb] [-skl] [-skp] [-skP]
[-ske] [-skI] [-ski] [-skv] [-skd] [-f IOCTL_FINDER_OUT]
optional arguments:
-h, --help show this help message and exit
-l LLVM_BC_OUT Destination directory where all the generated bitcode
files should be stored.
-a CHIPSET_NUM Chipset number. Valid chipset numbers are:
1(mediatek)|2(qualcomm)|3(huawei)|4(samsung)
-m MAKEOUT Path to the makeout.txt file.
-c COMPJSON Path to the compile_commands_json generated by Bear.
-g COMPILER_NAME Name of the compiler used in the makeout.txt, This is
needed to filter out compilation commands. Ex: aarch64
-linux-android-gcc
-n ARCH_NUM Destination architecture, 32 bit (1) or 64 bit (2).
-o OUT Path to the out folder. This is the folder, which
could be used as output directory during compiling
some kernels.
-k KERNEL_SRC_DIR Base directory of the kernel sources.
-isclang flag to indicate that clang was used to built the
kernel
-clangp CLANG_PATH Absolute path to the clang binary (if not provided,
the one available in the path will be used)
-llvmlinkp LLVMLINK_PATH
Absolute path to the llvm-link binary (if not
provided, the one available in the path will be used)
-skb Skip LLVM Build (default: not skipped).
-skl Skip Dr Linker (default: not skipped).
-skp Skip Parsing Headers (default: not skipped).
-skP Skip Generating Preprocessed files (default: not
skipped).
-ske Skip Entry point identification (default: not
skipped).
-skI Skip Generate Includes (default: not skipped).
-ski Skip IoctlCmdParser run (default: not skipped).
-skv Skip V4L2 ioctl processing (default: not skipped).
-skd Skip Device name finder (default: not skipped).
-f IOCTL_FINDER_OUT Path to the output folder where the ioctl command
finder output should be stored.
Le script compile, lie et exécute la récupération d'interface sur tous les pilotes reconnus, il peut donc prendre un temps considérable (45 min à 90 min).
Le script ci-dessus effectue les tâches suivantes en mode multiprocesseur pour utiliser tous les cœurs du CPU :
Tous les fichiers bitcode générés seront placés dans le dossier fourni à l'argument -l.
Cette étape prend un temps considérable, en fonction du nombre de cœurs dont vous disposez.
Donc, si vous avez déjà effectué cette étape, vous pouvez la sauter en passant -skb.
Cela effectue la liaison, il parcourt tous les fichiers bitcode, identifie les fichiers bitcode associés qui doivent être liés et les lie (en utilisant llvm-link) en un fichier bitcode consolidé (qui sera stocké à côté du fichier bitcode correspondant).
Comme pour l'étape précédente, vous pouvez sauter cette étape en passant -skl.
Cette étape recherche les déclarations de points d'entrée dans les fichiers d'en-tête et stocke leur configuration dans le fichier : hdr_file_config.txt sous le répertoire de compilation LLVM.
Pour sauter : -skp