Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
FormatFuzzer — Fuzzer de formato binário orientado por template que gera e analisa entradas de teste válidas em alta velocidade, com integração AFL++ para fuzzing guiado por cobertura. | Kitploit
Ferramentas/GitHubGitHub/uds-se/formatfuzzer
FuzzingAnálise de Binários
GitHubuds-se/formatfuzzer

FormatFuzzer

Fuzzer de formato binário orientado por template que gera e analisa entradas de teste válidas em alta velocidade, com integração AFL++ para fuzzing guiado por cobertura.

Ver RepositórioSite
44638há 5 mesesRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

FormatFuzzer

FormatFuzzer é uma estrutura para geração e análise de alta eficiência e alta qualidade de entradas binárias. Ela recebe um template binário que descreve o formato de uma entrada binária e gera um executável que produz e analisa o formato binário fornecido. A partir de um template binário para GIF, por exemplo, FormatFuzzer produz um gerador de GIF - também conhecido como fuzzer de GIF.

Os geradores produzidos pelo FormatFuzzer são altamente eficientes, produzindo milhares de entradas de teste válidas por segundo - em forte contraste com fuzzers baseados em mutação, onde a grande maioria das entradas é inválida. As entradas geradas pelo FormatFuzzer são independentes do programa sob teste (ou na verdade, de qualquer programa), então você também pode usá-las em configurações de caixa-preta. No entanto, o FormatFuzzer também se integra com o AFL++ para produzir entradas válidas que também visam a cobertura máxima. Em nossos experimentos, essa abordagem "melhor dos dois mundos" supera todas as outras configurações; veja nosso artigo para detalhes.

Os templates binários usados pelo FormatFuzzer vêm do editor 010. Existem mais de 170 templates binários, que podem ser usados diretamente para o FormatFuzzer ou adaptados para seu uso. Prontos para uso, o FormatFuzzer produz formatos como AVI, BMP, GIF, JPG, MIDI, MP3, MP4, PCAP, PNG, WAV e ZIP; e continuamos estendendo esta lista toda semana.

Contribuições são bem-vindas! Visite a página do projeto FormatFuzzer para registrar ideias e problemas, ou adicionar pull requests. Para detalhes sobre como o FormatFuzzer funciona e como ele se compara, leia nosso artigo para mais informações.

Obtendo

O FormatFuzzer está disponível na página do projeto FormatFuzzer. Você pode baixar e extrair a versão mais recente na página de releases.

Para o mais recente e melhor, você também pode clonar seu repositório git:

root@kitploit:~
git clone https://github.com/uds-se/FormatFuzzer.git

Todas as ações subsequentes ocorrem na sua pasta principal:

root@kitploit:~
cd FormatFuzzer

Pré-requisitos

Para executar o FormatFuzzer, você precisa do seguinte:

  • Python 3
  • Um compilador C++ com bibliotecas GNU (notavelmente getopt_long()) como clang ou gcc
  • Os pacotes Python py010parser, six e intervaltree
  • Uma biblioteca zlib (para funções de compressão)
  • Uma biblioteca boost (para funções de checksum)

Se você planeja editar os scripts de construção e configuração (arquivos .ac e .am), você também precisará de

  • GNU autoconf
  • GNU automake

Instalando Requisitos no Linux (Pacotes Debian, usando um ambiente virtual python)

root@kitploit:~
sudo apt install git g++ make automake python3-full zlib1g-dev libboost-dev
python3 -m venv ~/fuzz
source ~/fuzz/bin/activate
pip3 install py010parser six intervaltree

Instalando Requisitos no MacOS (com Xcode & Homebrew)

root@kitploit:~
xcode-select --install
brew install python3 automake boost
pip3 install py010parser six intervaltree

Instalando Apenas Pacotes Python (Todos os Sistemas Operacionais)

Em todos os sistemas, usando pip:

root@kitploit:~
pip install py010parser
pip install six
pip install intervaltree

Construindo

Nota: todos os comandos de construção exigem que você esteja na mesma pasta que este arquivo README. A construção de um fuzzer fora desta pasta ainda não é suportada.

Método 1: Usando o script build.sh

Existe um script build.sh que automatiza todas as etapas de construção. Basta executar

root@kitploit:~
./build.sh gif

para criar um fuzzer de GIF.

Isso funciona para todos os formatos de arquivo fornecidos em templates/; se houver um arquivo templates/FOO.bt, então ./build.sh FOO construirá um fuzzer.

Método 2: Usando Make

Existe um Makefile (fonte em Makefile.am) que automatiza todas as etapas de construção. (Requer GNU make.) Primeiro faça

root@kitploit:~
touch configure Makefile.in

depois

root@kitploit:~
./configure

e então

root@kitploit:~
make gif-fuzzer

para criar um fuzzer de GIF.

Isso funciona para todos os formatos de arquivo fornecidos em templates/; se houver um arquivo templates/FOO.bt, então make FOO-fuzzer construirá um fuzzer.

Método 3: Passos manuais

Se o método make acima não funcionar, ou se você quiser mais controle, pode ser necessário prosseguir manualmente.

Passo 1: Compilando Arquivos de Template Binário em código C++

Execute o compilador ffcompile para compilar o template binário em código C++. Ele recebe dois argumentos: o template binário .bt e um arquivo C++ .cpp a ser gerado.

root@kitploit:~
./ffcompile templates/gif.bt gif.cpp

Passo 2: Compilando o código C++

Use os comandos a seguir para criar um fuzzer gif-fuzzer. Primeiro, compile o driver de linha de comando genérico:

root@kitploit:~
g++ -c -I . -std=c++17 -g -O3 -Wall fuzzer.cpp

(-I . denota a localização do arquivo bt.h; -std=c++17 define o padrão C++.)

Em seguida, compile o analisador/gerador binário:

root@kitploit:~
g++ -c -I . -std=c++17 -g -O3 -Wall gif.cpp

Finalmente, vincule o analisador/gerador binário com o driver de linha de comando para obter um executável. Se você usar bibliotecas extras (como -lz), certifique-se de especificá-las aqui também.

root@kitploit:~
g++ -O3 gif.o fuzzer.o -o gif-fuzzer -lz

Executando o Fuzzer

O FormatFuzzer pode ser executado como um analisador, gerador ou mutador autônomo de formatos específicos. Além disso, ele pode ser chamado por fuzzers de propósito geral como AFL++ para integrar essas capacidades específicas de formato no processo de fuzzing (veja a seção abaixo sobre integração com AFL++).

O fuzzer gerado recebe um comando como primeiro argumento, seguido por opções e argumentos para esse comando.

O comando mais importante é fuzz, para produzir saídas. Seus argumentos são arquivos a serem gerados no formato apropriado.

Execute o gerador como

root@kitploit:~
./gif-fuzzer fuzz output.gif

para criar um arquivo binário aleatório output.gif, ou

root@kitploit:~
./gif-fuzzer fuzz out1.gif out2.gif out3.gif

para criar três arquivos GIF out1.gif, out2.gif e out3.gif.

Observe que o template gif.bt que fornecemos foi aumentado com funções especiais para facilitar a geração de arquivos válidos. Se você usar arquivos de template .bt originais sem adaptações, pode receber avisos durante a geração e criar arquivos inválidos.

Executando Analisadores

Você também pode executar o fuzzer como um analisador para arquivos binários, usando o comando parse. Isso é útil se você quiser testar a precisão do template binário, ou se quiser mutar uma entrada (veja 'Arquivos de Decisão', abaixo).

Para executar o analisador, use

root@kitploit:~
./gif-fuzzer parse input.gif

Você verá mensagens de erro se input.gif não puder ser analisado com sucesso.

Arquivos de Decisão

Ao analisar, você também pode armazenar todas as decisões de análise (ou seja, quais alternativas de análise foram tomadas) em um arquivo de decisão. Esta é uma sequência de bytes enumerando as decisões tomadas. Cada byte representa uma única decisão de análise. Um valor de byte 0 significa que a primeira alternativa foi tomada, um valor de byte 1 significa que a segunda alternativa foi tomada, e assim por diante.

Você pode gerar esse arquivo de decisão ao analisar uma entrada:

root@kitploit:~
./gif-fuzzer parse --decisions input.dec input.gif

Aqui, input.dec armazena as decisões tomadas para analisar input.gif.

Você também pode usar esse arquivo de decisão ao gerar entradas. O fuzzer então tomará exatamente as mesmas decisões encontradas durante a análise. O seguinte comando gera um novo arquivo GIF usando as decisões determinadas ao analisar input.gif:

root@kitploit:~
./gif-fuzzer fuzz --decisions input.dec input2.gif

Se tudo funcionar bem, ambos os arquivos devem ser idênticos:

root@kitploit:~
cmp input.gif input2.gif

Ao mutar um arquivo de decisão (por exemplo, substituindo bytes individuais), você pode criar entradas que são semelhantes ao arquivo original analisado. Isso é útil para interagir com estratégias de teste específicas e fuzzers como AFL, onde você pode usar gif-fuzzer e similares como tradutores de arquivos de decisão para arquivos binários e vice-versa: o AFL mutaria arquivos de decisão, e o programa sob teste seria executado nos arquivos binários traduzidos. Em contraste com a mutação direta de arquivos binários (como o AFL normalmente faria), isso teria a vantagem de sempre ter entradas válidas - e assim progredir muito mais rápido em direção à cobertura.

Integração com AFL++

Além dos fuzzers específicos de formato, como gif-fuzzer, o FormatFuzzer também pode ser compilado em bibliotecas compartilhadas específicas de formato, como gif.so (para isso, basta executar ./build.sh gif ou make gif.so). Essas bibliotecas compartilhadas podem ser carregadas por fuzzers de propósito geral, como AFL++.

Para executar o AFL++ com o FormatFuzzer, basta seguir as instruções em nossa versão modificada do AFL++. Suportamos diferentes estratégias de fuzzing, incluindo:

  • AFL+FFMut: executa AFL++ usando o FormatFuzzer para fornecer mutações inteligentes específicas de formato.

  • AFL+FFGen: usa o FormatFuzzer como um gerador específico de formato, enquanto o AFL++ muta suas sementes de decisão.

Criando e Personalizando Templates Binários

Para escrever seus próprios templates binários .bt (e assim criar um fuzzer/analisador de alta eficiência para este formato), leia a seção Introdução a Templates e Scripts do Manual do Editor 010.

Em muitos casos, um template do formato que você está procurando (ou um similar) pode já existir. Dê uma olhada na coleção de templates binários do editor 010 para ver se há algo que você possa usar ou basear seu formato.

Observe que os arquivos .bt fornecidos no repositório geralmente visam analisar arquivos. Eles podem ser usados para gerar arquivos também; mas frequentemente carecem de informações exatas sobre quais partes da entrada são necessárias.

Nesta seção, discutimos algumas das maneiras pelas quais você pode personalizar arquivos .bt para funcionar bem com o FormatFuzzer.

Por exemplo, para o formato GIF, o arquivo templates/gif-orig.bt mostra o template binário original, que foi projetado apenas para análise, enquanto o arquivo templates/gif.bt é uma versão modificada capaz de gerar GIFs válidos. Comparando os dois arquivos, vemos que um pequeno número de alterações foi necessário para conseguir isso.

Se você criou um gif-fuzzer, seja executando make gif-fuzzer ou usando a ferramenta ffcompile, você já obteve um arquivo C++ gif.cpp que contém uma implementação do gerador e analisador de GIF. Isso é útil para ver como as alterações que você faz no template binário são traduzidas em código executável. Mais detalhes sobre o código C++ são apresentados na próxima seção.

O template binário GIF faz uso de funções de lookahead ReadUByte() e ReadUShort() para olhar adiante nos valores dos próximos bytes no arquivo antes de realmente analisá-los em um campo de struct. No momento da geração, permitimos que essas funções recebam um argumento adicional especificando um conjunto de valores conhecidos bons para escolher para os bytes que estamos olhando adiante. Além disso, também permitimos especificar um conjunto global de valores conhecidos bons para usar sempre ao chamar uma função de lookahead específica, como ReadUByte(). Eles são armazenados no vetor ReadUByteInitValues.

Por padrão, nosso procedimento de tradução ffcompile tenta minerar valores interessantes que foram usados em comparações contra bytes de lookahead e usá-los como um conjunto global de valores conhecidos. Ao executar

root@kitploit:~
./ffcompile templates/gif.bt gif.cpp

uma mensagem impressa mostra as funções de lookahead identificadas, bem como os valores interessantes minerados:

root@kitploit:~
Finished creating cpp generator.

Lookahead functions found:

ReadUByte
ReadUShort

Mined interesting values:

GlobalColorTableFlag: ['1']
LocalColorTableFlag: ['1']
ReadUByte: ['0x3B', '0x2C']
ReadUShort: ['0xF921', '0xFE21', '0x0121', '0xFF21']
Signature: ['"GIF"']

Para a geração de GIF, no entanto, é melhor especificar o conjunto de valores conhecidos bons para ReadUByte() individualmente em cada chamada à função. Então definimos um array vazio (tamanho 0)

root@kitploit:~
const local UBYTE ReadUByteInitValues[0];

para sobrescrever o conjunto global de ReadUByteInitValues e para cada chamada a ReadUByte(), usamos um argumento adicional para especificar o conjunto de valores bons a usar para aquela localização específica. A linguagem do template binário também é suficientemente poderosa para permitir que essa escolha seja feita com base em condições de tempo de execução. Por exemplo, no código a seguir mostramos como a escolha de valores apropriados para uma chamada ReadUByte() pode depender da versão atual do GIF que estamos gerando. Uma versão GIF 89a permite um valor extra possível para o byte (0x21).

root@kitploit:~
	if(GifHeader.Version == "89a")
		local UBYTE values[] = { 0x3B, 0x2C, 0x21 };
	else
		local UBYTE values[] = { 0x3B, 0x2C };

	while (ReadUByte(FTell(), values) != 0x3B) {
		...
	}

As edições restantes necessárias para o template binário GIF são semelhantes. Por exemplo, para cada campo de struct também pode especificar um conjunto de valores conhecidos bons. Por exemplo, isso especifica os valores corretos para o campo Version: 87a e 89a.

root@kitploit:~
	char	Version[3] = { {"87a"}, {"89a"} };

Entendendo o Código C++ Gerado

Para fins de depuração, bem como para entender como fazer alterações apropriadas para melhorar seus geradores e analisadores, pode ser útil entender alguns funcionamentos internos do código C++ gerado. Idealmente, você deve ser capaz de editar os arquivos de template binário até que eles possam ser usados para gerar arquivos válidos com alta probabilidade, para que você não precise editar o código C++ gerado.

O código C++ cria uma classe para cada struct e union definidos no template binário, bem como para tipos nativos, como int.

No momento da construção, ao inicializar uma variável, podemos definir um conjunto de valores conhecidos bons que essa variável pode assumir. Por exemplo, a chamada do construtor

root@kitploit:~
char_array_class cname(cname_element, { "IHDR", "tEXt", "PLTE", "cHRM", "sRGB", "iEXt", "zEXt", "tIME", "pHYs", "bKGD", "sBIT", "sPLT", "acTL", "fcTL", "fdAT", "IHDR", "IEND" });

especificaria 17 valores bons para usar na variável cname. Mas isso muitas vezes não é suficiente, pois a escolha de tipos de chunk apropriados depende do contexto. Portanto, também permitimos especificar um conjunto de valores bons no momento da geração ao gerar um novo chunk. Por exemplo, esta chamada poderia ser usada para gerar uma instância de chunk para o primeiro chunk, que deve ter o tipo IHDR.

root@kitploit:~
GENERATE(chunk, ::g->chunk.generate({ "IHDR" }, false));

Ao gerar o segundo chunk, podemos usar esta longa lista de chunks possíveis que podem vir entre o chunk IHDR e o chunk PLTE:

root@kitploit:~
GENERATE(chunk, ::g->chunk.generate({ "iCCP", "sRGB", "sBIT", "gAMA", "cHRM", "pHYs", "sPLT", "tIME", "zTXt", "tEXt", "iTXt", "eXIf", "oFFs", "pCAL", "sCAL", "acTL", "fcTL", "fdAT", "fRAc", "gIFg", "gIFt", "gIFx", "sTER" }, true));

O gerador então escolherá uniformemente um dos valores conhecidos bons para usar na nova instância. Também permitimos a escolha de um valor malicioso que não está entre os valores conhecidos bons com pequena probabilidade de 1/128. Este recurso pode ser ativado ou desativado a qualquer momento usando o método set_evil_bit.

Todas as escolhas aleatórias tomadas pelo gerador são feitas chamando o método rand_int().

root@kitploit:~
long long rand_int(unsigned long long x, std::function<long long (unsigned char*)> parse);

Ao executar o programa como gerador, este método amostra um inteiro de 0 a x-1 lendo bytes do buffer aleatório. Ao executar o programa como analisador, este método usa a função parse() para descobrir quais bytes aleatórios devem estar presentes no buffer aleatório para gerar o arquivo alvo, e então escreve esses bytes no buffer aleatório. A função parse recebe como argumento o buffer na posição atual do arquivo e deve então retornar qual valor seria retornado pela chamada atual a rand_int() para gerar esta configuração exata do arquivo.

Autores

O FormatFuzzer foi projetado e escrito por Rafael Dutra <[email protected]>.

O conceito de um compilador de fuzzer foi introduzido por Rahul Gopinath <[email protected]> e Andreas Zeller <[email protected]>.

Direitos Autorais e Licenças

O FormatFuzzer tem direitos autorais © 2020, 2021 do CISPA Helmholtz Center for Information Security. As seguintes licenças se aplicam:

  • O código do FormatFuzzer (notavelmente, todo o código C++ e código relacionado à sua geração) está sujeito à GNU GENERAL PUBLIC LICENSE, conforme encontrado em COPYING.

  • Como exceção ao acima, o código C++ gerado pelo FormatFuzzer (ou seja, fuzzers e analisadores para formatos específicos) está em domínio público.

  • O código pfp original, no qual o FormatFuzzer se baseia, está sujeito a uma licença MIT, conforme encontrado em LICENSE-pfp.

Baixar ferramenta