Libc Protections
Last updated
Last updated
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
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 alinhar com 0x8, e em sistemas de 64 bits com 0x0. O recurso de segurança verifica se cada chunk alinha corretamente nesses locais específicos antes de usar um ponteiro de um bin.
A aplicação de alinhamento de chunk em sistemas de 64 bits melhora significativamente a segurança do Malloc ao limitar a colocação de chunks falsos a apenas 1 em 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 difíceis de executar com sucesso.
Ataque Fastbin em __malloc_hook
As novas regras de alinhamento no Malloc também frustram um ataque clássico envolvendo o __malloc_hook
. Anteriormente, os atacantes podiam manipular tamanhos de chunks para sobrescrever este ponteiro de função e ganhar execução de código. Agora, a exigência de alinhamento rigoroso garante que tais manipulações não sejam mais viáveis, fechando uma rota comum de exploração e melhorando a segurança geral.
Mistura de Ponteiros é uma melhoria de segurança usada para proteger ponteiros Fd de fastbin e tcache em operações de gerenciamento de memória. Esta 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 locais de memória diretamente em relação a posições conhecidas (sobrescritas relativas).
O núcleo desta técnica é uma fórmula de ofuscação:
New_Ptr = (L >> 12) XOR P
L é a Localização de Armazenamento do ponteiro.
P é o Ponteiro Fd de fastbin/tcache.
A razão para o deslocamento bit a bit 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 a restrições da arquitetura do sistema. Ao deslocar os bits, a parte previsível é removida da equação, aumentando a aleatoriedade do novo ponteiro misturado e, assim, protegendo contra explorações que dependem da previsibilidade desses bits.
Esse ponteiro misturado aproveita a aleatoriedade existente fornecida pela Randomização de Layout de Espaço de Endereços (ASLR), que randomiza endereços usados por programas para dificultar a previsão do layout de memória de um processo pelos atacantes.
Desmistificar o ponteiro para recuperar o endereço original envolve usar a mesma operação XOR. Aqui, o ponteiro misturado é 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 mistura e desmistificação garante que o sistema possa codificar e decodificar ponteiros de forma eficiente, sem sobrecarga significativa, enquanto aumenta substancialmente a segurança contra ataques que manipulam ponteiros de memória.
A mistura de ponteiros visa prevenir sobrescritas parciais e totais de ponteiros na heap, uma melhoria significativa em segurança. Este recurso impacta técnicas de exploração de várias maneiras:
Prevenção de Sobrescritas Relativas por 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 mistura de ponteiros, tais sobrescritas relativas sem um vazamento da heap agora requerem força bruta, reduzindo drasticamente a probabilidade de sucesso.
Aumento da Dificuldade de Ataques em Tcache Bin/Fastbin: Ataques comuns que sobrescrevem ponteiros de função (como __malloc_hook
) manipulando entradas de fastbin ou tcache são dificultados. Por exemplo, um ataque pode envolver vazar um endereço da LibC, liberar um chunk no bin tcache e, em seguida, sobrescrever o ponteiro Fd para redirecioná-lo para __malloc_hook
para execução de código arbitrário. Com a mistura de ponteiros, esses ponteiros devem ser corretamente misturados, necessitando de um vazamento da heap para manipulação precisa, elevando assim a barreira de exploração.
Requisito de Vazamentos da 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 da heap devido à necessidade de mistura de ponteiros. Isso estende a complexidade de explorar essas áreas, semelhante ao requisito de manipular endereços da LibC.
Vazar Endereços da Heap Torna-se Mais Desafiador: A mistura de ponteiros restringe a utilidade dos ponteiros Fd em fastbin e tcache como fontes para vazamentos de endereços da heap. No entanto, ponteiros em bins não ordenados, pequenos e grandes permanecem não misturados, portanto ainda utilizáveis para vazar endereços. Essa mudança empurra os atacantes a explorar esses bins em busca de informações exploráveis, embora algumas técnicas ainda possam permitir a desmistificação de ponteiros antes de um vazamento, embora com restrições.
Para uma melhor explicação do processo verifique o post original aqui.
A fórmula usada para misturar e desmistificar ponteiros é:
New_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, 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ê efetivamente obtém 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 que você calcule o outro operando. Essa propriedade é usada para deduzir todo o conjunto de bits para P ao XORar sucessivamente conjuntos conhecidos de bits com partes do ponteiro misturado.
Desmistificação Iterativa: O processo é repetido, cada vez usando os novos bits descobertos de P do passo anterior para decodificar o próximo segmento do ponteiro misturado, até que todos os bits sejam recuperados.
Tratamento 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 após o processo.
Você pode encontrar uma implementação deste algoritmo aqui: https://github.com/mdulin2/mangle
A guarda de ponteiro é uma técnica de mitigação de exploração usada no glibc para proteger ponteiros de função armazenados, particularmente aqueles registrados por chamadas de biblioteca como atexit()
. Essa proteção envolve embaralhar os ponteiros XORando-os com um segredo armazenado nos dados da thread (fs:0x30
) e aplicando uma rotação bit a bit. Esse mecanismo visa impedir que atacantes sequestram o fluxo de controle sobrescrevendo ponteiros de função.
Entendendo as Operações da Guarda de Ponteiro: O embaralhamento (mistura) de ponteiros é feito usando o macro PTR_MANGLE
, que XORa o ponteiro com um segredo de 64 bits e, em seguida, realiza uma rotação à esquerda de 0x11 bits. A operação reversa para recuperar o ponteiro original é tratada por PTR_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 misturada de um ponteiro para deduzir o segredo usado para a mistura.
Explorando Textos Conhecidos:
Identificando Ponteiros de Função Fixos: Ao examinar o código-fonte do glibc ou tabelas de ponteiros de função inicializadas (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 misturada da tabela de ponteiros de função, o segredo pode ser calculado girando para trás (rotação à direita) o ponteiro misturado e, em seguida, XORando-o com o endereço da função.
Textos Alternativos: O atacante também pode experimentar misturar ponteiros com valores conhecidos, como 0 ou -1, para ver se esses produzem padrões identificáveis na memória, potencialmente revelando o segredo quando esses padrões são encontrados em dumps de memória.
Aplicação Prática: Após calcular o segredo, um atacante pode manipular ponteiros de maneira controlada, essencialmente contornando a proteção da Guarda de Ponteiro em uma aplicação multithreaded com conhecimento do endereço base da libc e a capacidade de ler locais de memória arbitrários.
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)