
Framework de análise estática que identifica alvos de funções fuzzáveis em código fonte e binários, gera modelos de harness e se integra com AFL++ e libFuzzer para descoberta automatizada de vulnerabilidades.
Framework para Automatizar a Descoberta de Alvos Fuzzable com Análise Estática

Pesquisadores de vulnerabilidades que realizam avaliações de segurança em software frequentemente aproveitam as capacidades de fuzzing guiado por cobertura por meio de ferramentas poderosas como AFL++ e libFuzzer. Isso é importante, pois automatiza o processo de caça a bugs e revela condições exploráveis em alvos rapidamente. No entanto, ao encontrar bases de código grandes e complexas ou binários de código fechado, os pesquisadores precisam dedicar tempo meticulosamente para auditar e fazer engenharia reversa manualmente, a fim de identificar funções onde a exploração baseada em fuzzing pode ser útil.
Fuzzable é um framework que se integra tanto com código-fonte C/C++ quanto com binários para auxiliar pesquisadores de vulnerabilidades a identificar funções-alvo que são viáveis para fuzzing. Isso é feito aplicando várias heurísticas baseadas em análise estática para identificar comportamentos arriscados no software e as funções que os executam. Os pesquisadores podem então usar o framework para gerar templates básicos de harness, que podem ser usados para caçar vulnerabilidades ou ser integrados como parte de um pipeline contínuo de fuzzing, como o projeto oss-fuzz do Google.
Além de funcionar como uma ferramenta autônoma, o Fuzzable também é integrado como um plugin para o desassemblador Binary Ninja, com suporte para outros backends de desmontagem em desenvolvimento.
Confira o post original do blog detalhando a ferramenta aqui, que destaca as especificações técnicas das heurísticas de análise estática e como essa ferramenta surgiu. Esta ferramenta também é apresentada no Black Hat Arsenal USA 2022.
Alguns alvos binários podem exigir alguma sanitização (ex. correspondência de assinaturas ou identificação de funções de inlining) e, portanto, o fuzzable usa principalmente o Binary Ninja como backend de desmontagem devido à sua capacidade de resolver esses problemas de forma eficaz. Portanto, pode ser utilizado tanto como ferramenta autônoma quanto como plugin.
Como o Binary Ninja não é acessível a todos e pode haver demanda para uso em avaliações de segurança e potencial escalonamento na nuvem, um backend fallback angr também é suportado. Antecipo incorporar outros desassembladores no futuro também (prioridade: Ghidra).
Se você possui o Binary Ninja Comercial, certifique-se de instalar a API para uso autônomo headless:
$ python3 /Applications/Binary\ Ninja.app/Contents/Resources/scripts/install_api.py
Instale com pip:
$ pip install fuzzable
Usamos poetry para gerenciamento de dependências e build. Para fazer um build manual, clone o repositório com os módulos de terceiros:
$ git clone --recursive https://github.com/ex0dus-0x/fuzzable
Para instalar manualmente:
$ cd fuzzable/
# without poetry
$ pip install .
# with poetry
$ poetry install
# with poetry for a development virtualenv
$ poetry shell
Agora você pode analisar binários e/ou código-fonte com a ferramenta!
# analyzing a single shared object library binary
$ fuzzable analyze examples/binaries/libbasic.so
# analyzing a single C source file
$ fuzzable analyze examples/source/libbasic.c
# analyzing a workspace with multiple C/C++ files and headers
$ fuzzable analyze examples/source/source_bundle/
fuzzable pode ser facilmente instalado através do marketplace de plugins do Binary Ninja acessando Binary Ninja > Manage Plugins e procurando por ele. Aqui está um exemplo do plugin fuzzable em execução, identificando com precisão alvos para fuzzing e avaliação adicional de vulnerabilidades:

fuzzable vem com várias opções para ajudar a ajustar melhor sua análise. Mais opções serão suportadas em planos futuros e quaisquer solicitações de funcionalidades feitas.
Para determinar a fuzzabilidade, o fuzzable utiliza várias heurísticas para determinar quais alvos são os mais viáveis para análise dinâmica. Essas heurísticas são ponderadas de forma diferente usando a biblioteca scikit-criteria, que utiliza análise de decisão multicritério para determinar os melhores candidatos. Essas métricas e seus pesos podem ser vistos aqui:
Como mencionado, confira o post técnico do blog para uma visão mais aprofundada de por que e como essas métricas são utilizadas.
Muitas métricas foram amplamente inspiradas pelo trabalho original de Vincenzo Iozzo em fuzzing de conhecimento zero.
Cada alvo que você deseja analisar é diverso, e o fuzzable não será capaz de considerar todos os comportamentos de casos extremos no programa alvo. Assim, pode ser importante durante a análise ajustar esses pesos adequadamente para ver se resultados diferentes fazem mais sentido para o seu caso de uso. Para ajustar esses pesos na CLI, basta especificar o argumento --score-weights:
$ fuzzable analyze <TARGET> --score-weights=0.2,0.2,0.2,0.2,0.2
Por padrão, o fuzzable filtrará alvos de função com base nos seguintes critérios:
static e não são expostas por meio de cabeçalhos.Para ver as chamadas que foram filtradas pelo fuzzable, defina a flag --list_ignored:
$ fuzzable analyze --list-ignored <TARGET>
No Binary Ninja, você pode ativar essa configuração em Settings > Fuzzable > List Ignored Calls.
No caso de o fuzzable filtrar falsamente chamadas importantes que devem ser analisadas, é recomendado usar argumentos --include-* para incluí-las durante a execução:
# include ALL non top-level calls that were filtered out
$ fuzzable analyze --include-nontop <TARGET>
# include specific symbols that were filtered out
$ fuzzable analyze --include-sym <SYM> <TARGET>
No Binary Ninja, isso é suportado através de Settings > Fuzzable > Include non-top level calls e Symbols to Exclude.
Agora que você encontrou seus candidatos ideais para fuzz, o fuzzable também ajudará você a gerar harnesses de fuzzing que estão (quase) prontos para instrumentar e compilar para uso com um fuzzer baseado em arquivo (ex. AFL++, Honggfuzz) ou fuzzer em memória (libFuzzer). Para fazer isso na CLI:
# generate harness from a candidate
$ fuzzable create-harness target --symbol-name=some_unsafe_call
# make minimal and necessary modifications to the harness
$ vim target_some_unsafe_call_harness.cpp
# example compilation for AFL-QEMU, which is specified in the comments of the generated harness
$ clang target_some_unsafe_call_harness.cpp -no-pie -o target_some_unsafe_call_harness -ldl
# create your base seeds, ideally should be more well-formed for input
$ mkdir in/
$ echo "seed" >> in/seed
# start black box fuzzing
$ afl-fuzz -Q -m none -i in/ -o out/ -- ./target_some_unsafe_call_harness
Se este alvo for uma base de código-fonte, o template de fonte genérico será usado.
Se o alvo for um binário, o template genérico de caixa-preta será usado, que idealmente pode ser usado com um modo de emulação de fuzzing como AFL-QEMU. Uma cópia do binário também será criada como um objeto compartilhado se o símbolo não for exportado diretamente para ser dlopenado usando LIEF.
No momento, esse recurso é bastante rudimentar, pois simplesmente criará um harness C++ autônomo preenchido com os parâmetros apropriados e não gerará automaticamente o código necessário para nenhum comportamento em tempo de execução (ex. instanciar e liberar estruturas). No entanto, os templates criados para o fuzzable ainda devem fazer você começar rapidamente. Aqui estão alguns recursos ambiciosos que gostaria de implementar no futuro:
fuzzable suporta a geração de relatórios em vários formatos. Os atualmente suportados são JSON, CSV e Markdown. Isso pode ser útil se você estiver utilizando isso como parte de automação onde deseja ingerir a saída em um formato serializável.
Na CLI, basta passar o argumento --export com um nome de arquivo com a extensão apropriada:
$ fuzzable analyze --export=report.json <TARGET>
No Binary Ninja, vá para Plugins > Fuzzable > Export Fuzzability Report > ... e selecione o formato para o qual deseja exportar e o caminho onde deseja gravá-lo.
Esta ferramenta será continuamente desenvolvida, e qualquer ajuda de mantenedores externos é apreciada!
Fuzzable é licenciado sob a Licença MIT.
| Heurística | Descrição | Peso |
|---|
| Nome Amigável para Fuzz | Nome do símbolo implica comportamento que ingere entrada de arquivo/buffer | 0.3 |
| Sumidouros Arriscados | Argumentos que fluem para chamadas arriscadas (ex. memcpy) | 0.3 |
| Laços Naturais | Número de loops detectados com a fronteira de dominância | 0.05 |
| Complexidade Ciclomática | Complexidade do alvo da função baseada em arestas + nós | 0.05 |
| Profundidade de Cobertura | Número de funções chamadas que o alvo percorre | 0.3 |