Advanced Heap Exploitation: House of Mind & House of Orange

Featherine

Introduction

In this post, I will introduce the mechanism of House of Mind and House of Orange. I will use similar code in [1] to demonstrate the memory layout in House of Orange. For House of Mind, I will give an explanation on it works based on the source code of libc.

House of Orange

To put it simple, House of Orange provides an implicit way to trigger _int_free in exploitation. It takes advantage of the following code of sysmalloc to trigger _int_free implicitly.

if (old_size >= MINSIZE)
{
    set_head (chunk_at_offset (old_top, old_size), (2 * SIZE_SZ) | PREV_INUSE);
    set_foot (chunk_at_offset (old_top, old_size), (2 * SIZE_SZ));
    set_head (old_top, old_size | PREV_INUSE | NON_MAIN_ARENA);
    _int_free (av, old_top, 1);
}

However, to trigger the implicit deallocation we have to satisfy the following two conditions as below.

old_top = av->top;
old_size = chunksize (old_top);
old_end = (char *) (chunk_at_offset (old_top, old_size));

assert ((old_top == initial_top (av) && old_size == 0) ||
          ((unsigned long) (old_size) >= MINSIZE &&
           prev_inuse (old_top) &&
           ((unsigned long) old_end & (pagesize - 1)) == 0));

assert ((unsigned long) (old_size) < (unsigned long) (nb + MINSIZE));

To summarise, there are two constraints on House of Orange.
1. The size of top chunk has to be less than nb + MINSIZE.
2. One of the two conditions has to be satisfied:
2.1 The top chunk is at unsorted bin and size of top chunk is 0.
2.2 Size of chunk is larger than MINSIZE, P bit of top chunk is set and end of top chunk is page aligned.
In House of Orange, we try to satisfy 1 and 2.2 to trigger _int_free.

To demonstrate how House of Orange work, we use the following code to demonstrate the memory layout manipulation.



//Memory layout after corrupting the metadata of top chunk
(gdb) x/8gx 0x602000
0x602000:	0x0000000000000000	0x0000000000000401
0x602010:	0x0000000000000000	0x0000000000000000
0x602020:	0x0000000000000000	0x0000000000000000
0x602030:	0x0000000000000000	0x0000000000000000
(gdb) x/8gx 0x602400
0x602400:	0x0000000000000000	0x0000000000000c01
0x602410:	0x0000000000000000	0x0000000000000000
0x602420:	0x0000000000000000	0x0000000000000000
0x602430:	0x0000000000000000	0x0000000000000000
0x7ffff7dd3b00 <main_arena>:	0x0000000100000000	0x0000000000000000
0x7ffff7dd3b10 <main_arena+16>:	0x0000000000000000	0x0000000000000000
0x7ffff7dd3b20 <main_arena+32>:	0x0000000000000000	0x0000000000000000
0x7ffff7dd3b30 <main_arena+48>:	0x0000000000000000	0x0000000000000000
0x7ffff7dd3b40 <main_arena+64>:	0x0000000000000000	0x0000000000000000
0x7ffff7dd3b50 <main_arena+80>:	0x0000000000000000	0x0000000000602400
0x7ffff7dd3b60 <main_arena+96>:	0x0000000000000000	0x00007ffff7dd3b58
0x7ffff7dd3b70 <main_arena+112>:	0x00007ffff7dd3b58	0x00007ffff7dd3b68
0x7ffff7dd3b80 <main_arena+128>:	0x00007ffff7dd3b68	0x00007ffff7dd3b78

//Memory layout after triggering the implicit free.
(gdb) x/8gx 0x602400
0x602400:	0x0000000000000000	0x0000000000000be1
0x602410:	0x00007ffff7dd3b58	0x00007ffff7dd3b58
0x602420:	0x0000000000000000	0x0000000000000000
0x602430:	0x0000000000000000	0x0000000000000000
0x7ffff7dd3b00 <main_arena>:	0x0000000100000000	0x0000000000000000
0x7ffff7dd3b10 <main_arena+16>:	0x0000000000000000	0x0000000000000000
0x7ffff7dd3b20 <main_arena+32>:	0x0000000000000000	0x0000000000000000
0x7ffff7dd3b30 <main_arena+48>:	0x0000000000000000	0x0000000000000000
0x7ffff7dd3b40 <main_arena+64>:	0x0000000000000000	0x0000000000000000
0x7ffff7dd3b50 <main_arena+80>:	0x0000000000000000	0x0000000000624010
0x7ffff7dd3b60 <main_arena+96>:	0x0000000000000000	0x0000000000602400
0x7ffff7dd3b70 <main_arena+112>:	0x0000000000602400	0x00007ffff7dd3b68
0x7ffff7dd3b80 <main_arena+128>:	0x00007ffff7dd3b68	0x00007ffff7dd3b78

From the memory dump above, we can see that the top chunk is inserted into the unsorted bin after the second time of malloc.

House of Mind

House of Mind is the only techniques that exploits the A bit of a chunk. It takes advantage of the following code of __libc_free of libc.
ar_ptr = arena_for_chunk (p);
_int_free (ar_ptr, p, 0);

#define heap_for_ptr(ptr) ((heap_info *) ((unsigned long) (ptr) & ~(HEAP_MAX_SIZE – 1)))
#define arena_for_chunk(ptr) (chunk_main_arena (ptr) ? &main_arena : heap_for_ptr (ptr)->ar_ptr)
#define chunk_main_arena(p) (((p)->mchunk_size & NON_MAIN_ARENA) == 0)
[/code]
If the attacker is able to modify the A bit of a chunk, he can forge a arena accordingly and set fake bins in the next.

Then the attacker may use the following code in malloc_consolidate to do the same thing as unsorted bin attack and use similar techniques introduced in FSOP to pwn a shell.

first_unsorted = unsorted_bin->fd;
unsorted_bin->fd = p;
first_unsorted->bk = p;

Conclusion

In this post, I give a simple explanation on House of Mind and House of Orange. Those two techniques can always be combined with other exploitation techniques to get a shell in the end.

Reference

[1] https://github.com/shellphish/how2heap

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.