LibAFL - Framework modular de fuzzing
LibAFL es un framework de fuzzing, no un fuzzer. Escrito en Rust por el equipo de AFL++, proporciona bloques de construcción componibles — observers, feedbacks, mutators, schedulers, stages, executors — que ensamblas en un fuzzer adaptado a tu objetivo. La motivación es que los fuzzers monolíticos funcionan bien en objetivos convencionales y mal en objetivos inusuales (protocolos personalizados, firmware emulado, kernels, gramáticas), donde terminas peleando con la herramienta. Con LibAFL construyes exactamente el fuzzer que el objetivo necesita, y obtienes scaling multi-core gratis.
Construir un fuzzer es más trabajo que ejecutar uno. Alcanza LibAFL cuando las herramientas off-the-shelf genuinamente no se ajustan.
Setup
| Paso | Comando |
|---|
| Nuevo proyecto | cargo new my_fuzzer && cd my_fuzzer |
| Añadir LibAFL | cargo add libafl libafl_bolts |
| Instrumentación del objetivo | cargo add libafl_targets (o libafl_qemu, libafl_frida) |
| Compilar | cargo build --release |
Conceptos básicos
| Componente | Rol |
|---|
| Input | Lo que se hace fuzzing (bytes, árbol de gramática, syscalls) |
| Observer | Registra datos durante una ejecución (mapa de cobertura, timing) |
| Feedback | Decide si una ejecución fue “interesante” |
| Objective | Decide si una ejecución es una solución (un crash) |
| Corpus | Almacenamiento para entradas interesantes |
| Mutator | Transforma entradas |
| Scheduler | Elige la siguiente entrada a ejecutar |
| Stage | Una fase aplicada por entrada (mutar, trim, calibrate) |
| Executor | Ejecuta el objetivo con una entrada |
// Estructura conceptual — ver ejemplos de LibAFL para código completo
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)?;
Executors (cómo se ejecuta el objetivo)
| Executor | Usar |
|---|
InProcessExecutor | Más rápido; harness en el mismo proceso |
ForkserverExecutor | Estilo AFL forkserver para binarios externos |
CommandExecutor | Ejecutar un comando externo por entrada |
libafl_qemu | Objetivos emulados / fuzzing binario-only |
libafl_frida | Instrumentación dinámica (binario-only) |
libafl_nyx | Fuzzing de VM basado en snapshot |
Feedbacks
| Feedback | Interesante cuando |
|---|
MaxMapFeedback | Nuevos edges de cobertura golpeados |
TimeFeedback | Tiempo de ejecución cambia |
CrashFeedback | Objetivo crasheó (objetivo) |
TimeoutFeedback | Objetivo se colgó (objetivo) |
NewHashFeedback | Nuevo stack de crash único |
| Combinadores | feedback_or!, feedback_and! para componer |
Mutators
| Mutator | Hace |
|---|
havoc_mutations() | Mutaciones aleatorias estándar tipo AFL |
tokens_mutations() | Inserción de diccionario/token |
| Grammar mutators | Generación consciente de estructura |
| Personalizado | Implementar el trait Mutator para tu tipo de entrada |
Los tipos de entrada personalizados más los mutadores personalizados son la razón principal para elegir LibAFL — hacer fuzzing de un protocolo o AST de forma inteligente en lugar de voltear bits al azar.
Scaling multi-core
| Mecanismo | Nota |
|---|
LlmpRestartingEventManager | Paso de mensajes de bajo overhead entre cores |
Launcher | Genera un fuzzer por core con corpus compartido |
| Sincronización de corpus | Las entradas interesantes se propagan entre instancias |
| Reiniciando | Sobrevive a crashes del proceso fuzzer |
LibAFL vs fuzzers listos para usar
| Aspecto | LibAFL | AFL++ | honggfuzz |
|---|
| Modelo | Construye el tuyo | Listo para ejecutar | Listo para ejecutar |
| Esfuerzo | Alto | Bajo | Bajo |
| Flexibilidad | Total | Configurable | Configurable |
| Mejor para | Objetivos inusuales, investigación | Binarios estándar | Inicio rápido, feedback por hardware |
Comienza con AFL++ o honggfuzz; muévete a LibAFL cuando puedas articular específicamente por qué no se ajustan.
Recursos