
Fuzzing de alto rendimiento usando traducciones binarias de riscv a x86 y técnicas modernas de fuzzing
Fecha de inicio: diciembre de 2021
Este es un fuzzer de caja gris basado en emulación y guiado por cobertura que utiliza un compilador Just-In-Time personalizado para alcanzar un rendimiento cercano al nativo. Funciona elevando binarios ELF de RISC-V a una representación intermedia antes de compilarlos con JIT a x86 durante la ejecución. Durante la compilación JIT, el código se instrumenta para habilitar mejoras de fuzzing como el seguimiento de cobertura, asan, cmpcov o fuzzing basado en snapshots.

El objetivo de este proyecto es resaltar los beneficios de usar un entorno emulado para el fuzzing. Existen muchos fuzzers anteriores basados en emulación, pero casi todos utilizan exclusivamente el motor de emulación qemu para la emulación subyacente. Si bien este motor tiene un compilador just-in-time bastante maduro y genera muy buen código, no está diseñado para fuzzing. Durante el fuzzing, pretendemos ejecutar el mismo proceso miles de veces por segundo. Esto deja espacio para optimizaciones especializadas que qemu no aprovecha en gran medida, como reutilizar el mismo espacio de memoria para cada ejecución del proceso y restablecer solo una cantidad limitada de memoria mediante mecanismos de dirty bits.
En muchos sentidos, esto es más una prueba de concepto en la que quería trabajar para aprender sobre el funcionamiento interno de los compiladores y tener un entorno de pruebas basado en emulación para experimentar con diversas técnicas de fuzzing, como diferentes métricas de cobertura, programadores de semillas y fuzzing basado en snapshots. Con más optimizaciones JIT y, lo más importante, extensiones para incluir arquitecturas más populares como mips o arm, sin embargo, ciertamente podría usarse para fuzzear de manera eficiente código fuente cerrado que no puede simplemente instrumentarse mediante recompilación.
Dadas las pruebas que he realizado hasta ahora, sfuzz tiene significativamente menos sobrecarga que muchos otros fuzzers populares, lo que se traduce en un rendimiento muy rápido, especialmente para casos de fuzzing pequeños.
Más detalles sobre las características/decisiones tomadas para este fuzzer se enumeran en la publicación del blog adjunta (https://seal9055.com/blog/fuzzing/sfuzz) y en los archivos de documentación que se enumeran a continuación:
Todo este fuzzer está escrito en rust, así que después de clonar el repositorio, simplemente ejecuta cargo build --release para compilarlo.
Dado que el fuzzer actualmente solo admite RISC-V, el objetivo debe compilarse a RISC-V usando la siguiente cadena de herramientas (o una similar). Alternativamente, si ya tienes un binario RISC-V, también funcionará perfectamente.
Una vez que esto esté configurado, simplemente crea directorios de entrada/salida, agrega algunos archivos semilla iniciales al directorio de entrada e inicia el fuzzer.
./sfuzz -i in -o out -- ./test_cases/simple_test @@
Se pueden pasar indicadores adicionales mediante opciones de línea de comandos para especificar el número de hilos, habilitar el fuzzing con snapshots, agregar un diccionario al mutador, etc. Las opciones adicionales se pueden listar ejecutando sfuzz con el indicador -h.
Si deseas probar el fuzzer contra algunos objetivos de complejidad variable, el progrem_generator en tools/program_generator se puede usar para generar automáticamente programas de complejidad variable. Ten en cuenta que necesitarás una cadena de herramientas RISC-V para luego compilar el objetivo.
Esto configura una cadena de herramientas para compilar binarios riscv que pueden ser cargados/usados por este proyecto.
Riscv compiler/tooling:
sudo apt-get install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev \
libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev \
libexpat-dev
git clone https://github.com/riscv/riscv-gnu-toolchain && cd riscv-gnu-toolchain
./configure --prefix=/opt/riscv --with-arch=rv64i
sudo make
Debugger:
gdb-multiarch
Esta lista representa un conjunto de características que planeo implementar en el futuro.