Categories

glibc Heap Exploitation: House of Force

(Update 05/2019: Made a note that this method is now patched in glibc>=2.29)

The “House of Force” is a glibc heap overflow exploitation technique first named in the archived email “Malloc Maleficarum” by Phantasmal Phantasmagoria, and subsequently a PoC surfaced online in the Phrack magazine.

Vector

The House of Force technique overwrites the top chunk of the heap in order to fabricate a memory allocation that will return an arbitrary memory region. By tampering the size of top chunk to a very large value and allocating a chunk with an attacker-controlled size, the top chunk can be set to a desired arbitrary memory location so that the next allocation from the top chunk will produce a chunk at the desired memory location. This results in a write-what-where condition which the exploit developer may leverage to achieve arbitrary code execution.

Requirements

There are some requirements that the adversary must meet:

1. A heap overflow vulnerability must exist in the application.
2. The top chunk mchunk_size field must be reachable by the heap overflow.
3. The ability to invoke the memory allocator for an arbitrarily-sized chunk twice, and be able to write arbitrary data to it.
4. The ability to leak the address of the libc base (in an ASLR-enabled system)

Example

The vulnerable code begins with one memory allocation. Using the heap overflow vulnerability, we write into the allocated memory space and overflow into the top chunk. The mchunk_size field of the top chunk will be overwritten with an arbitrarily large value (e.g. 0xffffffffffffffff). Since we require control over allocation sizes, we can exploit this by requesting allocations with incredibly large sizes so that our allocations will end up in locations of our own choosing.

The first step in exploiting a heap overflow would be to leak some libc address. We have a memory address conveniently planted in the PoC which gives us the address of __malloc_hook, from which we may easily calculate the address of any desired libc function (since we also know the version of libc used). This leak gives for a more reliable exploit in the face of ASLR and PIC. Additionally, the stack is unused and no shellcode is injected, so stack canaries/protection and DEP are moot here.

For arbitrary code execution, we overwrite the .got.plt entry of __malloc_hook with system. We can also calculate the position of the /bin/sh string in libc using the leaked address. Now that we have changed the .got.plt entry, every time malloc() is invoked, system will be called instead of __malloc_hook and the first argument to system will be the first argument to malloc().

def exploit_house_of_force(ps, leaked_addr, system_addr, binsh_addr, interactive=False):
# Allocate a chunk
first_slot = ps.alloc(256)
# Overwrite mchunk_size field of the top chunk
ps.write(first_slot, "\xff"*(256 + 2*PTR_BYTES))
# Allocate a chunk large enough so that it ends before __malloc_hook,
# referencing the leaked libc address minus the 256-byte chunk that
# we allocated earlier.
second_slot = ps.alloc(leaked_addr - 2*PTR_BYTES - (slots[0] + 256 + PTR_BYTES))
# Allocate another chunk
last_slot = ps.alloc(256)
# Write data into the last chunk, which should overwrite __malloc_hook
return ps.try_spawn_shell(binsh_addr, interactive)
An mchunk_size field check for the top chunk was implemented in glibc>=2.29 by making sure it is sane (no more than the arena heap size), effectively killing this exploit mechanism.
victim = av->top;
malloc_printerr ("malloc(): corrupted top size");