
En este artículo, vamos a hablar no sobre el AFL clásico en sí, sino sobre las utilidades diseñadas para él y sus modificaciones, que, en nuestra opinión, pueden mejorar significativamente la calidad del fuzzing. Si desea saber cómo aumentar la AFL y cómo encontrar más vulnerabilidades más rápido, ¡siga leyendo!
¿Qué es AFL y para qué sirve?
AFL es un difusor guiado por cobertura o basado en comentarios. Más información sobre estos conceptos se puede encontrar en un artículo genial,
"Fuzzing: Art, Science, and Engineering" . Vamos a resumir la información general sobre AFL:
- Modifica el archivo ejecutable para descubrir cómo influye en la cobertura.
- Muta los datos de entrada para maximizar la cobertura.
- Repite el paso anterior para encontrar dónde se bloquea el programa.
- Es altamente efectivo, lo cual está probado por la práctica.
Aquí hay una representación gráfica:

Si no sabe qué es AFL, aquí hay una lista de recursos útiles para que pueda comenzar:
- La página oficial del proyecto .
- afl-training : una breve introducción a AFL.
- afl-demo : una demostración simple de programas difusos de C ++ con AFL.
- afl-cve : una colección de vulnerabilidades encontradas con AFL (no se ha actualizado desde 2017).
- Aquí puede leer sobre las cosas que AFL agrega a un programa durante su construcción.
- Algunos consejos útiles sobre aplicaciones de red fuzzing.
En el momento en que se escribió este artículo, la última versión de AFL era
2.52b . El fuzzer está en desarrollo activo y, con el tiempo, algunos desarrollos secundarios se están incorporando a la rama principal de AFL y se vuelven irrelevantes. Hoy, podemos nombrar varias herramientas accesorias útiles, que se enumeran en el siguiente capítulo.
Rode0day concursoTambién vale la pena mencionar la competencia mensual de
Rode0day , un evento donde los fuzzers intentan encontrar la mayor cantidad de errores con menos tiempo que sus oponentes en corpus prefabricados con y sin acceso al código fuente. En su naturaleza, Rode0day es una batalla entre diferentes modificaciones y tenedores de AFL.
Algunos usuarios de AFL
notaron que su autor, Michal Zalewski, aparentemente había abandonado el proyecto desde la fecha de las últimas modificaciones hasta el 5 de noviembre de 2017. Esto puede estar relacionado con que abandone Google y trabaje en algunos proyectos nuevos. Entonces, los usuarios comenzaron a hacer nuevos
parches para la última versión actual 2.52b.

También hay diferentes variaciones y derivados de AFL, que permiten difuminar Python, Go, Rust, OCaml, GCJ Java, syscalls de kernel o incluso máquinas virtuales completas.
Herramientas de accesorios
Para este capítulo, hemos recopilado varios scripts y herramientas para AFL y los hemos dividido en varias categorías:
Procesamiento de bloqueo- afl-utils : un conjunto de utilidades para el procesamiento / análisis automático de fallas y la reducción del número de casos de prueba.
- afl-crash-analyzer : otro analizador de bloqueos para AFL.
- fuzzer-utils : un conjunto de scripts para el análisis de resultados.
- atriage : una herramienta de triaje simple.
- afl-kit - afl-cmin en Python.
- AFLize : una herramienta que genera automáticamente compilaciones de paquetes debian adecuados para AFL.
- afl-fid : un conjunto de herramientas para trabajar con datos de entrada.
Trabaja con cobertura de código- afl-cov : proporciona datos amigables para los humanos sobre la cobertura.
- count-afl-calls - evaluación de proporción. El script cuenta el número de bloques de instrumentación en el binario.
- afl-sancov : es como afl-cov pero usa un desinfectante clang.
- covnavi : un script para cubrir el código y el análisis de Cisco Talos Group.
- Pases LAF LLVM : algo así como una colección de parches para AFL que modifican el código para facilitar que el fuzzer encuentre ramas.
Algunas secuencias de comandos para minimizar los casos de prueba- afl-pytmin : un contenedor para afl-tmin que intenta acelerar el proceso de minimización de casos de prueba mediante el uso de muchos núcleos de CPU.
- afl-ddmin-mod : una variación de afl-tmin basada en el algoritmo ddmin.
- halfempty : es una utilidad rápida para minimizar los casos de prueba de Tavis Ormandy basada en la paralelización.
Ejecución distribuidaRecientemente, se ha publicado un muy buen artículo titulado
"Escalado de AFL a una máquina de 256 hilos" .
Despliegue, gestión, seguimiento, informes.- afl-other-arch : es un conjunto de parches y scripts para agregar fácilmente soporte para varias arquitecturas que no son x86 para AFL.
- afl-trivia : algunas pequeñas secuencias de comandos para simplificar la gestión de AFL.
- afl-monitor : un script para monitorear AFL.
- afl-manager : un servidor web en Python para administrar multi-afl.
- afl-tools : una imagen de un acoplador con afl-latest, afl-dyninst y Triforce-afl.
- afl-remote : un servidor web para la gestión remota de instancias de AFL.
Modificaciones AFL
AFL tuvo un impacto muy fuerte en la comunidad de investigadores de vulnerabilidades y se confundió. No es sorprendente en absoluto que después de un tiempo la gente comenzó a hacer modificaciones inspiradas en el AFL original. Echemos un vistazo a ellos. En diferentes situaciones, cada una de estas modificaciones tiene sus propios pros y contras en comparación con el AFL original.
Casi todas las modificaciones se pueden encontrar en
hub.docker.comPara que
- Aumentar la velocidad y / o la cobertura del código
- Trabajando sin código fuente
- Emulación de código
- Instrumentación de código
Modos predeterminados de operación AFLAntes de continuar con el examen de diferentes modificaciones y tenedores de AFL, tenemos que hablar sobre dos modos importantes, que también habían sido modificaciones en el pasado pero que finalmente se incorporaron. Son Syzygy y Qemu.
Modo
Syzygy : es el modo de trabajar en instrument.exe
instrument.exe --mode=afl --input-image=test.exe --output-image=test.instr.exe
Syzygy permite reescribir estáticamente los binarios de PE32 con AFL, pero requiere símbolos y un desarrollador adicional para que el núcleo WinAFL sea consciente.
Modo Qemu: la forma en que funciona bajo QEMU se puede ver en
"Internals of AFL fuzzer - QEMU Instrumentation" . El soporte de trabajar con binarios con QEMU se agregó a AFL ascendente en la Versión 1.31b. El modo AFL QEMU funciona con la funcionalidad adicional de la instrumentación binaria en el motor de traducción binaria qemu tcg (un generador de código pequeño). Para eso, AFL tiene un script de compilación qemu, que extrae las fuentes de una determinada versión de qemu (2.10.0), las coloca en varios parches pequeños y construye para una arquitectura definida. Luego, se crea un archivo llamado afl-qemu-trace, que de hecho es un archivo de emulación en modo de usuario de (emulación de solo archivos ELF ejecutables) qemu-. Por lo tanto, es posible usar fuzzing con retroalimentación sobre los binarios de elfos para muchas arquitecturas diferentes compatibles con qemu. Además, obtienes todas las herramientas de AFL, desde el monitor con información sobre la sesión actual hasta cosas avanzadas como afl-analyse. Pero también obtienes las limitaciones de qemu. Además, si un archivo se construye con la cadena de herramientas utilizando las funciones de SoC de hardware, que inicia el binario y no es compatible con qemu, el fuzzing se interrumpirá tan pronto como haya una instrucción específica o se use un MMIO específico.
Aquí hay
otra bifurcación interesante del modo qemu, donde la velocidad se incrementó 3-4 veces con instrumentación de código TCG y cobro.
TenedoresLa aparición de horquillas de AFL está relacionada en primer lugar con los cambios y mejoras de los algoritmos del AFL clásico.
- pe-afl : una modificación para difuminar archivos PE que no tienen código fuente en el sistema operativo Windows. Para su funcionamiento, el fuzzer analiza un programa de destino con IDA Pro y genera la información para la siguiente instrumentación estática. Una versión instrumentada se difunde con AFL.
- afl-cygwin : es un intento de portar el clásico AFL a Windows con Cygwin. Desafortunadamente, tiene muchos errores, es muy lento y el desarrollo de ha sido abandonado.
- AFLFast (extiende AFL con Power Schedules): uno de los primeros tenedores AFL. Ha agregado heurísticas, que le permiten recorrer más caminos en un corto período de tiempo.
- FairFuzz - una extensión para AFL, que apunta a ramas raras.
- AFLGo : es una extensión para AFL destinada a llegar a ciertas partes del código en lugar de la cobertura completa del programa. Se puede usar para probar parches o fragmentos de código recién agregados.
- PerfFuzz : una extensión para AFL, que busca casos de prueba que podrían ralentizar significativamente el programa.
- Pythia : es una extensión para AFL destinada a predecir lo difícil que es encontrar nuevos caminos.
- Angora : es uno de los últimos fuzzers, escrito sobre óxido. Utiliza nuevas estrategias para la mutación y para aumentar la cobertura.
- Neuzz : fuzzing con redes neuronales.
- UnTracer-AFL : integración de AFl con UnTracer para un seguimiento efectivo.
- Qsym : práctico motor de ejecución concólico adaptado para fuzzing híbrido. Esencialmente, es un motor de ejecución simbólico (los componentes básicos se realizan como un complemento para Intel pin) que junto con AFL realiza fuzzing híbrido. Esta es una etapa en la evolución del fuzzing basado en comentarios y requiere una discusión por separado. Su principal ventaja es que puede hacer la ejecución concólica relativamente rápido. Esto se debe a la ejecución nativa de comandos sin representación intermedia de código, instantáneas y algunas heurísticas. Utiliza el pin anterior de Intel (debido a problemas de soporte entre libz3 y otros DBT) y actualmente puede funcionar con arquitecturas elf x86 y x86_64.
- Superion - Greybox fuzzer, cuya ventaja obvia es que, junto con un programa instrumentado, también obtiene la especificación de los datos de entrada utilizando la gramática ANTLR y luego realiza mutaciones con la ayuda de esta gramática.
- AFLSmart - Otro fuzzer de Graybox. Como entrada, obtiene la especificación de los datos de entrada en el formato utilizado por el fuzzer Peach.
Hay muchos trabajos de investigación dedicados a la implementación de los nuevos enfoques y técnicas de fuzzing donde se modifica AFL. Solo hay libros blancos disponibles, por lo que ni siquiera nos molestamos en mencionarlos. Puedes buscarlos en Google si quieres. Por ejemplo, algunos de los últimos son
CollAFL: Path Sensitive Fuzzing ,
EnFuzz ,
"Enfoque eficiente para intérpretes fuzzing" ,
ML para AFL.
Modificaciones basadas en Qemu- TriforceAFL : fuzz AFL / QEMU con emulación completa de un sistema. Un tenedor por nccgroup. Permite difuminar todo el sistema operativo en modo qemu. Se realiza con una instrucción especial (aflCall (0f 24)), que se agregó en la CPU QEMU x64. Desafortunadamente, ya no es compatible; La última versión de AFL es 2.06b.
- TriforceLinuxSyscallFuzzer : la difuminación de las llamadas al sistema Linux.
- afl-qai : un pequeño proyecto de demostración con QEMU Augmented Instrumentation (qai).
Una modificación basada en KLEEkleefl : para generar casos de prueba mediante ejecución simbólica (muy lento en programas grandes).
Una modificación basada en Unicornioafl-unicorn : permite difuminar fragmentos de código al emularlo en
Unicorn Engine . Utilizamos con éxito esta variación de AFL en nuestra práctica, en las áreas del código de un determinado RTOS, que se ejecutó en SOC, por lo que no pudimos usar el modo QEMU. El uso de esta modificación se justifica en el caso en que no podemos tener fuentes (no podemos construir un binario independiente para el análisis del analizador sintáctico) y el programa no toma datos de entrada directamente (por ejemplo, datos está encriptado o es una muestra de señal como en un binario CGC), entonces podemos revertir y encontrar las supuestas funciones de lugares, donde los datos se procesan en un formato conveniente para el fuzzer. Esta es la modificación más general / universal de AFL, es decir, permite difuminar cualquier cosa. Es independiente de la arquitectura, las fuentes, el formato de datos de entrada y el formato binario (el ejemplo más llamativo de metal desnudo: solo fragmentos de código de la memoria del controlador). El investigador primero examina este binario y escribe un fuzzer, que emula el estado en la entrada del procedimiento del analizador. Obviamente, a diferencia de AFL, esto requiere un cierto examen de binario. Para el firmware de metal desnudo, como Wi-Fi o banda base, hay ciertos inconvenientes que debe tener en cuenta:
- Tenemos que localizar la verificación de la suma de control.
- Tenga en cuenta que el estado del fuzzer es un estado de memoria que se guardó en el volcado de memoria, lo que puede evitar que el fuzzer llegue a ciertas rutas.
- No se sanean las llamadas a la memoria dinámica, pero se puede realizar de forma manual y dependerá de RTOS (debe investigarse).
- La interacción Intertask RTOS no se emula, lo que también puede evitar encontrar ciertas rutas.
Un ejemplo de trabajo con esta modificación
"afl-unicornio: Código binario arbitrario fuzzing " y
"afl-unicornio: Parte 2 - Fuzzing 'Unfuzzable'" .
Antes de pasar a las modificaciones basadas en los marcos de la instrumentación binaria dinámica (DBI), no olvidemos que DynamoRIO, Dynlnst y, finalmente, PIN muestran la velocidad más alta de estos marcos.
Modificaciones basadas en PIN- aflpin - AFL con instrumentación de PIN Intel.
- afl_pin_mode : otra instrumentación AFL realizada a través de Intel PIN.
- afl-pin - AFL con PINtool.
- NaFl : un clon (del núcleo básico) de AFL fuzzer.
- PinAFL : el autor de esta herramienta intentó portar AFL a Windows para eliminar los binarios ya compilados. Parece que se hizo de la noche a la mañana solo por diversión; El proyecto nunca ha ido más lejos. El repositorio no tiene fuentes, solo binarios compilados e instrucciones de lanzamiento. No sabemos en qué versión de AFL se basa, y solo admite aplicaciones de 32 bits.
Como puede ver, hay muchas modificaciones diferentes, pero no son muy útiles en la vida real.
Modificaciones basadas en Dyninstafl-dyninst - American Fuzzy Lop + Dyninst == AFL balckbox fuzzing. La característica de esta versión es que primero un programa investigado (sin el código fuente) se instrumenta estáticamente (instrumentación binaria estática, reescritura binaria estática) con Duninst, y luego se confunde con el AFL clásico que cree que el programa está construido con afl- gcc / afl-g ++ / afl-as;) Como resultado, permite trabajar con una muy buena productividad sin el código fuente: solía tener una velocidad de 0.25x en comparación con una compilación nativa. Tiene una ventaja significativa en comparación con QEMU: permite la instrumentación de bibliotecas vinculadas dinámicas, mientras que QEMU solo puede instrumentar el archivo ejecutable básico estáticamente vinculado con bibliotecas. Desafortunadamente, ahora solo es relevante para Linux. Para el soporte de Windows, se necesitan cambios en Dyninst, lo que se
está haciendo .
Hay otra
bifurcación con velocidad mejorada y ciertas características (el soporte de las arquitecturas AARCH64 y PPC).
Modificaciones basadas en DynamoRIO- drAFL - AFl + DynamoRIO - fuzzing sin fuentes en Linux.
- afl-dr : otra implementación basada en DynamoRIO que se describe muy bien en Habr .
- afl-dynamorio : una modificación de vanhauser-thc. Esto es lo que dice al respecto: "ejecutar AFL con DynamoRIO cuando afl-dyninst normal está bloqueando el binario y el modo qemu -Q no es una opción". Es compatible con ARM y AARCH64. En cuanto a la productividad: DynamoRIO es aproximadamente 10 veces más lento que Qemu, 25 veces más lento que dyninst, pero aproximadamente 10 veces más rápido que Pintool.
- WinAFL : la bifurcación de AFL más famosa de Windows. (DynamoRIO, también modo syzygy). Era solo cuestión de tiempo que apareciera este mod porque muchos querían probar AFL en Windows y aplicarlo a aplicaciones sin fuentes. Actualmente, esta herramienta se está mejorando activamente, e independientemente de una base de código relativamente desactualizada de AFL (2.43b cuando se escribe este artículo), ayudó a encontrar varias vulnerabilidades (CVE-2016-7212, CVE-2017-0073, CVE- 2017-0190, CVE-2017-11816). Los especialistas del equipo de Google Zero Project y el Equipo de Vulnerabilidades y Mitigaciones de MSRC están trabajando en este proyecto, por lo que podemos esperar un mayor desarrollo. En lugar de la instrumentación de tiempo de compilación, los desarrolladores utilizaron instrumentación dinámica (basada en DynamoRIO), que ralentizó significativamente la ejecución del software analizado, pero la sobrecarga resultante (duplicada) es comparable a la del AFL clásico en modo binario. También resolvieron el problema del inicio rápido del proceso, llamándolo modo persistente de fuzzing; eligen la función para difuminar (por el desplazamiento dentro del archivo o por el nombre de la función presente en la tabla de exportación) y la instrumentan para que pueda llamarse en el ciclo, iniciando así varias muestras de datos de entrada sin reiniciar el proceso. Recientemente apareció un artículo que describe cómo los autores encontraron alrededor de 50 vulnerabilidades en aproximadamente 50 días usando WinAFL. Y poco antes de su publicación, el modo Intel PT se había agregado a WinAFL; Los detalles se pueden encontrar aquí .
Un lector avanzado podría notar que hay modificaciones con todos los marcos de instrumentación populares, excepto
Frida . La única mención del uso de Frida con AFL se encontró en
"Chizpurfle: un Fuzzer de Android de caja gris para personalizaciones de servicios de proveedores" . Una versión de AFL con Frida es realmente útil porque Frida admite varias arquitecturas RISC.
Muchos investigadores también esperan con ansias el lanzamiento del marco DBI Scopio por parte del creador de Capstone, Unicorn y Keystone. Con base en este marco, los autores ya han creado un fuzzer (Darko) y, según ellos, lo utilizan con éxito para difuminar dispositivos integrados. Se puede encontrar más información sobre esto en
"Profundizando: encontrar 0 días en sistemas integrados con fuzzing guiado por cobertura de código" .
Modificaciones, basadas en las características del hardware del procesador.Cuando se trata de modificaciones de AFL con el soporte de las características de hardware del procesador, en primer lugar, permite difuminar el código del kernel y, en segundo lugar, permite difuminar las aplicaciones mucho más rápido sin el código fuente.
Y, por supuesto, hablando de las características del hardware del procesador, estamos más interesados en
Intel PT (Processor Tracing). Está disponible desde la sexta generación de procesadores en adelante (aproximadamente, desde 2015). Por lo tanto, para poder usar los fuzzers enumerados a continuación, necesita un procesador compatible con Intel PT.
Conclusión
Como puede ver, el área de modificaciones de AFL está evolucionando activamente. Aún así, hay espacio para experimentos y soluciones creativas; puedes crear una nueva modificación útil e interesante.
¡Gracias por leernos y buena suerte con fuzzing!
Coautor: Nikita Knyzhov
preslerPD: Gracias al equipo del centro de investigación, sin el cual este artículo sería imposible.