The toddler’s introduction to Heap Exploitation, House of Lore(Part 4.5)
Similarly to other heap exploitation attacks that we saw so far, the idea behind the House of Lore (HoL) is to trick malloc to return a pointer to a memory location which is controlled by the attacker. HoL (ab)uses the way that ptmalloc handles the small bin
entries although the initial post included the large bin
entries too. Besides the fact that the conditions surrounding the House of Lore are quite unique[1], changes in malloc implementation (the introduction of fd_nextsize
and bk_nextsize
) [2] rendered this attack impractical for large bin abuse, while after the tcache
introduction and the additional hardening at the latest glibc versions, even more conditions need to be in place for this attack to be successful.
Beyond its (un)practicality, understanding how this attack works, will help us comprehend how malloc works, and after all… this what really matters.
Before we start, here is the story so far:
- The toddler’s, Heap Exploitation, Introduction (Part 1)
- The toddler’s, Heap exploitation, Introduction (Part 2)
- The toddler’s, Heap exploitation, Overflows (Part 3)
- The toddler’s, Use After Free & Double free (Part 4)
- The toddler’s, FastBin Dup to Stack (Part 4.1)
- The toddler’s, FastBin Dup Consolidate (Part 4.2)
- The toddler’s, Unsafe Unlink(Part 4.3)
- The toddler’s House of Spirit(Part 4.4)
The House of Lore
Sticking with the main idea of the attack, we will force malloc to return a pointer to a stack memory area that we control. This will help us to overwrite the return address of the function where the vulnerability takes place and bypass the stack smash detection by jumping over the canary value. We will investigate the HoL in the context of glibc version 2.23 to avoid the tcache
and gradually, we will add the missing conditions in order to implement this attack for the latest glibc version.
Before we start, here is what you need to know:
- When a chunk is passed to free(), it is first added to the unsorted bin.
- On the next call to malloc, if the memory requirement cannot be satisfied by a smallbin or an unsorted chunk, then the unsorted chunks are put to the appropriate list.
- When a chunk is inserted into the (doubly linked) small bin the fd and bk pointers are updated in order to point to the appropriate nodes.
- As the allocator follows a FIFO rule for this bin, a call to
free
will send the new chunk to the head of the list and a call to malloc will unlink and remove a chunk from the tail:


The attack
Assume that you have an overflow that allows you to overwrite the bk
entry of a N-size chunk so it points to an arbitrary memory location:

Then in order for the attack to take place the allocator needs to perform n calls to a N-sized malloc so the overwritten bk will be reached. Lets see an example from the shellphish’s how2heap repo:
The stack_buffer_1
and stack_buffer_2
at lines 6 and 7 represent two fake chunks which will be allocated in the stack. In line 9 we allocate the victim
chunk which we suppose to control its header data via an overflow. At line 11 the victim_chunk
will point to the header of the victim chunk. The lines 14 to 19 craft the stack_buffer_1
and stack_buffer_2
to look like valid chunks which are linked with the victim chunk. More specifically, line 16 will bypass the malloc’s check at line 3388:

and the code at lines 17,19 will link the fake chunks in a double linked list, thus we’ll have the following:

Line 21 is added to avoid consolidation of the victim chunk with the top chunk. The call to free at line 23 will first move the victim chunk to the unsorted bin thus the next malloc which can’t be satisfied by the unsorted bin will move the victim chunk to the smallbin. The line 28 symbolises the vulnerability which will have as a result the following arrangement:

Since the victim_chunk
is the only node in the smallbin, the first call to malloc at line 31 will return its address to satisfy the allocation, so the subsequent call to malloc at line 33 will return a pointer to the (fake) data part of stack_buffer_1
. As we control the memory location where p4
points to, we can overwrite the return address of the main function (line 37) to point to the entry of the jackpot()
function, thus by running the program we will get a Nice jump d00d
in the output and then the program will exit.
#if USE_TCACHE
The tcache introduction added a couple of additional branches to the smallbin handling flow that have to be bypassed for the attack to be successful. More specifically, malloc will try to stash the rest of the same sized smallbin chunks to the tcache

To overcome these checks the code at shellphish’s repo creates a fake free list and links each node via a fake bk
pointer:
void* fake_freelist[7][4];
for(int i=0; i<6; i++) { fake_freelist[i][3] = fake_freelist[i+1]; }
This will create the following setup:

which will fill the tcache list and exit the loop at line 3927. Finally, the code exhausts the tcache list via a dummy requirement, listed below:
void *dummies[7]; for(int i=0; i<7; i++) dummies[i] = malloc(0x100);
…
…
for(int i=0; i<7; i++) free(dummies[i]);
The whole code is as follows:
[1] https://dl.packetstormsecurity.net/papers/attack/MallocMaleficarum.txt
[2] https://heap-exploitation.dhavalkapil.com/attacks/house_of_lore