Skip to content
KitploitKITPLOIT
FerramentasBlog
Log in
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.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
ExecASLR-ekoparty — Prova de conceito de exploit que contorna a ASLR em CPUs Intel ao abusar do branch target buffer e da execução especulativa para vazar endereços randomizados via canal lateral. | Kitploit
Ferramentas/GitHubGitHub/es0j/execaslr-ekoparty
Análise de VulnerabilidadesExploraçãoSegurança de HardwareAprendizado e EducaçãoRed TeamingAtaque AdversárioExploração de Binários
GitHubes0j/execaslr-ekoparty

ExecASLR-ekoparty

Prova de conceito de exploit que contorna a ASLR em CPUs Intel ao abusar do branch target buffer e da execução especulativa para vazar endereços randomizados via canal lateral.

Ver Repositório
72921há 3 anosRevisado 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

ExecASLR - Abusando de preditores de desvio da Intel para contornar o ASLR

O que é ASLR

A Randomização do Layout do Espaço de Endereçamento é uma mitigação usada para dificultar ataques de corrupção de memória. Em um cenário de vulnerabilidade de buffer overflow, por exemplo, um atacante que tenta fazer um exploit de Return Oriented Programming precisa conhecer os endereços dos gadgets na cadeia. Se o segmento de código do binário explorado é randomizado, então é muito mais difícil para um atacante escolher o endereço correto para o exploit, tornando a exploração inviável.

O exemplo a seguir mostra como um endereço é randomizado:

#include <stdio.h>
void DoNothing();
void (*codePtr)() = DoNothing;

void DoNothing(){}

int main(int argc,char **argv){

    printf("Destination %p\n",codePtr);
    DoNothing();
}


Cada execução o valor é randomizado:

Destination 0x563714256149
Destination 0x556d8e2f1149
Destination 0x5618c8bdd149
Destination 0x55ee623b0149

Os últimos 12 bits 149 são sempre os mesmos, mas a localização da função pode estar aproximadamente em qualquer lugar entre 0x550000000000 e 0x570000000000, o que significa que 29 bits são randomizados, ocupando um espaço de endereçamento possível de 0x200 0000 0000 ou 2,2 TB de tamanho.

Pipeline da CPU

O processamento de cada instrução é uma tarefa árdua. Algumas etapas do processamento de uma única instrução são:

  • Buscar a instrução;
  • decodificar a instrução;
  • Executar operações na Unidade Lógica Aritmética

Para aumentar a vazão de instruções na CPU, cada tarefa da instrução é executada por uma unidade específica do processador. Com todas as unidades trabalhando em paralelo, isso permite que a CPU execute em velocidades de clock muito mais altas; essa é a ideia de um pipeline.

Operação \ ciclo de clock12345
FetchABC
DecodingABC
ExecutionABC

Execução das instruções A, B e C ao longo dos ciclos 1-5. No ciclo 3, por exemplo, as unidades de leitura, decodificação e execução estão simultaneamente ativas

No entanto, as instruções não são completamente independentes umas das outras. Por exemplo, a seguinte sequência:

A. add ax,[bx]
B. jz $+1
C. mov dl,[rsi]  
D. nop

Neste caso, a instrução A no melhor caso só terminará no ciclo 3, na execução. No entanto, a unidade de busca precisa decidir qual é a próxima instrução a ser buscada da memória, se a instrução C (mov dl,[rsi]) deve ser ignorada. Nesse cenário, a CPU tem a opção de esperar a instrução A terminar, o que só acontecerá no terceiro ciclo de clock, para então buscar a instrução correta na memória, se a operação de adição retornar 0, por exemplo:

Operação \ ciclo de clock123456
FetchABD
DecodingABD
ExecutionABD

Isso implica em um atraso no pipeline porque a CPU deve esperar a instrução ser executada. Neste exemplo o atraso é um único ciclo de clock, mas a instrução add ax,[bx] requer uma operação de memória, que, como visto antes, pode levar centenas de ciclos para ser concluída, gerando assim um custo de desempenho significativo no processador.

Uma opção mais rápida seria tentar "adivinhar" o caminho de execução correto. A CPU pode especular se o desvio é tomado ou não. Após esse ponto, a execução continua a partir do caminho especulado e os valores só são confirmados se o caminho for comprovado correto após o término da instrução A. Se o caminho for comprovado errado, os resultados são descartados e o estado é revertido para antes do ponto especulado.

Operação \ ciclo de clock123456
FetchAB(S) C
DecodingAB(S) C
ExecutionAB(S) C

O único problema em reverter o caminho tomado é que o estado microarquitetural da CPU não pode ser revertido. Então, se a CPU especular executar a instrução C (mov dl,[rsi]), o dado apontado por rsi será movido para o cache. Esse efeito pode ser medido posteriormente usando um ataque de canal lateral.

Preditor condicional de 2 bits. https://en.wikipedia.org/wiki/Branch_predictor

Spectre V2 (Injeção de Alvo de Desvio)

Não apenas instruções condicionais devem ser previstas, mas também desvios indiretos. A CPU deve ter um mecanismo para adivinhar os destinos de uma instrução como call [rdi].

A vulnerabilidade Spectre V2 mostra que é possível explorar o preditor indireto para alcançar execução transiente em outros processos: Extraído de https://spectreattack.com/spectre.pdf

Ao colocar uma instrução de chamada no contexto A no mesmo endereço virtual de outra chamada no contexto B, o atacante pode treinar a CPU para executar código em uma posição escolhida pelo atacante no contexto B, em um ataque de reutilização de código, semelhante ao Return Oriented Programming (ROP).

A vítima alvo deve ter um trecho de código conhecido como "spectre gadget" que seja capaz de vazar um segredo usando um ataque de canal lateral. Para um ataque Spectre bem-sucedido, o atacante também deve saber a localização do spectre gadget. Portanto, em ataques usuário-usuário, proteger a vítima com ASLR costumava ser uma mitigação para esse tipo de ataque. No entanto, também existem técnicas para extrair ASLR usando ataques microarquiteturais, como o Jump Over ASLR. Contudo, essa técnica tem algumas limitações sobre a quantidade de bits vazados, pois depende de colisão no preditor direto para contornar o ASLR.

Os mecanismos internos desse preditor são mostrados abaixo:

Extraído de https://spectreattack.com/spectre.pdf

Alguns desses componentes são:

  • O Branch Target Buffer (BTB);
    • O BTB é um componente semelhante a um cache que armazena os destinos para as previsões. O BTB armazena o endereço completo de 64 bits do destino e o número de entradas disponíveis no BTB depende da arquitetura.
  • O Branch History Buffer (BHB);
    • O BHB armazena um "hash" do fluxo de execução recente. Cada instrução de desvio escreve no BHB. Em CPUs Skylake e anteriores, o BHB pode armazenar o contexto dos últimos 29 desvios. No Icelake, o BHB armazena até ~100 desvios. Observe que o BHB usa apenas os 20 bits menos significativos dos desvios para criar o hash, dos quais 12 não são randomizados.
  • O preditor indireto;
    • Usa apenas os 12 bits menos significativos da instrução de desvio indireto para determinar o destino completo de 64 bits. O Exec ASLR vaza o ponteiro de 64 bits do BTB para recuperar completamente os endereços do ASLR.
  • O preditor de desvio direto
    • Usa os 30 bits menos significativos do endereço de origem para prever um valor de 32 bits. A outra metade do endereço é reutilizada da origem. O ataque Jump Over ASLR explora colisões nesse preditor para encontrar um endereço de origem que colida com outro contexto, portanto é limitado a vazar apenas os 30 bits menos significativos do contexto da vítima.

O layout clássico do ataque Spectre V2 se parece com isto:

Baixar ferramenta