Ir al contenido

LibAFL - Framework modular de fuzzing

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

PasoComando
Nuevo proyectocargo new my_fuzzer && cd my_fuzzer
Añadir LibAFLcargo add libafl libafl_bolts
Instrumentación del objetivocargo add libafl_targets (o libafl_qemu, libafl_frida)
Compilarcargo build --release

Conceptos básicos

ComponenteRol
InputLo que se hace fuzzing (bytes, árbol de gramática, syscalls)
ObserverRegistra datos durante una ejecución (mapa de cobertura, timing)
FeedbackDecide si una ejecución fue “interesante”
ObjectiveDecide si una ejecución es una solución (un crash)
CorpusAlmacenamiento para entradas interesantes
MutatorTransforma entradas
SchedulerElige la siguiente entrada a ejecutar
StageUna fase aplicada por entrada (mutar, trim, calibrate)
ExecutorEjecuta el objetivo con una entrada

Un fuzzer mínimal (forma)

// 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)

ExecutorUsar
InProcessExecutorMás rápido; harness en el mismo proceso
ForkserverExecutorEstilo AFL forkserver para binarios externos
CommandExecutorEjecutar un comando externo por entrada
libafl_qemuObjetivos emulados / fuzzing binario-only
libafl_fridaInstrumentación dinámica (binario-only)
libafl_nyxFuzzing de VM basado en snapshot

Feedbacks

FeedbackInteresante cuando
MaxMapFeedbackNuevos edges de cobertura golpeados
TimeFeedbackTiempo de ejecución cambia
CrashFeedbackObjetivo crasheó (objetivo)
TimeoutFeedbackObjetivo se colgó (objetivo)
NewHashFeedbackNuevo stack de crash único
Combinadoresfeedback_or!, feedback_and! para componer

Mutators

MutatorHace
havoc_mutations()Mutaciones aleatorias estándar tipo AFL
tokens_mutations()Inserción de diccionario/token
Grammar mutatorsGeneración consciente de estructura
PersonalizadoImplementar 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

MecanismoNota
LlmpRestartingEventManagerPaso de mensajes de bajo overhead entre cores
LauncherGenera un fuzzer por core con corpus compartido
Sincronización de corpusLas entradas interesantes se propagan entre instancias
ReiniciandoSobrevive a crashes del proceso fuzzer

LibAFL vs fuzzers listos para usar

AspectoLibAFLAFL++honggfuzz
ModeloConstruye el tuyoListo para ejecutarListo para ejecutar
EsfuerzoAltoBajoBajo
FlexibilidadTotalConfigurableConfigurable
Mejor paraObjetivos inusuales, investigaciónBinarios estándarInicio 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