Guía de prueba de AFL para la herramienta Fuzzer clásica

AFL (American Fuzzy Lop) es una herramienta de prueba difusa basada en Cobertura guiada desarrollada por el investigador de seguridad Michał Zalewski. Al registrar la cobertura del código de las muestras de entrada, la entrada se muta continuamente para lograr una mayor cobertura del código. AFL utiliza un nuevo tipo de instrumentación en tiempo de compilación y algoritmo genético para descubrir automáticamente nuevos casos de prueba que desencadenarán nuevos estados internos en el binario objetivo. Esto mejora en gran medida la cobertura del código de las pruebas fuzz. 1

  1. Inserte el instrumento al compilar el programa del código fuente para registrar la cobertura del código (Cobertura del código);
  2. Seleccione algunos archivos de entrada para unirse a la cola de entrada como el conjunto de prueba inicial;
  3. Mutar los archivos en la cola de acuerdo con una determinada estrategia ";
  4. Si la cobertura se actualiza a través del archivo de mutación, se mantendrá y se agregará a la cola;
  5. El proceso anterior continuará circulando y se grabará el archivo que provocó el bloqueo.

Inserte la descripción de la imagen aquí


0x10 instalar afl

Elija una de las siguientes tres versiones (se recomienda la segunda. He probado las tres. En modo afl normal, no hay problema con las tres. Pero cuando se trata de un uso más profundo, hay algunos errores; segunda Esta es una versión relativamente buena)

AFLplusplus introduce un algoritmo de compilación más fuerte.Si se inserta el código fuente, AFLplusplus es más adecuado. Ingrese al proyecto descargado, instale afl, el comando es el siguiente

make	# 编译 afl
sudo make install

Esta es una captura de pantalla de una compilación exitosa
Inserte la descripción de la imagen aquí

0x20 compilar el programa bajo prueba (prueba de caja blanca)

El propósito de usar AFL para compilar el código fuente de destino es insertar instrumentación para que el programa compilado pueda ser cubierto por la ruta de retroalimentación. AFL viene con versiones personalizadas de compiladores gcc y clang, se recomienda elegir el compilador clang de LLVM, que puede acelerar la velocidad de fuzz .

0x21 Use afl-gcc para la inserción del código fuente

Para un solo archivo, solo use afl-gcc en lugar de gcc

afl-gcc test.c -o test

Para un proyecto completo, debe especificar el compilador como afl-gcc y luego compilar

./configure CC="afl-gcc" CXX="afl-g++"	# 或者直接修改 Makefie 文件,将编译器改位 afl-gcc
make

Si necesita biblioteca compartida pelusa , puede configurar LD_LIBRARY_PATHel programa para cargar archivos .so instrumentados a través de la AFL, pero la forma más fácil es construir una estática, logrado por

./configure --disable-shared CC="afl-gcc" CXX="afl-g++"

0x22 Utilice el modo LLVM para instrumentación de código fuente

AFL también admite el uso del modo LLVM, que puede obtener una velocidad de fuzz más rápida y tiene más opciones. La representación frontal de LLVM es el compilador clang, por lo que debe instalar clang usted mismo y luego puede compilar

afl-clang test.c -o test

Error 0x23 al cargar bibliotecas compartidas error 2

Una vez completada la compilación, puede producirse el siguiente error. Esto se debe a que el compilador solo usará los archivos de la biblioteca en los dos directorios / lib y / usr / lib de forma predeterminada . Instale el programa mediante la compilación del código fuente. Si no se especifica --prefix, la biblioteca se instalará en el /usr/local/libdirectorio; cuando ejecute el programa, debe vincular Cuando se muestra la biblioteca dinámica, indica que no se puede encontrar la biblioteca .so relevante y se informará un error. En otras palabras, el directorio / usr / local / lib no está en el directorio de búsqueda de biblioteca predeterminado del sistema, y ​​el directorio debe agregarse.
Inserte la descripción de la imagen aquí
Solución

  1. Abrir /etc/ld.so.confarchivo
  2. Agregue el directorio donde se encuentra el archivo de biblioteca dinámica: ejecutar vi /etc/ld.so.conf, include ld.so.conf.d/*.conf"agregue en ""/usr/local/lib"
  3. Después de guardar, ejecutar el terminal de línea de comandos: /sbin/ldconfig -v; su papel es el de archivo de /etc/ld.so.confalmacenamiento en caché de archivo de biblioteca en la ruta que se muestra a /etc/ld.so.cachepara su uso, por lo que al instalar algunas de las bibliotecas, o modificar etc/ld.so.confañadido una nueva ruta de búsqueda de biblioteca, consiguió correr ldconfig, de modo que todos los archivos de la biblioteca se almacenan en caché en el archivo /etc/ld.so.cache, si no se hace, que no podía encontrar las librerías recién instaladas.

0x30 seleccione corpus

De hecho, es para alimentar el programa de prueba con casos de prueba apropiados. Afl generará una gran cantidad de casos de uso basados ​​en estas semillas y mutaciones originales. En condiciones ideales, el corpus proporcionado (es decir, el caso de prueba original) puede permitir que el programa ejecute diferentes rutas , para maximizar la cobertura del código.

0x31 Seleccionar caso de uso

Aquí, tomando prestados los materiales proporcionados por Freebuf, proporcione algunos corpus de código abierto

De hecho, muchos programas también traerán algunos casos, que también pueden usarse como casos de prueba.


Cuerpo condensado 0x32

Después de encontrar el corpus, es mejor poder recortar, fusionar casos de uso repetidos y recortar el volumen. afl El volumen de casos de uso recomendado es inferior a 1 KB , de lo contrario, afectará la eficiencia de fuzz.

Deduplicación

afl-cmin Es una herramienta muy útil proporcionada por afl, que puede racionalizar el corpus y eliminar posibles casos de prueba duplicados. Es muy útil para algunos cuerpos complejos y puede reducir en gran medida los casos de uso de fuzz inútiles.

afl-cmin -i input_dir -o output_dir -- /path/to/tested/program [params]

Más a menudo, recibimos información del archivo, por lo que a menudo usamos @@ en lugar de parámetros (parámetros), es decir

afl-cmin -i input_dir -o output_dir -- /path/to/tested/program @@

Reducir el volumen

afl-tminEl tamaño del archivo se puede acortar, porque afl requiere que el tamaño de los casos de prueba sea preferiblemente inferior a 1 KB, por lo que es mejor reducir aún más el tamaño de los casos de uso simplificados. afl-tmin tiene dos modos de trabajo instrumented modey crash mode. El modo de trabajo predeterminado es el modo instrumentado.

afl-tmin -i input_file -o output_file -- /path/to/tested/program [params] @@

Debido a que afl-cmin solo puede simplificar un solo archivo a la vez, si hay muchos casos de uso, lleva mucho tiempo manualmente, de hecho, se puede completar un script de shell simple

for i in *; do afl-tmin -i $i -o tmin-$i -- ~/path/to/tested/program [params] @@; done;

0x40 fuzzing

Antes de programa formalmente de la pelusa, se puede utilizar afl-mappara rastrear una sola ruta de ejecución con la forma de realización, se imprima y procedimientos tuplas de salida

afl-showmap -m none -o /dev/null

El comando para ejecutar formalmente la prueba fuzz es el siguiente

afl-fuzz -m none -i in -o out target_binary @@

Fuzz de caja negra 0x50

El proceso fuzz anterior depende del código fuente del programa que tenemos, y la instrumentación se lleva a cabo durante el proceso de compilación, pero muchas veces no tenemos el código fuente, en este momento confiamos en el modo qemu_mode provisto por afl. La versión original del modo afl qemu es demasiado antigua para ejecutarse normalmente. Se recomienda usar AFLplusplus o afl-unicorn en github . AFLplusplusMás fácil de instalar y afl-unicornmás fácil de usar para el modo de qemu.

No importa qué versión de afl se descargue, habrá una carpeta qemu_mode en el directorio raíz, ingrese este directorio, ejecute el siguiente script, si no hay error, significa que qemu_mode se realizó correctamente

cd qemu_mode
sudo ./build_qemu_support.sh

Si hay un error, visite: Análisis en profundidad de los problemas de compilación e instalación de afl / qemu-mode (qemu mode) / afl-unicorn y las soluciones correspondientes

Si desea hacer un recuadro negro de archivos binarios fuzz de diferentes arquitecturas, debe especificar la arquitectura correspondiente antes de compilar el script qemu . Por ejemplo, para ejecutar el programa de arquitectura fuzz arm bajo la arquitectura x86, debe ejecutar el siguiente comando

CPU_TARGET=arm ./build_qemu_support.sh

Después de que la compilación sea exitosa, puede realizar fuzz box negro

afl-fuzz -Q -m none -i in -o out target_binary @@

Análisis de combate real 0x60

Análisis de código fuente 0x61

Escribe una demostración, por ejemplo. Aquí, para reflejar la función de instrumentación del af, varias si las ramas se escriben intencionalmente. En la profundidad de la rama, se producirá un desbordamiento de la pila.

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>

int main(int argc, char const *argv[])
{
	if(argc != 2)
	{
		printf("null args!\n");
		return -1;
	}

	/* Get file state */
	struct stat fstat;
	if(stat(argv[1], &fstat))
	{
		printf("Failed ^_^\n");
		return -1;
	}

	/* Open file */
	FILE * fd = NULL;
	fd = open(argv[1], O_RDONLY);
	if(fd == -1)
	{
		printf("open file failed!\n");
		return -1;
	}

	/* Select */
	char buf[15];
	if(read(fd, buf, 2) == -1)
	{
		printf("read failed!");
		return -1;
	}

	if(buf[0] == 'a' && buf[1] == 'b')
	{
		if(read(fd, buf, 4) != -1)
		{
			if(buf[2] == 's')
			{
				read(fd, buf, fstat.st_size - 6);
				printf("%s\n", buf);
			}
		}
	}

	return 0;
}

Inserción de código fuente 0x62

Compile con el modo LLVM de afl, es decir, instrumente el código fuente

afl-clang afl_demo.c -o afl_demo

Cada instrucción if representa cada rama condicional, y lo que aparece en la ventana de desmontaje de IDA es un bloque básico. Una declaración if es una nueva rama. Como se muestra a continuación, usamos afl-clang para compilar el código desensamblado. Como puede ver, en cada declaración if, se ha instrumentado automáticamente. Es _afl_maybe_loguna función de instrumentación que se utiliza para retroalimentar la ruta.
Inserte la descripción de la imagen aquí

0x63 Generar corpus

Cree un nuevo directorio en, cree un nuevo archivo en el directorio, escriba una semilla, y el algoritmo de mutación generará varios casos de prueba basados ​​en esta mutación semilla y lo alimentará al programa, como escribir la siguiente información (de acuerdo con el código, cuando el primer carácter es un, el segundo Los caracteres son b, el quinto carácter es s, puede producirse un desbordamiento)

abttdcccccccccccccccccccccccccaaaaaaaaaaaaaaaaaaaaaaadddddddddddddddddddddddddddd

0x64 comenzar a difuminar

root@lys-virtual-machine:~/Documents/test# afl-fuzz -m none -i in -o out ./afl_demo @@
afl-fuzz++2.60d based on afl by Michal Zalewski and a big online community
[+] afl++ is maintained by Marc "van Hauser" Heuse, Heiko "hexcoder" Eißfeldt and Andrea Fioraldi
[+] afl++ is open source, get it at https://github.com/vanhauser-thc/AFLplusplus
[+] Power schedules from github.com/mboehme/aflfast
[+] Python Mutator and llvm_mode whitelisting from github.com/choller/afl
[+] afl-tmin fork server patch from github.com/nccgroup/TriforceAFL
[+] MOpt Mutator from github.com/puppet-meteor/MOpt-AFL
[*] Getting to work...
[+] Using exploration-based constant power schedule (EXPLORE)
[+] You have 8 CPU cores and 2 runnable tasks (utilization: 25%).
[+] Try parallel jobs - see /usr/local/share/doc/afl/parallel_fuzzing.md.
[*] Checking CPU core loadout...
[+] Found a free CPU core, try binding to #0.
[*] Checking core_pattern...
[!] WARNING: Could not check CPU scaling governor
[*] Setting up output directories...
[+] Output directory exists but deemed OK to reuse.
[*] Deleting old session data...
[+] Output dir cleanup successful.
[*] Scanning 'in'...
[+] No auto-generated dictionary tokens to reuse.
[*] Creating hard links for all input files...
[*] Validating target binary...
[*] Attempting dry run with 'id:000000,time:0,orig:testcases.txt'...
[*] Spinning up the fork server...
[+] All right - fork server is up.
    len = 81, map size = 9, exec speed = 199 us
[+] All test cases processed.

[+] Here are some useful stats:

    Test case count : 1 favored, 0 variable, 1 total
       Bitmap range : 9 to 9 bits (average: 9.00 bits)
        Exec timing : 199 to 199 us (average: 199 us)

[*] No -t option specified, so I'll use exec timeout of 20 ms.
[+] All set and ready to roll!

En la ventana de fuzz,
Inserte la descripción de la imagen aquí
puede ver que se ha producido un bloqueo. Cuando los ciclos realizados son de color verde, significa que se puede detener el fuzz.

Análisis de resultados 0x65

Analicemos los resultados, de acuerdo con los comandos ingresados ​​durante fuzz, nuestros resultados se muestran en el directorio de salida

root@lys-virtual-machine:~/Documents/test/out# tree
.
├── cmdline
├── crashes
│   ├── id:000000,sig:11,src:000001,time:600493+000003,op:splice,rep:64
│   ├── id:000001,sig:11,src:000003,time:600898,op:havoc,rep:64
│   └── README.txt
├── fuzz_bitmap
├── fuzzer_stats
├── hangs
├── plot_data
└── queue
    ├── id:000000,time:0,orig:testcases.txt
    ├── id:000001,src:000000,time:3,op:flip1,pos:0,+cov
    ├── id:000002,src:000000,time:6,op:flip1,pos:1,+cov
    └── id:000003,src:000000,time:3406,op:havoc,rep:2,+cov

3 directories, 11 files
  • accidentes : casos de prueba únicos que hacen que el objetivo se bloquee con una señal fatal
  • fuzzer_stats: estado de ejecución de afl-fuzz
  • se bloquea: casos de prueba únicos que hacen que el objetivo agote el tiempo de espera
  • plot_data: se usa para el trazado afl-plot
  • cola: almacena todos los casos de prueba con rutas de ejecución únicas

afl-plot puede dibujar resultados más intuitivos, utilizando el archivo plot_data generado por el fuzzer. Por supuesto, para usar afl-plot, necesita instalarapt-get install gnuplot

root@lys-virtual-machine:~/Documents/test# afl-plot out result/
progress plotting utility for afl-fuzz by Michal Zalewski

[*] Generating plots...
[*] Generating index.html...
[+] All done - enjoy your charts!

De esta manera, puede generar archivos html y de imágenes en el directorio de resultados, como se muestra a continuación
Inserte la descripción de la imagen aquí

  • La primera imagen: cuando la cobertura de ruta cambia, el número de favoritos pendientes se convierte en cero, y el número de rutas totales básicamente no ha aumentado, significa que es menos probable que el fuzzer encuentre nuevas.
  • Crash y cambios de tiempo de espera
  • Cambios en la velocidad de ejecución.

Para encontrar el error nuevamente, simplemente ingrese el caso de prueba en el directorio de bloqueo.

Resumen 0x70

Como una excelente herramienta de fuzz, AFL calcula la cobertura del código a través de la inserción del código fuente, y luego utiliza esto como base para mutar continuamente el corpus (archivo semilla) para lograr el efecto de aumentar la cobertura del código. Este artículo explica principalmente su uso general, y su más eficiente es también la inserción del código fuente en modo LLVM, combinado con ejemplos específicos, para realizar pruebas fuzz. Para archivos binarios compilados a partir de código C / C ++, aunque AFL también proporciona fuzzbox de fuente negra sin fuente basada en qemu, la eficiencia es baja y la posibilidad de encontrar vulnerabilidades es pequeña. Por lo tanto, es mejor usar el modelo general de AFL, es decir, la prueba fuzz basada en la instrumentación del código fuente.

En el caso de que no haya código fuente, si desea utilizar la instrumentación binaria directamente, debe instalar qemu-mode o unicornio. Puede haber muchos problemas con la instalación. Bienvenido a otro blog: análisis en profundidad de afl / qemu-mode (qemu mode) / Problemas de compilación e instalación de afl-unicornio y soluciones correspondientes .


  1. https://www.freebuf.com/articles/system/191543.html ↩︎

  2. https://www.cnblogs.com/codingmengmeng/p/7456539.html ↩︎

52 artículos originales publicados · Me gusta 30 · Visitas 50,000+

Supongo que te gusta

Origin blog.csdn.net/song_lee/article/details/104777149
Recomendado
Clasificación