
O fuzzer de processador x86
: o fuzzer de processador x86
O sandsifter audita processadores x86 em busca de instruções ocultas e bugs de hardware, gerando sistematicamente código de máquina para pesquisar o conjunto de instruções de um processador e monitorando a execução em busca de anomalias. O sandsifter descobriu instruções secretas de processadores de todos os principais fornecedores; bugs de software ubíquos em disassemblers, assemblers e emuladores; falhas em hypervisors empresariais; e bugs de hardware tanto benignos quanto críticos para a segurança em chips x86.
Com a multitude de processadores x86 existentes, o objetivo da ferramenta é permitir que os usuários verifiquem seus próprios sistemas em busca de instruções e bugs ocultos.
Para executar uma auditoria básica no seu processador:
sudo ./sifter.py --unk --dis --len --sync --tick -- -P1 -t

O computador é varrido sistematicamente em busca de instruções anômalas. Na metade superior, você pode ver as instruções que o sandsifter está testando atualmente no processador. Na metade inferior, o sandsifter relata as anomalias que encontra.
A pesquisa levará de algumas horas a alguns dias, dependendo da velocidade e complexidade do seu processador. Quando estiver concluída, resuma os resultados:
./summarize.py data/log

Normalmente, vários milhões de instruções não documentadas serão encontradas no seu processador, mas geralmente se enquadram em um pequeno número de grupos diferentes. Após agrupar as anomalias, a ferramenta de sumarização tenta atribuir cada instrução a uma categoria de problema:
Pressione 'Q' para sair e obter um resumo baseado em texto da varredura do sistema:
Os resultados de uma varredura às vezes podem ser difíceis para as ferramentas classificarem automaticamente, e podem exigir análise manual. Para obter ajuda na análise dos seus resultados, sinta-se à vontade para enviar o arquivo ./data/log para [email protected]. Nenhuma informação pessoal, além da marca, modelo e revisão do processador (de /proc/cpuinfo) está incluída neste log.
A varredura com o sandsifter descobriu recursos de processador não documentados em dezenas de categorias de opcodes, falhas em hypervisors empresariais, bugs em quase todas as principais ferramentas de desmontagem e emulação, e bugs de hardware críticos que abrem vulnerabilidades de segurança no próprio processador.
Detalhes dos resultados podem ser encontrados no whitepaper do projeto.
(TODO: enumeração detalhada dos resultados aqui)
O Sandsifter requer a instalação prévia do disassembler Capstone: http://www.capstone-engine.org/. O Capstone normalmente pode ser instalado com:
sudo apt-get install libcapstone3 libcapstone-dev
sudo pip install capstone
O Sandsifter pode ser construído com:
make
e é então executado com
sudo ./sifter.py --unk --dis --len --sync --tick -- -P1 -t
As flags são passadas para o sifter com --flag, e para o injector com -- -f.
Exemplo:
sudo ./sifter.py --unk --dis --len --sync --tick -- -P1 -t
Flags do sifter:
--len
busca por diferenças de comprimento em todas as instruções (instruções que
executaram de forma diferente do esperado pelo disassembler, ou que não
existiam quando o disassembler as esperava)
--dis
busca por diferenças de comprimento em instruções válidas (instruções que
executaram de forma diferente do esperado pelo disassembler)
--unk
busca por instruções desconhecidas (instruções que o disassembler não
conhece, mas que executam com sucesso)
--ill
o inverso de --unk, busca por desmontagens inválidas (instruções que não
executam com sucesso mas que o disassembler reconhece)
--tick
escreve periodicamente a instrução atual no disco
--save
salva o progresso da pesquisa ao sair
--resume
retoma a pesquisa a partir do último estado salvo
--sync
escreve os resultados da pesquisa no disco à medida que são encontrados
--low-mem
não armazena resultados na memória
Flags do injector:
-b
modo: força bruta
-r
modo: fuzzing aleatório
-t
modo: fuzzing tunelado
-d
modo: fuzzing dirigido externamente
-R
modo de saída bruta
-T
modo de saída de texto
-x
escreve progresso periódico no stderr
-0
permite dereferência nula (requer sudo)
-D
permite prefixos duplicados
-N
sem suporte a bit NX
-s seed
em pesquisa aleatória, valor da semente
-B brute_depth
em pesquisa de força bruta, profundidade máxima de pesquisa
-P max_prefix
número máximo de prefixos a pesquisar
-i instruction
instrução na qual iniciar a pesquisa (inclusive)
-e instruction
instrução na qual terminar a pesquisa (exclusive)
-c core
núcleo no qual realizar a pesquisa
-X blacklist
inclui na lista negra a instrução especificada
-j jobs
número de trabalhos simultâneos para executar
-l range_bytes
número de bytes base de instrução em cada subfaixa
m: Modo - altera o modo de pesquisa (força bruta, aleatório ou tunelado) para o sifter
q: Sair - sai do sifter
p: Pausar - pausa ou retoma a pesquisa
A varredura suporta quatro algoritmos de pesquisa diferentes, que podem ser definidos na linha de comando ou alternados via teclas de atalho.
sudo
Para melhores resultados, a ferramenta deve ser executada como usuário root. Isso é necessário para que o processo possa mapear na memória uma página no endereço 0, o que requer permissões de root. Esta página evita que muitas instruções causem seg-fault em acessos à memória, o que permite uma análise de falhas mais precisa.
Prefixos
A principal limitação para a profundidade de uma pesquisa de instrução é o número de bytes de prefixo a explorar, com cada byte de prefixo adicional aumentando o espaço de pesquisa em cerca de um fator de 10. Limite os bytes de prefixo com a flag -P.
Cores
A interface do sifter é projetada para um terminal de 256 cores. Embora os detalhes variem muito dependendo do seu terminal, isso pode ser aproximadamente feito com:
export TERM='xterm-256color'
Interface Gráfica
A interface assume que o terminal tem pelo menos um determinado tamanho; se a interface não estiver renderizando corretamente, tente aumentar o tamanho do terminal; isso geralmente pode ser feito diminuindo o tamanho da fonte do terminal.
Em alguns casos, pode ser desejável ou necessário executar a ferramenta sem a interface gráfica. Isso pode ser feito executando o injector diretamente:
sudo ./injector -P1 -t -0
Para filtrar os resultados de uma invocação direta do injector, o grep pode ser usado. Por exemplo,
sudo ./injector -P1 -r -0 | grep '\.r' | grep -v sigill
procura instruções para as quais o processador e o disassembler discordaram sobre o comprimento da instrução (grep '.r'), mas a instrução foi executada com sucesso (grep -v sigill).
Fuzzing direcionado
Em muitos casos, é valioso direcionar o fuzzer para um alvo específico. Por exemplo, se você suspeitar que um emulador tem falhas em torno de prefixos 'lock' repetidos (0xf0), você pode direcionar o fuzzer para pesquisar esta região do espaço de instruções com as flags -i e -e:
sudo ./sifter.py --unk --dis --len --sync --tick -- -t -i f0f0 -e f0f1 -D -P15
sandsifter é um esforço de pesquisa de Christopher Domas (@xoreaxeaxeax).
Sistemas legados
Para varredura de sistemas muito antigos (processadores classe i586, sistemas com pouca memória), passe a flag --low-mem para o sifter e a flag -N para o injector:
sudo ./sifter.py --unk --dis --len --sync --tick --low-mem -- -P1 -t -N
Se você observar que suas varreduras estão concluindo muito rapidamente (por exemplo, uma varredura termina em segundos), geralmente é porque essas flags são necessárias para o processador que você está usando.
32 vs. 64 bits
Por padrão, o sandsifter é construído para atingir a arquitetura de bits do sistema operacional hospedeiro. No entanto, algumas instruções têm comportamentos diferentes quando executadas em um processo de 32 bits em comparação com quando executadas em um processo de 64 bits. Para explorar esses cenários, às vezes é valioso executar um sandsifter de 32 bits em um sistema de 64 bits.
Para construir um sandsifter de 32 bits em um sistema de 64 bits, o Capstone deve ser instalado como 32 bits; as instruções para isso podem ser encontradas em http://www.capstone-engine.org/.
Em seguida, o sandsifter deve ser construído para uma arquitetura de 32 bits:
make CFLAGS=-m32
Com isso, o espaço de instruções de 32 bits pode ser explorado em um sistema de 64 bits.