
Houve artigos sobre o Habré algumas vezes que levantam o tópico do American Fuzzy Lop (AFL) (
1 ,
2 ). Mas neste artigo, não falaremos sobre o AFL clássico, mas sobre utilitários auxiliares para ele e suas modificações, que, em nossa opinião, podem melhorar significativamente a qualidade da difusão. Se você estiver interessado em aprender como atualizar o AFL e procurar vulnerabilidades mais rápidas e mais, bem-vindo ao corte!
O que é AFL e por que é tão bom
AFL - Fuzzer guiado por cobertura ou fuzzer baseado em feedback. Você pode aprender mais sobre esses conceitos em um artigo interessante como
Fuzzing: Art, Science e Engineering . Se resumirmos as informações sobre a AFL, poderemos dizer o seguinte:
- Ferramentas de um executável para coletar informações de cobertura
- Muda a entrada para maximizar a cobertura
- Repete a etapa anterior para encontrar falhas no programa.
- Na prática, provou ser muito eficaz
Graficamente, isso pode ser representado da seguinte maneira:

Se você não sabe o que é AFL, então, para começar, recomendamos:
- Página oficial do projeto
- afl-training - uma breve excursão à AFL
- afl-demo - uma demonstração simples de como difundir um programa C ++ usando AFL
- afl-cve - Coleção de vulnerabilidades descobertas usando o AFL (não atualizado desde 2017)
- O fato de a AFL adicionar ao programa durante sua montagem pode ser encontrado aqui.
- Algumas dicas úteis para aplicações de rede em difusão aqui
No momento da redação deste artigo, a versão mais recente do AFL era a versão
2.52b . A Fazzer está desenvolvendo ativamente e, com o tempo, alguns desenvolvimentos de terceiros são incluídos no principal ramo da AFL e se tornam irrelevantes por si mesmos. Atualmente, existem várias ferramentas auxiliares úteis que podem ser identificadas - elas estão listadas na próxima seção.
Competição Rode0daySeparadamente, vale a pena mencionar a competição mensal
Rode0day , onde há uma competição entre phasers que rapidamente e mais encontrarão vulnerabilidades em casos pré-preparados com acesso ao código fonte e sem ele. E em geral é um confronto de várias modificações e garfos AFL.
No entanto, alguns usuários da AFL
observam que o autor do phaser Michal Zalewski marcou uma campanha para apoiar sua ideia intelectual, já que as últimas alterações são datadas de 5 de novembro de 2017. Isso está associado à sua saída do Google e a novos projetos. Nesse sentido, as pessoas começaram a coletar e fazer
patches de forma independente
para a versão atual mais recente 2.52b.

Também existem variantes e derivados diferentes da AFL que permitem a difusão de Python, Go, Rust, OCaml, GCJ Java, syscalls do kernel ou até VMs inteiras.
Ferramentas auxiliares
Nesta seção, selecionamos vários scripts e ferramentas para trabalhar com o AFL e os dividimos em várias categorias:
Processamento de Kresh- afl-utils - um conjunto de utilitários para processamento / análise automática de falhas e minimização de casos de teste.
- afl-crash-analyzer - Outro analisador de falhas AFL.
- fuzzer-utils - um conjunto de scripts para analisar os resultados.
- atriage é uma ferramenta simples de triagem.
- afl-kit - Reescrito em python afl-cmin.
- O AFLize é uma ferramenta que gera automaticamente compilações de pacotes debian compatíveis com afl.
- afl-fid - um conjunto de ferramentas para trabalhar com dados de entrada.
Cobertura de Código- afl-cov - fornece dados de cobertura legíveis por humanos.
- count-afl-calls - Pontuação da proporção. O script conta o número de blocos instrumentados no binar.
- afl-sancov - como o afl-cov, mas usa desinfetante clang.
- covnavi é um script de análise e cobertura de código do Cisco Talos Group.
- O LAF LLVM Passes é um conjunto de patches para afl que modificam o código para facilitar a passagem de fuzzers por ramificações
Vários scripts para minimizar casos de teste- afl-pytmin - um wrapper para afl-tmin que tenta acelerar o processo de minimizar o caso de teste usando vários núcleos de CPU.
- afl-ddmin-mod - uma variação do afl-tmin com base no algoritmo ddmin.
- halfempty é um utilitário rápido baseado em paralelismo para minimizar os casos de teste do Tavis Ormandy.
Para inicialização distribuída- disfuzz-afl - difusão distribuída por afl.
- AFLDFF é uma estrutura para difusão distribuída com AFL.
- afl-launch é uma ferramenta para iniciar muitas instâncias afl.
- afl-mothership - gerencie e inicie vários fuzzers AFL sincronizados na nuvem da AWS.
- afl-in-the-cloud é outro script para executar afl na AWS.
- VU_BSc_project - Fuzz testando bibliotecas de código aberto com libFuzzer e AFL.
Além disso, um artigo muito bom
“Dimensionando o AFL para uma máquina de 256 threads” foi publicado recentemente sobre este tópico, que descreve o lançamento do AFL em 256 threads.
Implantação, gerenciamento, monitoramento, relatórios- afl-other-arch - um conjunto de patches e scripts para adicionar facilmente suporte a várias arquiteturas (não x86) na AFL.
- afl-trivia - alguns pequenos scripts para simplificar o gerenciamento de AFL.
- afl-monitor - um script para monitorar a operação do AFL.
- afl-manager - um servidor web python para gerenciar multi-afl.
- afl-tools - imagem do docker com afl-latest, afl-dyninst e Triforce-afl.
- afl-remote - um servidor web para gerenciamento remoto de instâncias afl.
Modificações AFL
A AFL influenciou bastante a comunidade de pesquisa de vulnerabilidades e o próprio setor. E não surpreende que, com o tempo, várias modificações inspiradas na AFL original tenham começado a aparecer com base em sua ideia. Nesta seção, vamos considerá-los. Cada uma dessas modificações tem suas vantagens e desvantagens em comparação com a versão AFL original em diferentes situações.
Diremos imediatamente que, se houver problemas com a instalação ou você não quiser perder tempo, quase todas as modificações podem ser encontradas no
hub.docker.comPorque
- Aumentar a cobertura de velocidade e / ou código
- Algoritmos
- O meio ambiente
- Trabalhe em condições sem código fonte
- Emulação de código
- Instrumentação de código
Modos AFL incorporadosAntes de prosseguir para a discussão das várias modificações e garfos da AFL, é necessário falar sobre dois modos importantes que antes eram também modificações e, com o tempo, tornaram-se modos internos. Este é o modo Syzygy e o modo Qemu.
Modo
Syzygy - é o modo operacional no instrumento instrument.exe
instrument.exe --mode=afl --input-image=test.exe --output-image=test.instr.exe
Para este modo, é necessário: Reescrever estaticamente os binários do PE32 com AFL, são necessários símbolos. Requer dev adicional para tornar o kernel do WinAFL ciente.
Modo Qemu - Como ele funciona no QEMU pode ser encontrado aqui
"Internals of AFL fuzzer - QEMU Instrumentation" . O suporte para trabalhar com binários usando QEMU apareceu no AFL upstream da Versão 1.31b. O modo Afl qemu funciona com a funcionalidade adicional de instrumentação de código binário no mecanismo de tradução binária qemu tcg (gerador de código minúsculo). Para fazer isso, o afl possui um script de construção do qemu que baixa o código-fonte para uma versão específica (2.10.0) do qemu, impõe vários pequenos patches neles e compila para uma determinada arquitetura. Depois disso, o arquivo afl-qemu-trace é retornado, que na verdade é uma emulação de modo de usuário (emulação de apenas arquivos executáveis ELF). Graças a isso, você pode usar o fuzzing com feedback dos binários elf e para várias arquiteturas diferentes suportadas pelo qemu. Além disso, você obtém todas as ferramentas legais de afl, começando com uma tela conveniente com informações sobre a sessão atual e terminando com coisas avançadas, como afl-analyse. Mas lembre-se de que você também recebe restrições do qemu. Além disso, por exemplo, se o arquivo for compilado por uma cadeia de ferramentas que usa recursos de hardware SoC, nos quais o binário é iniciado e que não é suportado pelo qemu, a difusão será interrompida assim que uma instrução específica for encontrada ou, por exemplo, um MMIO específico seja usado.
Há também
uma bifurcação interessante do modo qemu, onde a velocidade foi aumentada 3x-4x vezes devido à instrumentação do código TCG e ao cache.
ForquilhasA aparência dos garfos AFL está principalmente associada a alterações, melhorias nos algoritmos de operação do próprio AFL clássico.
- O afl-cygwin é uma tentativa de portar o AFL clássico para o Windows usando o Cygwin. Infelizmente, essa tentativa é bastante divertida, lenta e pode-se dizer que o desenvolvimento foi abandonado.
- AFLFast (estende o AFL com Power Schedules) - um dos primeiros garfos do AFL, todos os tipos de heurísticas foram adicionados, graças aos quais ele poderia seguir outras formas em um curto período.
- FairFuzz é uma extensão AFL cujo objetivo é tentar passar mais tempo em filiais mais raras.
- O AFLGo é uma extensão do AFL, que se destina principalmente à obtenção direcionada de determinadas seções do código, e não à cobertura geral do código do programa. Isso pode ser usado para testar patches ou seções de código recém-adicionadas.
- O PerfFuzz é uma extensão AFL que procura casos de teste que podem retardar o programa o máximo possível.
- Pythia é uma extensão da AFL que visa adicionar elementos de previsão ao processo de fases com relação à dificuldade de encontrar novos caminhos.
- Angora é um dos fuzzers lançados mais recentemente, escrito em ferrugem. Usa suas novas estratégias para mutação e para aumentar a cobertura.
- Neuzz - uma tentativa de difusão usando redes neurais.
- UnTracer-AFL - integração afl com o UnTracer, para rastreamento eficiente.
- Qsym - Mecanismo prático de execução concólica sob medida para difusão híbrida. Na verdade, é um mecanismo de execução de símbolos (os principais componentes são implementados como um plug-in de pinos da Intel) que, em combinação com afl, implementa a difusão híbrida. Esta é uma evolução adicional no tópico difuso baseado em feedback e merece uma discussão separada. Seu principal mérito é que ele pode executar muito rapidamente (em relação ao resto) a execução concólica. Isso ocorre devido à execução nativa de comandos sem a apresentação intermediária do código, eliminando o mecanismo de captura instantânea e várias heurísticas. Ele usa o antigo pino da Intel (devido a vários problemas de suporte entre a libz3 e outros DBTs) e atualmente pode trabalhar com as arquiteturas elf x86 e x86_64.
Vale dizer que existe um grande número de trabalhos acadêmicos relacionados à implementação de novas abordagens, técnicas de difusão, onde a AFL é realizada e modificada. Além do whitepaper, nada mais está disponível; portanto, nem mencionamos essas implementações. Se você estiver interessado, eles são fáceis de pesquisar no Google. Por exemplo, o último é
CollAFL: Path Sensitive Fuzzing ,
EnFuzz ,
Smart Greybox Fuzzing ,
ML para afl.
Modificações baseadas no Qemu- TriforceAFL - AFL / QEMU difusa com emulação completa do sistema . Forquilha do nccgroup. Permite confundir todo o sistema operacional no modo qemu. Implementado por meio de uma instrução especial (aflCall (0f 24)), que foi adicionada à CPU QEMU x64. Infelizmente, ele não é mais suportado, a versão mais recente do afl é o 2.06b.
- TriforceLinuxSyscallFuzzer - Chamadas de sistema Linux confusas.
- O afl-qai é um pequeno projeto de demonstração com QEMU Augmented Instrumentation (qai).
Modificação baseada no KLEEkleefl - para gerar casos de teste por meio de execução simbólica (muito lento em programas grandes).
Modificações baseadas em Unicornafl-unicorn - permite que você confunda partes do código, emulando-o no
Unicorn Engine . Também usamos com sucesso essa variação de AFL em nossa prática, a saber, nas seções de código de um RTOS, que foi executado no SOC, e era impossível usar o modo QEMU. É aconselhável usar esta modificação quando não houver fontes (você não pode montar binários independentes para análise do analisador) e o programa não aceita dados de entrada diretamente (por exemplo, eles são criptografados ou representam amostras de sinal como em um binário CGC), então você pode usá-lo inverta e encontre as funções de local propostas onde esses dados são processados em um formato conveniente para o difusor e que pode ser difundido. Esta é a modificação AFL mais comum. No sentido em que permite literalmente confundir tudo. Ou seja, não depende da arquitetura, da disponibilidade dos códigos-fonte, do formato dos dados de entrada e do formato do próprio binário (o exemplo mais impressionante é apenas bare-metal - apenas trechos de código da memória do controlador). O pesquisador preliminar examina esse mesmo binário e escreve um fuzzer que emula o estado na entrada do procedimento do analisador, por exemplo. Pode-se ver que, diferentemente da AFL, você precisa fazer algum tipo de pesquisa no binar. Para firmware bare-metal, como Wi-Fi ou banda base, há simplesmente uma série de desvantagens que você precisa ter em mente:
- É necessário, de alguma forma, localizar verificações de soma de verificação.
- Deve-se ter em mente que o status do difusor é o estado da memória que foi armazenada no despejo de memória, isso pode impedir a obtenção de certos caminhos para o difusor.
- Não há saneamento dos acessos à memória dinâmica, mas ela pode ser implementada manualmente (também tendo se esforçado) e dependerá do RTOS (também precisará ser investigada antecipadamente).
- A interação entre tarefas do RTOS não é emulada - você também pode impedir que o fuzzer encontre certos caminhos.
Um exemplo de como trabalhar com esta modificação é
"afl-unicorn: Fuzzing Arbitrary Binary Code" e
“Afl-unicorn: Part 2 - Fuzzing the 'Unfuzzable'” .
Antes de avançarmos para modificações baseadas nas estruturas de instrumentação binária dinâmica (DBI), lembramos imediatamente que a mais rápida dessas estruturas é o DynamoRIO, depois o DynInst e, finalmente, o PIN.
Modificações de PIN- aflpin - AFL com instrumentação PIN da Intel.
- afl_pin_mode - Outra instrumentação AFL implementada através do PIN da Intel.
- afl-pin - AFL com PINtool.
- NaFl - Um clone (do núcleo básico) do fuzzer AFL.
- PinAFL - o autor da ferramenta tentou transferir o AFL para o Windows para obter binários já compilados. Aparentemente, mais foi feito no ventilador em uma noite e depois o projeto não se desenvolveu. O repositório não contém fontes, apenas binários coletados e instruções para iniciar. A versão AFL na qual esta ferramenta se baseia não está especificada e suporta apenas aplicativos de 32 bits.
Como você pode ver, existem muitas modificações diferentes, mas na prática não há muito uso nelas na vida real.
Modificações baseadas no Dyninstafl-dyninst - American Fuzzy Lop + Dyninst == AFL fuzzing na caixa preta. O recurso desta versão é que o programa inicialmente estudado (sem código-fonte) é instrumentado estaticamente (instrumentação binária estática, reescrita binária estática) usando DynInst e depois difundido pela AFL clássica, que acredita que o programa foi construído usando afl-gcc / afl -g ++ / afl-as;) No final, ele nos dá a oportunidade de trabalhar sem código fonte e com muito bom desempenho - Costumava estar na velocidade de 0,25x em comparação com uma compilação nativa. Há uma vantagem significativa sobre o QEMU, que é a capacidade de instrumentar bibliotecas vinculadas dinamicamente. Enquanto o QEMU só pode instrumentar o arquivo executável principal vinculado estaticamente às bibliotecas. Infelizmente, agora isso é relevante apenas para o sistema operacional Linux. Para dar suporte ao Windows, são necessárias alterações no próprio DynInst e o
trabalho está em
andamento lá .
Você também pode prestar atenção a essa
bifurcação, onde ela foi bem bombeada por vários recursos (suporte para arquiteturas AARCH64 e PPC) e velocidade;)
Modificações baseadas no DynamoRIO- drAFL - AFL + DynamoRIO = difusão sem fonte no Linux.
- afl-dr - mais uma implementação baseada no DynamoRIO, que já está detalhadamente pintada em espaços abertos da Habr.
- afl-dynamorio - modificação do vanhauser-thc (um ventilador para bombear e estabilizar o AFL). ele diz sobre esta versão: "execute o AFL com o DynamoRIO quando o afl-dyninst normal estiver travando o modo binário e o qemu -Q não é uma opção". De agradável, o suporte para ARM e AARCH64 é adicionado aqui. Em relação ao desempenho: o DynamoRIO é cerca de 10 vezes mais lento que o Qemu, ~ 25 mais lento que o dyninst - no entanto, ~ 10 mais rápido que o Pintool.
- O WinAFL é o mais famoso fork do afl para Windows. (DynamoRIO, também possui o modo syzygy). A aparência dessa modificação foi apenas uma questão de tempo, pois o desejo de experimentar o AFL no Windows em aplicativos para os quais não existem códigos-fonte apareceu para muitos. No momento, a ferramenta está sendo desenvolvida ativamente e, apesar de usar a base de código AFL ligeiramente atrasada (2,43b no momento da redação), várias vulnerabilidades já foram encontradas com ela (CVE-2016-7212, CVE-2017-0073, CVE-2017- 0190, CVE-2017-11816). Deve-se observar que os principais desenvolvedores são especialistas da equipe do Projeto Zero do Google e da equipe de vulnerabilidades e mitigações do MSRC, o que dá motivos para esperar um desenvolvimento ativo do projeto. Para implementar o fuzzer, os desenvolvedores passaram do tempo de compilação da instrumentação para o uso de instrumentação dinâmica (baseada no DynamoRIO), que provavelmente diminuiu a execução do software em estudo, mas a sobrecarga resultante (duas vezes) é comparável à AFL clássica no modo binário. Os desenvolvedores também resolveram o problema de um longo início do processo, chamando-o de modo persistente de distorção, selecionam a função que precisa ser distorcida (por deslocamento dentro do arquivo ou pelo nome, se a função for apresentada na tabela de exportação) e instrumentam-na de forma que possa ser chamada em loop. iniciando assim várias amostras de dados de entrada sem reiniciar o processo. Um artigo interessante apareceu recentemente, no qual os pesquisadores mostraram como encontraram ~ 50 vulnerabilidades com ~ 50 dias usando o winafl. Além disso, quase antes da publicação do artigo no WinAFL, o modo Intel PT também foi adicionado (mais sobre isso mais tarde) - os detalhes estão aqui .
Um leitor avançado / sofisticado pode observar que há modificações em todas as estruturas populares de instrumentação, com exceção de
Frida - na verdade é. A única menção ao uso do Frida com a AFL foi encontrada apenas em
Chizpurfle: um Fuzzer Android da Gray-Box para personalizações de serviços de fornecedores . A versão do AFL com Frida foi realmente útil, pois o Frida suporta bem várias arquiteturas RISC.
Muitos pesquisadores também estão ansiosos pelo lançamento do framework Scorpio DBI do criador de Capstone, Unicorne, Keystone. Com base nessa estrutura, os próprios autores já criaram um fuzzer (Darko) e, segundo eles, o utilizaram com sucesso para difundir dispositivos incorporados. Para obter mais informações, consulte
Digging Deep: Finding 0days in Embedded Systems with Fuzzing Guide Coverage Code .
Modificações baseadas nos recursos de hardware do processadorQuando se trata de modificações de AFL com suporte para os recursos de hardware do processador, isso indica principalmente a possibilidade de codificação de kernel com o código do kernel e, em segundo lugar, uma velocidade de processamento do código mais alta para aplicativos sem código fonte.
E, é claro, antes de tudo, estamos falando sobre recursos de hardware do processador como
Intel PT (Processor Tracing). Que está disponível a partir da 6ª geração de processadores (aproximadamente a partir de 2015). Naturalmente, para usar os seguintes fuzzers, você precisará de hardware com suporte adequado ao Intel PT.
- O WinAFL-IntelPT é uma modificação WinAFL de terceiros na qual a tecnologia Intel PT já é usada no lugar do DynamoRIO.
- O kAFL é um desenvolvimento acadêmico que visa solucionar o problema da cobertura do faseamento do kernel de maneira independente do SO. O que foi resolvido usando o hypervisor e a tecnologia Intel PT. Você pode aprender mais com o whitepaper "kAFL: Feedback assistido por hardware" para o Kernels do SO " .
Conclusão
Como você deve ter notado, este tópico está se desenvolvendo ativamente. Ao mesmo tempo, há muito espaço para a criatividade criar uma nova, interessante e útil modificação da AFL.
Obrigado por sua atenção e felicitações de sucesso!
Co-autor: Nikita Knizhov
PS Graças a toda a equipe do centro de pesquisa por sua ajuda na preparação deste material, sem sua experiência e ajuda, seria impossível preparar uma coisa dessas.