Introdução ao honggfuzz
O honggfuzz é um fuzzer baseado na cobertura de código desenvolvida pelo google, que acompanha o afl e o libfuzzer. É também uma ferramenta fuzz orientada a feedback muito eficiente .
Projeto | Honggfuzz |
---|---|
Endereço do projeto | https://github.com/google/honggfuzz |
Desenvolvedor | |
Se deve atualizar | Continue atualizando |
recursos do honggfuzz
- Multi-processo e multi-thread , então o fuzz é muito rápido
- Suporte a fuzz persistente (Fuzz persistente) , o processo de chamar a API para fuzz repetido por um longo tempo
- Fácil de usar, forneça-o em um catálogo de corpus simples (pode até estar vazio para testes de distorção baseados em feedback), ele evoluirá gradualmente e expandirá-o usando métricas de cobertura baseadas em feedback
- Use a interface subjacente para monitorar o processo e é mais provável que encontre e relate sinais que são seqüestrados e ignorados pela falha
- Suporta vários modos de fuzz (baseado em hardware (CPU: contagem de ramificações / instruções, Intel BTS, Intel PT) e modo fuzzy baseado em feedback baseado em software) (mais do que outros fuzzers baseados em cobertura)
Baixar projeto
$ git clone https://github.com/google/honggfuzz
Compilar e instalar
$ make
$ sudo make install
Análise prática
A demonstração do teste é a seguinte (pode ser comparada com afl: o clássico guia de teste difuso da ferramenta Fuzzer AFL ), aqui para refletir a função de instrumentação do afl, escrevi especificamente alguns se ramificações e, na profundidade da ramificação, ocorrerá um estouro de pilha
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
int main(int argc, char const *argv[])
{
if(argc != 2)
{
printf("null args!\n");
return -1;
}
/* Get file state */
struct stat fstat;
if(stat(argv[1], &fstat))
{
printf("Failed ^_^\n");
return -1;
}
/* Open file */
FILE * fd = NULL;
fd = open(argv[1], O_RDONLY);
if(fd == -1)
{
printf("open file failed!\n");
return -1;
}
/* Select */
char buf[15];
if(read(fd, buf, 2) == -1)
{
printf("read failed!");
return -1;
}
if(buf[0] == 'a' && buf[1] == 'b')
{
if(read(fd, buf, 4) != -1)
{
if(buf[2] == 's')
{
read(fd, buf, fstat.st_size - 6);
printf("%s\n", buf);
}
}
}
return 0;
}
Se o código acima chegar ao ponto mais profundo, o estouro da pilha é muito provável. Quando o primeiro caractere digitado pelo usuário é a, o segundo caractere é b e o quinto caractere é s, a condição é satisfeita. Nosso objetivo é fornecer apenas um caso de uso que esteja em conformidade com o formato (semente original, aqui está um caso de teste que permite que o programa seja executado, ou seja, uma string). A ferramenta fuzz será automaticamente alterada para gerar mais outros casos de teste, procurando se o código pode ir para ramificações diferentes (semelhante à força bruta).
Instrumentação do código fonte
hfuzz-clang hfuzzDemo.c -o hfuzzDemo
Cada instrução if representa cada ramo condicional, e o que aparece na janela de desmontagem da IDA é um bloco básico. Uma instrução if é um novo ramo. Como mostrado abaixo, usamos hfuz-clang para compilar o código de desmontagem. Em cada instrução if, ele foi instrumentado automaticamente. É _sanitizer_cov_trace_const
uma função de instrumentação usada para registrar a contaminação. Essa é uma opção de otimização que acompanha o compilador LLVM e pode calcular aproximadamente a cobertura do código.
Gere um corpus
Crie um novo diretório, crie um novo arquivo no diretório, escreva uma semente e o algoritmo de mutação gerará vários casos de teste com base nessa mutação de semente e a alimentará ao programa, como escrever as seguintes informações (de acordo com o código, quando o primeiro caractere for um, o segundo Os caracteres são b, o quinto caractere é s, pode ocorrer um estouro)
hello world
Comece a fuzzing
honggfuzz -e txt -u -z -Q -i ./in -W ./result -- ./hgfuzzDemo ___FILE___
Análise de parâmetros
- e especifica a extensão do caso de teste
- u Salve todos os casos de teste
- z Instrumentação do código fonte
- Q Imprima a saída do programa em teste
- i Corpus, ou seja, a semente, que é o caso de teste original
- W diretório de trabalho
--
Separe honggfuzz do programa em teste___FILE___
Os parâmetros do programa em teste usam espaços reservados em vez de nomes de arquivos, semelhantes a @@ no AFL
Executar captura de tela
Análise de resultados
armazenar os resultados do diretório resultado, incluindo o HONGGFUZZ.REPORT.TXT
bem de modo que os casos de testes de colisão
Problemas de perguntas e respostas
Pergunta um:
linux/bfd.c:28:10: fatal error: bfd.h: No such file or directory
#include <bfd.h>
^~~~~~~
compilation terminated.
Makefile:259: recipe for target 'linux/bfd.o' failed
make: *** [linux/bfd.o] Error 1
Isso ocorre porque não há binutils-dev
apt-get install binutils-dev
Pergunta dois:
linux/unwind.c:27:10: fatal error: libunwind-ptrace.h: No such file or directory
#include <libunwind-ptrace.h>
^~~~~~~~~~~~~~~~~~~~
compilation terminated.
Makefile:259: recipe for target 'linux/unwind.o' failed
make: *** [linux/unwind.o] Error 1
Se o seguinte erro for solicitado, isso ocorre porque não há libunwind-dev
apt-get install libunwind-dev
Pergunta 3: O
Ubuntu 18.0.4 falha, então o ambiente de teste é Kali
Sumário
Comparado às ferramentas tradicionais de fuzz, a maior vantagem do honggfuzz é que o fuzz é extremamente rápido.As vantagens do multi-threading e do multi-processo permitem que o honggfuzz utilize totalmente os recursos da CPU e melhore bastante a taxa de localização de casos de teste de falha. Aqui, o exemplo que usamos, e autor do clássico Fuzzer AFL guia ferramenta de fuzzing exemplo mencionado é o mesmo, no entanto,
Aqui, usei um mundo olá corpus muito casual e encontrei rapidamente a falha ; em comparação com o AFL mencionado anteriormente, o autor montou deliberadamente um caso de teste que é muito semelhante ao caso de teste da falha do programa * como o corpus original, que demorou muito tempo Somente encontrou falha *. Portanto, a eficiência do honggfuzz é óbvia.