11 KiB
Proteções do Libc
Aprenda hacking AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!
Outras maneiras de apoiar o HackTricks:
- Se você deseja ver sua empresa anunciada no HackTricks ou baixar o HackTricks em PDF Confira os PLANOS DE ASSINATURA!
- Adquira o swag oficial PEASS & HackTricks
- Descubra A Família PEASS, nossa coleção exclusiva de NFTs
- Junte-se ao 💬 grupo Discord ou ao grupo telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe seus truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
Aplicação de Alinhamento de Chunk
Malloc aloca memória em agrupamentos de 8 bytes (32 bits) ou 16 bytes (64 bits). Isso significa que o final dos chunks em sistemas de 32 bits deve se alinhar com 0x8, e em sistemas de 64 bits com 0x0. O recurso de segurança verifica se cada chunk se alinha corretamente nessas localizações específicas antes de usar um ponteiro de um bin.
Benefícios de Segurança
A aplicação do alinhamento de chunk em sistemas de 64 bits melhora significativamente a segurança do Malloc ao limitar o posicionamento de chunks falsos para apenas 1 a cada 16 endereços. Isso complica os esforços de exploração, especialmente em cenários onde o usuário tem controle limitado sobre os valores de entrada, tornando os ataques mais complexos e mais difíceis de executar com sucesso.
- Ataque Fastbin no __malloc_hook
As novas regras de alinhamento no Malloc também impedem um ataque clássico envolvendo o __malloc_hook
. Anteriormente, os atacantes podiam manipular tamanhos de chunk para sobrescrever este ponteiro de função e obter execução de código. Agora, o requisito rígido de alinhamento garante que tais manipulações não sejam mais viáveis, fechando uma rota comum de exploração e melhorando a segurança geral.
Ofuscação de Ponteiro em fastbins e tcache
Ofuscação de Ponteiro é um aprimoramento de segurança usado para proteger ponteiros Fd de fastbin e tcache em operações de gerenciamento de memória. Essa técnica ajuda a prevenir certos tipos de táticas de exploração de memória, especificamente aquelas que não requerem informações de memória vazadas ou que manipulam diretamente locais de memória relativos a posições conhecidas (sobrescritas relativas).
O cerne dessa técnica é uma fórmula de ofuscação:
Novo_Ptr = (L >> 12) XOR P
- L é a Localização de Armazenamento do ponteiro.
- P é o Ponteiro Fd de fastbin/tcache real.
A razão para o deslocamento de bits da localização de armazenamento (L) por 12 bits para a direita antes da operação XOR é crítica. Essa manipulação aborda uma vulnerabilidade inerente à natureza determinística dos 12 bits menos significativos dos endereços de memória, que são tipicamente previsíveis devido às restrições da arquitetura do sistema. Ao deslocar os bits, a parte previsível é removida da equação, aumentando a aleatoriedade do novo ponteiro ofuscado e, assim, protegendo contra explorações que dependem da previsibilidade desses bits.
Este ponteiro ofuscado aproveita a aleatoriedade existente fornecida pela Randomização do Layout do Espaço de Endereços (ASLR), que randomiza os endereços usados pelos programas para dificultar que os atacantes prevejam o layout de memória de um processo.
Desofuscar o ponteiro para recuperar o endereço original envolve o uso da mesma operação XOR. Aqui, o ponteiro ofuscado é tratado como P na fórmula e, quando XORado com a localização de armazenamento inalterada (L), resulta na revelação do ponteiro original. Essa simetria na ofuscação e desofuscação garante que o sistema possa codificar e decodificar eficientemente ponteiros sem sobrecarga significativa, ao mesmo tempo em que aumenta substancialmente a segurança contra ataques que manipulam ponteiros de memória.
Benefícios de Segurança
A ofuscação de ponteiros visa prevenir sobrescritas parciais e completas de ponteiros na heap, um aprimoramento significativo em segurança. Este recurso impacta as técnicas de exploração de várias maneiras:
- Prevenção de Sobrescritas Relativas de Bye Byte: Anteriormente, os atacantes podiam alterar parte de um ponteiro para redirecionar chunks da heap para diferentes locais sem conhecer endereços exatos, uma técnica evidente na exploração House of Roman sem vazamento. Com a ofuscação de ponteiros, tais sobrescritas relativas sem um vazamento de heap agora exigem força bruta, reduzindo drasticamente sua probabilidade de sucesso.
- Aumento da Dificuldade de Ataques de Tcache Bin/Fastbin: Ataques comuns que sobrescrevem ponteiros de função (como
__malloc_hook
) manipulando entradas de fastbin ou tcache são prejudicados. Por exemplo, um ataque pode envolver vazar um endereço LibC, liberar um chunk no tcache bin e, em seguida, sobrescrever o ponteiro Fd para redirecioná-lo para__malloc_hook
para execução de código arbitrário. Com a ofuscação de ponteiros, esses ponteiros devem ser corretamente ofuscados, necessitando de um vazamento de heap para manipulação precisa, elevando assim a barreira de exploração. - Necessidade de Vazamentos de Heap em Locais Não-Heap: Criar um chunk falso em áreas não-heap (como a pilha, seção .bss ou PLT/GOT) agora também requer um vazamento de heap devido à necessidade de ofuscação de ponteiros. Isso estende a complexidade de explorar essas áreas, semelhante à necessidade de manipular endereços LibC.
- Vazar Endereços de Heap se Torna Mais Desafiador: A ofuscação de ponteiros restringe a utilidade de ponteiros Fd em fastbin e tcache bins como fontes de vazamento de endereços de heap. No entanto, ponteiros em bins não ordenados, pequenos e grandes permanecem não ofuscados, ainda podendo ser usados para vazar endereços. Essa mudança leva os atacantes a explorar esses bins em busca de informações exploráveis, embora algumas técnicas ainda possam permitir desofuscar ponteiros antes de um vazamento, embora com restrições.
Desofuscar Ponteiros com um Vazamento de Heap
{% hint style="danger" %} Para uma melhor explicação do processo verifique a postagem original daqui. {% endhint %}
Visão Geral do Algoritmo
A fórmula usada para ofuscar e desofuscar ponteiros é:
Novo_Ptr = (L >> 12) XOR P
Onde L é a localização de armazenamento e P é o ponteiro Fd. Quando L é deslocado para a direita por 12 bits, ele expõe os bits mais significativos de P, devido à natureza do XOR, que produz 0 quando os bits são XORados consigo mesmos.
Passos Chave no Algoritmo:
- Vazamento Inicial dos Bits Mais Significativos: Ao XORar o L deslocado com P, você obtém efetivamente os 12 bits superiores de P porque a parte deslocada de L será zero, deixando os bits correspondentes de P inalterados.
- Recuperação dos Bits do Ponteiro: Como o XOR é reversível, conhecer o resultado e um dos operandos permite calcular o outro operando. Essa propriedade é usada para deduzir o conjunto inteiro de bits para P sucessivamente XORando conjuntos conhecidos de bits com partes do ponteiro ofuscado.
- Desofuscação Iterativa: O processo é repetido, cada vez usando os bits de P recém-descobertos da etapa anterior para decodificar o próximo segmento do ponteiro ofuscado, até que todos os bits sejam recuperados.
- Manuseio de Bits Determinísticos: Os últimos 12 bits de L são perdidos devido ao deslocamento, mas são determinísticos e podem ser reconstruídos pós-processo.
Você pode encontrar uma implementação deste algoritmo aqui: https://github.com/mdulin2/mangle
Proteção de Ponteiro
O Pointer Guard é uma técnica de mitigação de exploração usada no glibc para proteger ponteiros de função armazenados, especialmente aqueles registrados por chamadas de biblioteca como atexit()
. Essa proteção envolve embaralhar os ponteiros através de XOR com um segredo armazenado nos dados da thread (fs:0x30
) e aplicando uma rotação bitwise. Esse mecanismo tem como objetivo evitar que atacantes assumam o controle da execução ao sobrescrever ponteiros de função.
Burlando o Pointer Guard com um vazamento
- Compreendendo as Operações do Pointer Guard: O embaralhamento (mangling) dos ponteiros é feito usando a macro
PTR_MANGLE
, que faz XOR do ponteiro com um segredo de 64 bits e então realiza uma rotação à esquerda de 0x11 bits. A operação reversa para recuperar o ponteiro original é tratada porPTR_DEMANGLE
. - Estratégia de Ataque: O ataque é baseado em uma abordagem de texto conhecido, onde o atacante precisa conhecer tanto a versão original quanto a versão embaralhada de um ponteiro para deduzir o segredo usado para o embaralhamento.
- Explorando Textos Conhecidos:
- Identificando Ponteiros de Função Fixos: Ao examinar o código-fonte do glibc ou tabelas de ponteiros de função inicializados (como
__libc_pthread_functions
), um atacante pode encontrar ponteiros de função previsíveis. - Calculando o Segredo: Usando um ponteiro de função conhecido como
__pthread_attr_destroy
e sua versão embaralhada da tabela de ponteiros de função, o segredo pode ser calculado revertendo a rotação (rotação à direita) do ponteiro embaralhado e então fazendo XOR com o endereço da função.
- Textos Conhecidos Alternativos: O atacante também pode experimentar embaralhar ponteiros com valores conhecidos como 0 ou -1 para ver se produzem padrões identificáveis na memória, potencialmente revelando o segredo quando esses padrões são encontrados em despejos de memória.
- Aplicação Prática: Após calcular o segredo, um atacante pode manipular ponteiros de forma controlada, essencialmente burlando a proteção do Pointer Guard em um aplicativo multithread com conhecimento do endereço base do libc e capacidade de ler locais de memória arbitrários.