
Um plugin do Binary Ninja que utiliza hashes XFG obtidos por força bruta para recuperar protótipos precisos de funções.
Este repositório contém scripts para gerar e consultar hashes do eXtended Flow Guard.
Uma descrição estendida de como isso funciona está disponível na edição 22 do International Journal of Proof of Concept || GTFO.
Meu trabalho neste PoC foi enormemente simplificado pelo pessoal da Quarkslab, que realizou engenharia reversa extensiva das partes relevantes do compilador da MS. A descrição detalhada deles sobre como os hashes XFG são calculados pode ser lida aqui: https://blog.quarkslab.com/how-the-msvc-compiler-generates-xfg-function-prototype-hashes.html
Nota: isso de forma alguma "quebra" o XFG como mitigação de exploits; simplesmente abusa de seus efeitos colaterais para iluminar funções sem símbolos.
Em resumo, o XFG, como implementado no Windows, estende e torna mais estrita a mitigação de exploits do Control Flow Guard ao limitar os alvos possíveis de chamadas indiretas de função não apenas a pontos de entrada de função válidos, mas a funções com assinatura correspondente. Para isso, um hash XFG é calculado para cada função e uma verificação contra ele é realizada durante a execução. Os hashes são baseados apenas no protótipo da função (ou seja, convenção de chamada, argumentos e seus tipos). Dessa forma, podemos pré-calculá-los para tipos conhecidos e depois consultá-los para funções em binários desconhecidos.
Se a consulta for bem-sucedida, podemos ter 100% de certeza do número exato e dos tipos de todos os argumentos, bem como do valor de retorno da função. Isso pode ser imensamente útil para binários e funções sem símbolos públicos.
Convido você a ler o artigo completo no PoC||GTFO, servido a partir de um espelho próximo.
Os scripts são:
Para usar esses scripts, você primeiro modificaria gen_function_prototypes.py para adicionar "tipos primitivos", structs ou enums específicos para o alvo que você está analisando. Além disso, você vai querer escolher até quantos argumentos deseja forçar por força bruta. Até 3 leva um minuto; até 4, um dia...
Após gerar os protótipos de função de todas as combinações, você vai querer executar gen_hash_from_ast.py, que fará o parsing do arquivo gerado anteriormente linha por linha e gerará o hash XFG correspondente. Quando isso for concluído, você terá um banco de dados SQLite de protótipos de função com seus hashes XFG correspondentes. Um plugin muito simples do Binary Ninja está incluído em xfg_analyzer.py. Quando executado contra um binário protegido por XFG, ele encontrará todos os hashes XFG, os consultará no banco de dados e, se houver correspondência, aplicará o novo protótipo de função à função definida.
Saiba que isso é apenas um PoC. Para ser realmente útil, um banco de dados gigante de hashes (possivelmente alimentado com todos os nomes de structs/enums dos arquivos de cabeçalho do Windows) deveria ser gerado e disponibilizado para consultas online. Além disso, expandir essa ideia para hashes XFG de C++ seria um projeto muito divertido.
Sinta-se à vontade para usar o código deste repositório da forma que quiser. Se você achá-lo útil, gostaria de saber.