Simple Science

Ciencia de vanguardia explicada de forma sencilla

# Informática# Lenguajes de programación

Mejorando la Prueba de Software con Fuzzing de Caja Gris

Un nuevo enfoque para las pruebas de software usando fuzzing de caja gris y descenso de gradiente.

― 7 minilectura


Avance en Fuzzing de CajaAvance en Fuzzing de CajaGrisefectiva.para descubrir errores de maneraPruebas de software de nivel superior
Tabla de contenidos

El fuzzing es una forma de probar software dando entradas aleatorias o inesperadas. Ayuda a encontrar errores que pueden causar caídas u otros problemas. Este artículo habla sobre un nuevo método llamado fuzzing de caja gris, que busca mejorar este proceso de prueba combinándolo con el descenso de gradiente, una técnica matemática que se usa a menudo para encontrar el mínimo o máximo de una función. Este método se enfoca específicamente en cómo los valores numéricos se convierten en valores verdaderos o falsos en el software.

¿Qué es el Fuzzing de Caja Gris?

El fuzzing de caja gris es un tipo de prueba que tiene conocimiento sobre el funcionamiento interno del software, pero aún así utiliza entradas aleatorias. Esto se diferencia de las pruebas de caja negra, donde el probador no sabe nada sobre cómo opera el software. Al entender algunas partes del software, el fuzzing de caja gris puede generar entradas que probablemente conduzcan a resultados interesantes.

¿Por qué Usar Descenso de Gradiente?

El descenso de gradiente es útil porque ayuda a identificar las entradas correctas que pueden cambiar los resultados de ciertas instrucciones dentro del software. Al hacer esto, el proceso de fuzzing de caja gris puede enfocarse en áreas específicas que probablemente contengan errores.

Instrucciones Booleanas y Cobertura

Las instrucciones booleanas son comandos en un programa que evalúan condiciones y producen resultados verdaderos o falsos. Un ejemplo es la comparación entre dos números. Maximizar la cobertura de estas instrucciones booleanas puede llevar a mejores resultados en las pruebas, ya que esto asegura que se exploren varios caminos y condiciones en la lógica del programa.

La Herramienta de Fuzzing

El nuevo método de fuzzing de caja gris se implementa en una herramienta de software. Esta herramienta está diseñada para interactuar con ejecutables de 64 bits, tomando programas de entrada escritos en C y convirtiéndolos en binarios que se pueden probar. La herramienta consiste en varios componentes que trabajan juntos para generar entradas, ejecutar el programa que se está probando y analizar los resultados.

Generación de entradas

El bucle de fuzzing funciona generando entradas basadas en datos previos. Esto puede incluir entradas aleatorias o más específicas basadas en características conocidas del software. Para una generación efectiva de entradas, la herramienta debe entender cuáles son las entradas más sensibles a los cambios en el programa.

Bits Sensibles

Algunos bits en la entrada tienen un impacto mayor en las salidas que otros. Al identificar estos bits sensibles, la herramienta de fuzzing puede enfocar sus esfuerzos en generar entradas más útiles, en lugar de perder tiempo en cambios que podrían no afectar el resultado.

Usando Datos Históricos

La herramienta mantiene un registro de qué entradas han tenido éxito en alcanzar ciertas condiciones. Estos datos históricos son útiles para generar nuevas entradas que pueden llevar al programa a nuevos estados, descubriendo potencialmente más errores.

Bucle de Fuzzing

El bucle de fuzzing es el núcleo del proceso de prueba. En cada iteración, la herramienta genera una entrada, ejecuta el programa con esta entrada y recopila datos sobre cómo se comporta el programa.

Ejecución de Entradas

Cuando el programa se ejecuta con la entrada generada, puede producir varios resultados: puede terminar normalmente, fallar, exceder los límites de tiempo o violar ciertos límites operativos. Cada posible resultado se registra, permitiendo que la herramienta aprenda de sus interacciones con el programa.

Comunicación entre Componentes de la Herramienta

La herramienta utiliza tanto memoria compartida como comunicación por red para gestionar la generación y ejecución de entradas. La memoria compartida permite un transfer de datos rápido entre procesos, mientras que la comunicación por red proporciona una forma flexible de configurar los entornos de prueba.

Monitoreo de Ejecución

Para entender qué tan bien funcionan las entradas generadas, la herramienta inserta código de monitoreo en el programa. Este código recopila datos clave sobre cómo el software ejecuta cada instrucción booleana.

Recolectando Datos

El código de monitoreo registra varias piezas de información, como el resultado de cada instrucción booleana, los valores que llevaron a esos resultados y si se cumplieron ciertas condiciones antes de las evaluaciones. Estos datos son críticos para entender el comportamiento del programa bajo diferentes entradas.

Construyendo un Árbol de Ejecución

A medida que se ejecuta el bucle de fuzzing, la herramienta construye un árbol de ejecución. Cada nodo en este árbol representa un punto en el programa donde se ejecutó una instrucción booleana. El camino a través de este árbol muestra cómo el software llegó a ese punto, y el árbol ayuda a visualizar qué partes del programa se han cubierto.

Actualizando el Árbol

Después de cada iteración del bucle de fuzzing, el árbol de ejecución se actualiza con nuevos datos del código de monitoreo. Esto incluye marcar nodos como "visitados" cuando son ejecutados y registrar si llevaron a resultados exitosos o no exitosos.

Usando Funciones de Ramificación

Las funciones de ramificación se utilizan para describir las condiciones bajo las cuales se logran ciertos resultados. La herramienta busca encontrar entradas que cambien los resultados de estas funciones de manera exitosa.

Encontrando Entradas

Usando datos históricos, la herramienta puede muestrear valores de entrada de manera estratégica para aumentar la probabilidad de producir salidas deseadas. El descenso de gradiente ayuda a refinar estas entradas mientras busca aquellas que conducen a diferentes resultados de evaluación.

Análisis de Sensibilidad

Se realiza un análisis de sensibilidad para identificar qué bits de entrada afectan significativamente los resultados.

Identificación de Bits Sensibles

Al probar varias combinaciones de bits de entrada, la herramienta determina qué cambios conducen a diferentes resultados de instrucciones booleanas. Esta información ayuda a enfocar más esfuerzos de prueba en esos bits sensibles.

Análisis de Bitshare

El análisis de bitshare ayuda a reutilizar bits sensibles de entradas anteriores para crear nuevas. Al combinar elementos exitosos de pruebas anteriores, la herramienta puede generar nuevas entradas que probablemente produzcan diferentes resultados.

Análisis de Minimización

El análisis de minimización busca encontrar la entrada más corta o simple que aún produzca un efecto significativo en el comportamiento del software. Este análisis es crucial para la eficiencia, ya que las entradas complejas pueden ser más difíciles de manejar y analizar.

Generando Entradas Semilla

Antes de que se pueda aplicar el descenso de gradiente, la herramienta necesita entradas semilla. Estas entradas semilla se generan basándose en pruebas exitosas previas y están destinadas a guiar rápidamente el proceso de prueba hacia la búsqueda de nuevas entradas efectivas.

Conclusión

El fuzzing de caja gris combinado con el descenso de gradiente y la cobertura de expresiones booleanas proporciona un método poderoso para mejorar las pruebas de software. Al enfocarse en el comportamiento del programa y en los bits de entrada sensibles, este enfoque puede descubrir errores de manera más efectiva que los métodos tradicionales. La integración de datos históricos, monitoreo y análisis crea una herramienta robusta para garantizar la calidad y confiabilidad del software.

Trabajo Futuro

Los desarrollos futuros en el fuzzing de caja gris podrían involucrar mejorar las técnicas de generación de entradas, optimizar la eficiencia del código de monitoreo y ampliar el uso de aprendizaje automático para analizar el comportamiento del programa y guiar los esfuerzos de prueba. Al continuar refinando estos métodos, se puede lograr el objetivo de conseguir pruebas de software más exhaustivas.

Fuente original

Título: Gray-Box Fuzzing via Gradient Descent and Boolean Expression Coverage (Technical Report)

Resumen: We present a novel gray-box fuzzing algorithm monitoring executions of instructions converting numerical values to Boolean ones. An important class of such instructions evaluate predicates, e.g., *cmp in LLVM. That alone allows us to infer the input dependency (c.f. the taint analysis) during the fuzzing on-the-fly with reasonable accuracy, which in turn enables an effective use of the gradient descent on these instructions (to invert the result of their evaluation). Although the fuzzing attempts to maximize the coverage of the instructions, there is an interesting correlation with the standard branch coverage, which we are able to achieve indirectly. The evaluation on Test-Comp 2023 benchmarks shows that our approach, despite being a pure gray-box fuzzing, is able to compete with the leading tools in the competition, which combine fuzzing with other powerful techniques like model checking, symbolic execution, or abstract interpretation.

Autores: Martin Jonáš, Jan Strejček, Marek Trtík, Lukáš Urban

Última actualización: 2024-01-23 00:00:00

Idioma: English

Fuente URL: https://arxiv.org/abs/2401.12643

Fuente PDF: https://arxiv.org/pdf/2401.12643

Licencia: https://creativecommons.org/publicdomain/zero/1.0/

Cambios: Este resumen se ha elaborado con la ayuda de AI y puede contener imprecisiones. Para obtener información precisa, consulte los documentos originales enlazados aquí.

Gracias a arxiv por el uso de su interoperabilidad de acceso abierto.

Artículos similares