
Un plugin de Binary Ninja que utiliza hashes XFG obtenidos por fuerza bruta para recuperar prototipos de funciones precisos.
Este repositorio contiene scripts para generar y buscar hashes de eXtended Flow Guard.
Un análisis extendido de cómo funciona esto está disponible en el número 22 de International Journal Of Proof Of Concept || GTFO.
Mi trabajo en este PoC fue enormemente simplificado por la gente de Quarkslab, quienes han realizado una extensa ingeniería inversa de las partes relevantes del compilador de MS. Su análisis detallado sobre cómo se calculan los hashes XFG se puede leer aquí: https://blog.quarkslab.com/how-the-msvc-compiler-generates-xfg-function-prototype-hashes.html
Nota: esto de ninguna manera "rompe" XFG como mitigación de explotación; simplemente abusa de sus efectos secundarios para iluminar funciones sin símbolos.
En resumen, XFG tal como se implementa en Windows extiende y hace más estricta la mitigación de explotación Control Flow Guard al limitar los posibles destinos de llamadas indirectas a funciones no solo con puntos de entrada válidos, sino a funciones con una firma coincidente. Para ello, se calcula un hash XFG para cada función y se realiza una verificación contra él durante la ejecución. Los hashes se basan únicamente en el prototipo de la función (es decir, convención de llamada, argumentos y sus tipos). Como tal, podemos precalcularlos para tipos conocidos y luego buscarlos para funciones en binarios desconocidos.
Si la búsqueda tiene éxito, podemos estar 100% seguros del número exacto y los tipos de todos los argumentos, así como del valor de retorno de la función. Esto puede ser enormemente útil para binarios y funciones sin símbolos públicos.
Te invito a leer el artículo completo en PoC||GTFO, servido desde un espejo cercano.
Los scripts son:
Para usar estos scripts, primero modificaría gen_function_prototypes.py para agregar "tipos primitivos", estructuras o enums que sean específicos para el objetivo que estás analizando. Además, querrás elegir hasta cuántos argumentos quieres forzar por fuerza bruta. Hasta 3 toma un minuto, hasta 4 un día...
Después de que se generen los prototipos de función de todas las combinaciones, querrás ejecutar gen_hash_from_ast.py, que analizará el archivo generado previamente línea por línea y generará el hash XFG correspondiente.
Cuando eso haya terminado, tendrás una base de datos SQLite de prototipos de funciones con sus hashes XFG coincidentes. Se incluye un plugin muy simple de Binary Ninja en xfg_analyzer.py. Cuando se ejecuta contra un binario protegido por XFG, encontrará todos los hashes XFG, los buscará en la base de datos y, si se encuentra una coincidencia, aplicará el nuevo prototipo de función a la función definida.
Ten en cuenta que esto es solo un PoC. Para ser realmente útil, se debería generar una base de datos gigante de hashes (posiblemente sembrada con todos los nombres de structs/enums de los archivos de cabecera de Windows) y ponerla a disposición para búsquedas en línea. Además, expandir esta idea a hashes XFG de C++ sería un proyecto muy divertido.
Siéntete libre de usar el código de este repositorio de cualquier manera. Si lo encuentras útil, me gustaría saber de ti.