> For the complete documentation index, see [llms.txt](https://sansong.gitbook.io/cyber/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://sansong.gitbook.io/cyber/pwn/fuzzing.md).

# Fuzzing

**Le fuzzing, c'est quoi ?**

Le <mark style="color:purple;">fuzzing</mark> consiste à générer des entrées qui sont ensuite passées au programme dans le but de trouver des bugs. L'idée est de voir si des entrées non prévues peuvent altérer son exécution (en gros on essaie de faire crash le programme avec pleins d'entrées bizarres).&#x20;

N’importe quel programme peut être testé comme ça à condition qu’il accepte une entrée qu’elle se fasse par l’entrée standard, l’ouverture d’un fichier, une variable d’environnement, l’écoute sur un port, etc. Le fuzzing permet de tester des millions d’entrées et d'être considérablement plus efficace qu’une approche manuelle.

**Comment générer les entrées ?**

On part d'une entrée (ou plusieurs) et on applique des <mark style="color:purple;">mutations</mark>.

<figure><img src="https://upload.wikimedia.org/wikipedia/commons/f/fa/AFL_Fuzz_Logo.gif" alt="" width="188"><figcaption><p>Exemple de mutations sur une image</p></figcaption></figure>

Par exemple:

* bitflip, byteflip
* addition, soustraction de bits/octets
* ajout, duplication, suppression de bits/octets
* magic bytes (ajout de valeurs spéciales ex: 0xdeadbeef...)

Il faut commencer un pool d'entrées qu'on appelle le <mark style="color:purple;">corpus</mark>. C'est l'ensemble des entrées avec lequel le fuzzing commence. Pour un programme qui prend des images en entrée, le corpus contient différentes images.

**Comment fuzz efficacement un programme ?**

Il ne suffit pas de générer des entrées aléatoires pour avoir un fuzzing efficace. Il faut avoir des informations sur ce qu’il se passe à l’intérieur du programme une fois l’entrée passée à celui-ci, on parle <mark style="color:purple;">d’instrumentation</mark>. Les entrées susceptibles de corrompre l’exécution du programme doivent être sauvegardées pour permettre une analyse manuelle ultérieure.&#x20;

Comme un programmeur qui parsème son programme de <mark style="color:purple;">`printf`</mark> pour voir quels endroits du code sont atteints <mark style="color:purple;">l’instrumentation</mark> du programme permet de détecter des problèmes et de donner un retour sur les parties du code atteintes par une entrée.&#x20;

{% hint style="info" %}
Quand on test un programme en boîte blanche (avec accès au code source), le compilateur ajoute des instructions pour l'instrumenter et remonter les informations de parcours. En boîte noire, on utilise QEMU, Unicorn, Frida ou d'autres outils d'émulation pour l'instrumentation.
{% endhint %}

todo: schema chemin pris par une entrée

L’approche la plus fréquente est le <mark style="color:purple;">coverage-based fuzzing</mark> dont l’objectif est de maximiser la couverture de code testé. Plus la quantité de code testé est grande, plus les chances de trouver des vulnérabilités sont importantes. Un fuzzer de ce type applique des mutations sur ses entrées et se concentre sur les entrées atteignant des nouveaux chemins d’exécutions.

todo: schema coverage based fuzzing

D'abord un ensemble d’entrées formées au préalable constitue le <mark style="color:purple;">corpus</mark>. Une file d’entrées est initialisée avec le <mark style="color:purple;">corpus</mark> et le fuzzer sélectionne une entrée dans cette file selon une méthode qui lui est spécifique. L’entrée subit des <mark style="color:purple;">mutations</mark> et est donnée au programme. Si elle permet d’augmenter la couverture de code, i.e. d’atteindre des parties du code encore non atteintes, elle est ajoutée à la file. Si elle compromet l’exécution du programme, elle est sauvegardée pour une étude manuelle plus avancée.

**Snapshot**

Pour optimiser les performances, il faut pouvoir maximiser le nombre d’exécutions par secondes. Dans certains cas, il est intéressant de se focaliser sur une partie spécifique du programme comme une fonction par exemple. Il n’est alors pas intéressant d’exécuter la totalité du programme à chaque nouvelle entrée, il est préférable de n’exécuter que la partie du code à tester. Pour cela, il existe le <mark style="color:purple;">snapshot fuzzing</mark>. Un <mark style="color:purple;">snapshot</mark> est pris avant la partie de code à tester, soit une sauvegarde de la mémoire, des registres, etc.

todo: schema fuzzing

A chaque itération, le <mark style="color:purple;">snapshot</mark> est rechargé et l’entrée est directement injectée en mémoire. Ce type de fuzzing nécessite plus de travail pour le testeur car il implique une analyse du programme pour trouver l’adresse à laquelle prendre le snapshot et comment l’entrée doit être injectée dans la mémoire.

**Analyse manuelle**

Une fois que le fuzzer a trouver des entrées intéressantes il faut souvent approfondir l'analyse à la main pour trier les faux positifs et comprendre comment cette entrée fait crash le programme.

[Lighthouse](/cyber/pwn/fuzzing/lighthouse.md) est un plugin IDA/Binary Ninja pour charger des fichiers de couverture et suivre plus facilement le chemin prit, les fonctions et le pourcentage de code exécuté.

<figure><img src="https://github.com/gaasedelen/lighthouse/blob/master/screenshots/painting.png?raw=true" alt="" width="563"><figcaption></figcaption></figure>
