LibAFL - Framework de Fuzzing Modulaire
LibAFL est un framework de fuzzing, pas un testeur. Écrit en Rust par l’équipe AFL++, il fournit des blocs de construction composables — observateurs, retours, mutateurs, planificateurs, étapes, exécuteurs — que vous assemblez en un testeur adapté à votre cible. La motivation est que les testeurs monolithiques fonctionnent bien sur les cibles conventionnelles et mal sur les cibles inhabituelles (protocoles personnalisés, firmware émulé, noyaux, grammaires), où vous finissez par combattre l’outil. Avec LibAFL, vous construisez exactement le testeur dont la cible a besoin, et obtenez l’évolutivité multi-cœur gratuitement.
Construire un testeur est plus de travail que d’en exécuter un. Préférez LibAFL quand les outils prêts à l’emploi ne correspondent réellement pas.
Setup
| Étape | Commande |
|---|
| Nouveau projet | cargo new my_fuzzer && cd my_fuzzer |
| Ajouter LibAFL | cargo add libafl libafl_bolts |
| Instrumentation cible | cargo add libafl_targets (ou libafl_qemu, libafl_frida) |
| Construire | cargo build --release |
Concepts Clés
| Composant | Rôle |
|---|
| Input | Ce qui est testé (octets, arborescence de grammaire, appels système) |
| Observer | Enregistre les données pendant une exécution (carte de couverture, timing) |
| Feedback | Décide si une exécution était « intéressante » |
| Objective | Décide si une exécution est une solution (un plantage) |
| Corpus | Stockage pour les entrées intéressantes |
| Mutator | Transforme les entrées |
| Scheduler | Choisit l’entrée suivante à exécuter |
| Stage | Une phase appliquée par entrée (muter, trimmer, calibrer) |
| Executor | Exécute la cible avec une entrée |
// Structure conceptuelle — voir les exemples LibAFL pour le code complet
let mut feedback = MaxMapFeedback::new(&edges_observer);
let mut objective = CrashFeedback::new();
let mut state = StdState::new(
StdRand::with_seed(current_nanos()),
InMemoryCorpus::new(),
OnDiskCorpus::new("./crashes")?,
&mut feedback,
&mut objective,
)?;
let scheduler = QueueScheduler::new();
let mut fuzzer = StdFuzzer::new(scheduler, feedback, objective);
let mut executor = InProcessExecutor::new(
&mut harness, tuple_list!(edges_observer), &mut fuzzer, &mut state, &mut mgr,
)?;
let mutator = StdScheduledMutator::new(havoc_mutations());
let mut stages = tuple_list!(StdMutationalStage::new(mutator));
fuzzer.fuzz_loop(&mut stages, &mut executor, &mut state, &mut mgr)?;
| Exécuteur | Utilisation |
|---|
InProcessExecutor | Plus rapide ; harnais dans le même processus |
ForkserverExecutor | Style AFL forkserver pour les binaires externes |
CommandExecutor | Exécuter une commande externe par entrée |
libafl_qemu | Cibles émulées / fuzzing sans source binaire |
libafl_frida | Instrumentation dynamique (sans source binaire) |
libafl_nyx | Fuzzing de VM basé sur snapshot |
Retours
| Retour | Intéressant quand |
|---|
MaxMapFeedback | Nouvelles arêtes de couverture touchées |
TimeFeedback | Le temps d’exécution change |
CrashFeedback | La cible s’est plantée (objectif) |
TimeoutFeedback | La cible s’est suspendue (objectif) |
NewHashFeedback | Nouvelle trace de plantage unique |
| Combinateurs | feedback_or!, feedback_and! pour composer |
Mutateurs
| Mutateur | Fait |
|---|
havoc_mutations() | Mutations aléatoires standard de style AFL |
tokens_mutations() | Insertion de dictionnaire/jeton |
| Mutateurs de grammaire | Génération tenant compte de la structure |
| Personnalisé | Implémenter le trait Mutator pour votre type d’entrée |
Les types d’entrée personnalisés plus les mutateurs personnalisés sont la raison principale de choisir LibAFL — tester un protocole ou un AST intelligemment plutôt que de basculer des octets.
Évolutivité Multi-Core
| Mécanisme | Note |
|---|
LlmpRestartingEventManager | Passage de messages à faible surcharge entre les cœurs |
Launcher | Générer un testeur par cœur avec corpus partagé |
| Synchronisation du corpus | Les entrées intéressantes se propagent entre les instances |
| Redémarrage | Survit aux plantages du processus testeur |
LibAFL vs Testeurs Prêts à l’Emploi
| Aspect | LibAFL | AFL++ | honggfuzz |
|---|
| Modèle | Construire votre propre | Prêt à exécuter | Prêt à exécuter |
| Effort | Élevé | Bas | Bas |
| Flexibilité | Total | Configurable | Configurable |
| Meilleur pour | Cibles inhabituelles, recherche | Binaires standard | Démarrage rapide, retour matériel |
Commencez avec AFL++ ou honggfuzz ; passez à LibAFL quand la structure d’entrée de la cible ou le modèle d’exécution les défait.
Ressources