House of Orange

Apoie o HackTricks

Informações Básicas

Código

Objetivo

  • Abusar da função malloc_printerr

Requisitos

  • Sobrescrever o tamanho do top chunk

  • Vazamentos de libc e heap

Contexto

Algumas informações necessárias dos comentários deste exemplo:

A questão é que, em versões mais antigas da libc, quando a função malloc_printerr era chamada, ela iterava por uma lista de estruturas _IO_FILE armazenadas em _IO_list_all, e realmente executava um ponteiro de instrução nessa estrutura. Este ataque irá forjar uma estrutura _IO_FILE falsa que escreveremos em _IO_list_all, e causará a execução de malloc_printerr. Então ele irá executar qualquer endereço que tivermos armazenado na tabela de saltos das estruturas _IO_FILE, e conseguiremos a execução de código

Ataque

O ataque começa conseguindo o top chunk dentro do unsorted bin. Isso é alcançado chamando malloc com um tamanho maior que o tamanho atual do top chunk, mas menor que mmp_.mmap_threshold (padrão é 128K), o que de outra forma acionaria a alocação mmap. Sempre que o tamanho do top chunk é modificado, é importante garantir que o top chunk + seu tamanho esteja alinhado à página e que o bit prev_inuse do top chunk esteja sempre definido.

Para obter o top chunk dentro do unsorted bin, aloque um chunk para criar o top chunk, altere o tamanho do top chunk (com um estouro no chunk alocado) para que top chunk + tamanho esteja alinhado à página com o bit prev_inuse definido. Em seguida, aloque um chunk maior que o novo tamanho do top chunk. Note que free nunca é chamado para colocar o top chunk no unsorted bin.

O antigo top chunk agora está no unsorted bin. Supondo que podemos ler dados dentro dele (possivelmente devido a uma vulnerabilidade que também causou o estouro), é possível vazar endereços da libc a partir dele e obter o endereço de _IO_list_all.

Um ataque ao unsorted bin é realizado abusando do estouro para escrever topChunk->bk->fwd = _IO_list_all - 0x10. Quando um novo chunk é alocado, o antigo top chunk será dividido, e um ponteiro para o unsorted bin será escrito em _IO_list_all.

O próximo passo envolve reduzir o tamanho do antigo top chunk para caber em um small bin, especificamente definindo seu tamanho para 0x61. Isso serve a dois propósitos:

  1. Inserção no Small Bin 4: Quando malloc percorre o unsorted bin e vê este chunk, ele tentará inseri-lo no small bin 4 devido ao seu tamanho pequeno. Isso faz com que o chunk acabe na cabeça da lista do small bin 4, que é a localização do ponteiro FD do chunk de _IO_list_all já que escrevemos um endereço próximo em _IO_list_all via o ataque ao unsorted bin.

  2. Desencadeando uma Verificação de Malloc: Essa manipulação de tamanho do chunk fará com que malloc execute verificações internas. Quando ele verifica o tamanho do chunk falso à frente, que será zero, ele desencadeia um erro e chama malloc_printerr.

A manipulação do small bin permitirá controlar o ponteiro à frente do chunk. A sobreposição com _IO_list_all é usada para forjar uma estrutura fake _IO_FILE. A estrutura é cuidadosamente elaborada para incluir campos-chave como _IO_write_base e _IO_write_ptr definidos para valores que passam verificações internas na libc. Além disso, uma tabela de saltos é criada dentro da estrutura falsa, onde um ponteiro de instrução é definido para o endereço onde um código arbitrário (por exemplo, a função system) pode ser executado.

Para resumir a parte restante da técnica:

  • Reduza o Antigo Top Chunk: Ajuste o tamanho do antigo top chunk para 0x61 para encaixá-lo em um small bin.

  • Configure a Estrutura Fake _IO_FILE: Sobreponha o antigo top chunk com a estrutura fake _IO_FILE e defina os campos apropriadamente para sequestrar o fluxo de execução.

O próximo passo envolve forjar uma estrutura fake _IO_FILE que se sobrepõe ao antigo top chunk atualmente no unsorted bin. Os primeiros bytes desta estrutura são cuidadosamente elaborados para incluir um ponteiro para um comando (por exemplo, "/bin/sh") que será executado.

Campos-chave na estrutura fake _IO_FILE, como _IO_write_base e _IO_write_ptr, são definidos para valores que passam verificações internas na libc. Além disso, uma tabela de saltos é criada dentro da estrutura fake, onde um ponteiro de instrução é definido para o endereço onde um código arbitrário pode ser executado. Tipicamente, este seria o endereço da função system ou outra função que pode executar comandos shell.

O ataque culmina quando uma chamada para malloc aciona a execução do código através da estrutura _IO_FILE manipulada. Isso permite a execução de código arbitrário, resultando tipicamente em um shell sendo aberto ou outra carga maliciosa sendo executada.

Resumo do Ataque:

  1. Configure o top chunk: Aloque um chunk e modifique o tamanho do top chunk.

  2. Force o top chunk para o unsorted bin: Aloque um chunk maior.

  3. Vaze endereços da libc: Use a vulnerabilidade para ler do unsorted bin.

  4. Execute o ataque ao unsorted bin: Escreva em _IO_list_all usando um estouro.

  5. Reduza o antigo top chunk: Ajuste seu tamanho para encaixá-lo em um small bin.

  6. Configure uma estrutura fake _IO_FILE: Forje uma estrutura de arquivo fake para sequestrar o fluxo de controle.

  7. Desencadeie a execução de código: Aloque um chunk para executar o ataque e executar código arbitrário.

Esta abordagem explora mecanismos de gerenciamento de heap, vazamentos de informações da libc e estouros de heap para alcançar a execução de código sem chamar diretamente free. Ao elaborar cuidadosamente a estrutura fake _IO_FILE e colocá-la na localização correta, o ataque pode sequestrar o fluxo de controle durante operações padrão de alocação de memória. Isso permite a execução de código arbitrário, potencialmente resultando em um shell ou outras atividades maliciosas.

Referências

Suporte ao HackTricks

Last updated