AddressSanitizer (ASan)
O AddressSanitizer (ASan) é uma ferramenta de detecção de erros de memória amplamente adotada, usada extensivamente durante testes de software, particularmente em fuzzing. Ela ajuda a detectar bugs de corrupção de memória que poderiam passar despercebidos, como estouros de buffer, erros de uso-após-liberação e outras violações de segurança de memória.
Visão Geral
O ASan é uma prática padrão em fuzzing devido à sua eficácia na identificação de vulnerabilidades de memória. Ele instrumenta o código em tempo de compilação para rastrear alocações e acessos de memória, detectando operações ilegais em tempo de execução.
Conceitos Chave
| Conceito | Descrição |
|---|---|
| Instrumentação | O ASan adiciona verificações em tempo de execução às operações de memória durante a compilação |
| Memória Sombra | Mapeia 20 TB de memória virtual para rastrear o estado das alocações |
| Custo de Desempenho | Aproximadamente 2 a 4x de lentidão em comparação com código não instrumentado |
| Escopo de Detecção | Encontra estouros de buffer, uso-após-liberação, dupla liberação e vazamentos de memória |
Quando Aplicar
Aplique esta técnica quando:
- Fuzzar código C/C++ para vulnerabilidades de segurança de memória
- Testar código Rust com blocos inseguros
- Depurar falhas relacionadas à corrupção de memória
- Executar testes unitários onde erros de memória são suspeitos
Pule esta técnica quando:
- Executar código em produção (ASan pode reduzir a segurança)
- A plataforma for Windows ou macOS (suporte limitado ao ASan)
- A sobrecarga de desempenho for inaceitável para seu caso de uso
- Fuzzar linguagens seguras puras sem FFI (ex.: Go puro, Java puro)
Referência Rápida
| Tarefa | Comando/Exemplo |
|---|---|
| Habilitar ASan (Clang/GCC) | -fsanitize=address |
| Habilitar verbosidade | ASAN_OPTIONS=verbosity=1 |
| Desabilitar detecção de vazamentos | ASAN_OPTIONS=detect_leaks=0 |
| Forçar aborto em erro | ASAN_OPTIONS=abort_on_error=1 |
| Múltiplas opções | ASAN_OPTIONS=verbosity=1:abort_on_error=1 |
Passo a Passo
Passo 1: Compilar com ASan
Compile e linke seu código com a flag -fsanitize=address:
clang -fsanitize=address -g -o meu_programa meu_programa.c
A flag -g é recomendada para obter melhores rastreamentos de pilha quando o ASan detecta erros.
Passo 2: Configurar Opções do ASan
Defina a variável de ambiente ASAN_OPTIONS para configurar o comportamento do ASan:
export ASAN_OPTIONS=verbosity=1:abort_on_error=1:detect_leaks=0
Passo 3: Executar Seu Programa
Execute o binário instrumentado com ASan. Quando erros de memória forem detectados, o ASan imprimirá relatórios detalhados:
./meu_programa
Passo 4: Ajustar Limites de Memória do Fuzzer
O ASan requer aproximadamente 20 TB de memória virtual. Desabilite as restrições de memória do fuzzer:
- libFuzzer:
-rss_limit_mb=0 - AFL++:
-m none
Padrões Comuns
Padrão: Integração Básica com ASan
Caso de Uso: Configuração padrão de fuzzing com ASan
Antes:
clang -o alvo_fuzz alvo_fuzz.c
./alvo_fuzz
Depois:
clang -fsanitize=address -g -o alvo_fuzz alvo_fuzz.c
ASAN_OPTIONS=verbosity=1:abort_on_error=1 ./alvo_fuzz
Padrão: ASan com Testes Unitários
Caso de Uso: Habilitar ASan para suíte de testes unitários
Antes:
gcc -o suite_teste suite_teste.c -lcheck
./suite_teste
Depois:
gcc -fsanitize=address -g -o suite_teste suite_teste.c -lcheck
ASAN_OPTIONS=detect_leaks=1 ./suite_teste
Uso Avançado
Dicas e Truques
| Dica | Por Que Ajuda |
|---|---|
Use a flag -g | Fornece rastreamentos de pilha detalhados para depuração |
Defina verbosity=1 | Confirma que o ASan está habilitado antes de o programa iniciar |
| Desabilite detecção de vazamentos durante fuzzing | A detecção de vazamentos não causa falhas imediatas, poluindo a saída |
Habilite abort_on_error=1 | Alguns fuzzers exigem abort() em vez de _exit() |
Entendendo os Relatórios do ASan
Quando o ASan detecta um erro de memória, ele imprime um relatório detalhado incluindo:
- Tipo de erro: Estouro de buffer, uso-após-liberação, etc.
- Rastreamento de pilha: Onde o erro ocorreu
- Rastreamentos de alocação/desalocação: Onde a memória foi alocada/liberada
- Mapa de memória: Estado da memória sombra ao redor do erro
Exemplo de relatório do ASan:
==12345==ERROR: AddressSanitizer: heap-buffer-overflow no endereço 0x60300000eff4 no pc 0x00000048e6a3
READ de tamanho 4 em 0x60300000eff4 thread T0
#0 0x48e6a2 in main /caminho/para/arquivo.c:42
Combinando Sanitizers
O ASan pode ser combinado com outros sanitizers para detecção abrangente:
clang -fsanitize=address,undefined -g -o alvo_fuzz alvo_fuzz.c
Considerações Específicas por Plataforma
Linux: Suporte completo ao ASan com melhor desempenho macOS: Suporte limitado, alguns recursos podem não funcionar Windows: Suporte experimental, não recomendado para fuzzing em produção
Anti-Padrões
| Anti-Padrão | Problema | Abordagem Correta |
|---|---|---|
| Usar ASan em produção | Pode tornar aplicações menos seguras | Use ASan apenas para testes |
| Não desabilitar limites de memória | O fuzzer pode matar o processo devido a 20 TB de memória virtual | Defina -rss_limit_mb=0 ou -m none |
| Ignorar relatórios de vazamento | Vazamentos de memória indicam problemas de gerenciamento de recursos | Revise relatórios de vazamento no final da campanha de fuzzing |
Orientações Específicas por Ferramenta
libFuzzer
Compile com ambos fuzzer e sanitizer de endereço:
clang++ -fsanitize=fuzzer,address -g harness.cc -o fuzz
Execute com RSS ilimitado:
./fuzz -rss_limit_mb=0
Dicas de integração:
- Sempre combine
-fsanitize=fuzzercom-fsanitize=address - Use
-gpara rastreamentos de pilha detalhados em relatórios de falha - Considere
ASAN_OPTIONS=abort_on_error=1para melhor tratamento de falhas
Veja: libFuzzer: AddressSanitizer
AFL++
Use a variável de ambiente AFL_USE_ASAN:
AFL_USE_ASAN=1 afl-clang-fast++ -g harness.cc -o fuzz
Execute com memória ilimitada:
afl-fuzz -m none -i diretorio_entrada -o diretorio_saida ./fuzz
Dicas de integração:
AFL_USE_ASAN=1adiciona automaticamente as flags de compilação adequadas- Use
-m nonepara desabilitar o limite de memória do AFL++ - Considere
AFL_MAP_SIZEpara programas com grandes mapas de cobertura
Veja: AFL++: AddressSanitizer
cargo-fuzz (Rust)
Use a flag --sanitizer=address:
cargo fuzz run alvo_fuzz --sanitizer=address
Ou configure em fuzz/Cargo.toml:
[profile.release]
opt-level = 3
debug = true
Dicas de integração:
- ASan é útil para fuzzing de código Rust inseguro ou limites FFI
- Código Rust seguro pode não se beneficiar tanto (o compilador já previne muitos erros)
- Foque em blocos inseguros, ponteiros brutos e ligações com bibliotecas C
Veja: cargo-fuzz: AddressSanitizer
honggfuzz
Compile com ASan e linke com honggfuzz:
honggfuzz -i diretorio_entrada -o diretorio_saida -- ./alvo_fuzz_asan
Compile o alvo:
hfuzz-clang -fsanitize=address -g alvo.c -o alvo_fuzz_asan
Dicas de integração:
- honggfuzz funciona bem com ASan sem configuração adicional
- Use modo orientado por feedback para melhor cobertura com sanitizers
- Monitore o uso de memória, pois o ASan aumenta o consumo de memória
Solução de Problemas
| Problema | Causa | Solução |
|---|---|---|
| Fuzzer mata processo imediatamente | Limite de memória muito baixo para 20 TB de memória virtual do ASan | Use -rss_limit_mb=0 (libFuzzer) ou -m none (AFL++) |
| "ASan runtime not initialized" | Ordem de linking errada ou runtime ausente | Garanta que -fsanitize=address seja usado tanto na compilação quanto no linking |
| Relatórios de vazamento poluem saída | LeakSanitizer habilitado por padrão | Defina ASAN_OPTIONS=detect_leaks=0 |
| Baixo desempenho (>4x lentidão) | Modo debug ou build não otimizado | Compile com -O2 ou -O3 junto com -fsanitize=address |
| ASan não detecta bugs óbvios | Binário não instrumentado | Verifique com ASAN_OPTIONS=verbosity=1 se o ASan imprime informações de inicialização |
| Falsos positivos | Conflitos de interceptadores | Consulte o FAQ do ASan para problemas conhecidos com bibliotecas específicas |
Habilidades Relacionadas
Ferramentas Que Usam Esta Técnica
| Habilidade | Como Aplica |
|---|---|
| libfuzzer | Compile com -fsanitize=fuzzer,address para fuzzing integrado com detecção de erros de memória |
| aflpp | Use a variável de ambiente AFL_USE_ASAN=1 durante a compilação |
| cargo-fuzz | Use a flag --sanitizer=address para habilitar ASan para alvos de fuzzing Rust |
| honggfuzz | Compile o alvo com -fsanitize=address para fuzzing instrumentado com ASan |
Técnicas Relacionadas
| Habilidade | Relação |
|---|---|
| undefined-behavior-sanitizer | Frequentemente usado junto com ASan para detecção abrangente de bugs (comportamento indefinido + erros de memória) |
| fuzz-harness-writing | Harnesses devem ser projetados para lidar com falhas detectadas pelo ASan e evitar falsos positivos |
| coverage-analysis | O fuzzing guiado por cobertura ajuda a acionar caminhos de código onde o ASan pode detectar erros de memória |
Recursos
Recursos Externos Principais
AddressSanitizer no Google Sanitizers Wiki
A documentação oficial do ASan cobre:
- Algoritmo e detalhes de implementação
- Lista completa de tipos de erro detectados
- Características de desempenho e sobrecarga
- Comportamento específico por plataforma
- Limitações e incompatibilidades conhecidas
Flags de configuração comuns compartilhadas por todos os sanitizers:
verbosity: Controla o nível de saída de diagnósticolog_path: Redireciona a saída do sanitizer para arquivossymbolize: Habilita/desabilita resolução de símbolos em relatóriosexternal_symbolizer_path: Usa um simbolizador personalizado
Opções de configuração específicas do ASan:
detect_leaks: Controla a detecção de vazamentos de memóriaabort_on_error: Chamaabort()vs_exit()em caso de errodetect_stack_use_after_return: Detecta bugs de uso-após-retorno na pilhacheck_initialization_order: Encontra bugs de ordem de inicialização
Pegadinhas e soluções comuns:
- Problemas de ordem de linking
- Conflitos com outras ferramentas
- Problemas específicos de plataforma
- Dicas para ajuste de desempenho
Documentação do AddressSanitizer para Clang
Orientações específicas para Clang:
- Flags e opções de compilação
- Interação com outros recursos do Clang
- Plataformas e arquiteturas suportadas
Opções de Instrumentação do GCC
Documentação específica do ASan para GCC:
- Flags e comportamento específicos do GCC
- Diferenças da implementação do Clang
- Suporte de plataforma no GCC
AddressSanitizer: A Fast Address Sanity Checker (Artigo USENIX)
Artigo de pesquisa original com detalhes técnicos:
- Algoritmo de memória sombra
- Requisitos de memória virtual (historicamente 16 TB, agora ~20 TB)
- Benchmarks de desempenho
- Decisões de design e compensações