
Fuzzer de formatos binarios basado en plantillas que genera y analiza entradas de prueba válidas a alta velocidad, con integración con AFL++ para fuzzing guiado por cobertura.
FormatFuzzer es un marco de trabajo para la generación y análisis de entradas binarias de alta eficiencia y alta calidad.
Toma una plantilla binaria que describe el formato de una entrada binaria y genera un ejecutable que produce y analiza el formato binario dado.
A partir de una plantilla binaria para GIF, por ejemplo, FormatFuzzer produce un generador de GIF, también conocido como fuzzer de GIF.
Los generadores producidos por FormatFuzzer son altamente eficientes, produciendo miles de entradas de prueba válidas por segundo, en marcado contraste con los fuzzers basados en mutación, donde la gran mayoría de las entradas son inválidas. Las entradas generadas por FormatFuzzer son independientes del programa bajo prueba (o, en realidad, de cualquier programa), por lo que también se pueden usar en entornos de caja negra. Sin embargo, FormatFuzzer también se integra con AFL++ para producir entradas válidas que también busquen la máxima cobertura. En nuestros experimentos, este enfoque de "lo mejor de dos mundos" supera a todos los demás entornos; consulte nuestro artículo para obtener más detalles.
Las plantillas binarias utilizadas por FormatFuzzer provienen del editor 010.
Hay más de 170 plantillas binarias, que se pueden usar directamente para FormatFuzzer o adaptarse para su uso. De serie, FormatFuzzer produce formatos como AVI, BMP, GIF, JPG, MIDI, MP3, MP4, PCAP, PNG, WAV y ZIP; y seguimos ampliando esta lista cada semana.
¡Los colaboradores son bienvenidos! Visite la página del proyecto FormatFuzzer para plantear ideas y problemas, o agregar pull requests. Para obtener detalles sobre cómo funciona FormatFuzzer y cómo se compara, lea nuestro artículo para más información.
FormatFuzzer está disponible en la página del proyecto FormatFuzzer. Puede descargar y descomprimir la última versión desde la página de versiones.
Para lo más reciente y mejor, también puede clonar su repositorio git:
git clone https://github.com/uds-se/FormatFuzzer.git
Todas las acciones posteriores se realizan en su carpeta principal:
cd FormatFuzzer
Para ejecutar FormatFuzzer, necesita lo siguiente:
getopt_long()) como clang o gccpy010parser, six e intervaltreezlib (para funciones de compresión)boost (para funciones de suma de comprobación)Si planea editar los scripts de compilación y configuración (archivos .ac y .am), también necesitará
sudo apt install git g++ make automake python3-full zlib1g-dev libboost-dev
python3 -m venv ~/fuzz
source ~/fuzz/bin/activate
pip3 install py010parser six intervaltree
xcode-select --install
brew install python3 automake boost
pip3 install py010parser six intervaltree
En todos los sistemas, usando pip:
pip install py010parser
pip install six
pip install intervaltree
Nota: todos los comandos de compilación requieren que esté en la misma carpeta que este archivo README. La compilación de un fuzzer fuera de esta carpeta aún no es compatible.
Hay un script build.sh que automatiza todos los pasos de construcción.
Simplemente ejecute
./build.sh gif
para crear un fuzzer de GIF.
Esto funciona para todos los formatos de archivo proporcionados en templates/; si hay un archivo templates/FOO.bt, entonces ./build.sh FOO compilará un fuzzer.
Hay un Makefile (fuente en Makefile.am) que automatiza todos los pasos de construcción.
(Requiere GNU make).
Primero haga
touch configure Makefile.in
luego
./configure
y luego
make gif-fuzzer
para crear un fuzzer de GIF.
Esto funciona para todos los formatos de archivo proporcionados en templates/; si hay un archivo templates/FOO.bt, entonces make FOO-fuzzer compilará un fuzzer.
Si el método make anterior no funciona, o si desea más control, es posible que deba proceder manualmente.
Ejecute el compilador ffcompile para compilar la plantilla binaria en código C++. Toma dos argumentos: la plantilla binaria .bt y un archivo .cpp de C++ que se generará.
./ffcompile templates/gif.bt gif.cpp
Utilice los siguientes comandos para crear un fuzzer gif-fuzzer.
Primero, compile el controlador de línea de comandos genérico:
g++ -c -I . -std=c++17 -g -O3 -Wall fuzzer.cpp
(-I . denota la ubicación del archivo bt.h; -std=c++17 establece el estándar de C++).
Luego, compile el analizador/generador binario:
g++ -c -I . -std=c++17 -g -O3 -Wall gif.cpp
Finalmente, enlace el analizador/generador binario con el controlador de línea de comandos para obtener un ejecutable. Si utiliza bibliotecas adicionales (como -lz), asegúrese de especificarlas aquí también.
g++ -O3 gif.o fuzzer.o -o gif-fuzzer -lz
FormatFuzzer se puede ejecutar como un analizador, generador o mutador independiente de formatos específicos. Además, puede ser llamado por fuzzers de propósito general como AFL++ para integrar esas capacidades específicas de formato en el proceso de fuzzing (consulte la sección a continuación sobre la integración con AFL++).
El fuzzer generado toma un comando como primer argumento, seguido de opciones y argumentos para ese comando.
El comando más importante es fuzz, para producir salidas. Sus argumentos son archivos que se generarán en el formato apropiado.
Ejecute el generador como
./gif-fuzzer fuzz output.gif
para crear un archivo binario aleatorio output.gif, o
./gif-fuzzer fuzz out1.gif out2.gif out3.gif
para crear tres archivos GIF out1.gif, out2.gif y out3.gif.
Tenga en cuenta que la plantilla gif.bt que proporcionamos ha sido aumentada con funciones especiales para facilitar la generación de archivos válidos. Si utiliza archivos de plantilla .bt originales sin adaptaciones, puede recibir advertencias durante la generación y crear archivos inválidos.
También puede ejecutar el fuzzer como un analizador de archivos binarios, usando el comando parse. Esto es útil si desea probar la precisión de la plantilla binaria, o si desea mutar una entrada (consulte 'Archivos de Decisión', a continuación).
Para ejecutar el analizador, use
./gif-fuzzer parse input.gif
Verá mensajes de error si input.gif no se puede analizar correctamente.
Mientras analiza, también puede almacenar todas las decisiones de análisis (es decir, qué alternativas de análisis se tomaron) en un archivo de decisión. Esta es una secuencia de bytes que enumera las decisiones tomadas.
Cada byte representa una única decisión de análisis. Un valor de byte 0 significa que se tomó la primera alternativa, un valor de byte 1 significa que se tomó la segunda alternativa, y así sucesivamente.
Puede generar dicho archivo de decisión al analizar una entrada:
./gif-fuzzer parse --decisions input.dec input.gif
Aquí, input.dec almacena las decisiones tomadas para analizar input.gif.