(Update 05/2019: Made a note that this method is now patched in
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.
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.
There are some requirements that the adversary must meet:
- A heap overflow vulnerability must exist in the application.
mchunk_sizefield must be reachable by the heap overflow.
- The ability to invoke the memory allocator for an arbitrarily-sized chunk twice, and be able to write arbitrary data to it.
- The ability to leak the address of the
libcbase (in an ASLR-enabled system)
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
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
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 + 256 + PTR_BYTES)) # Allocate another chunk last_slot = ps.alloc(256) # Write data into the last chunk, which should overwrite __malloc_hook ps.write(last_slot, p64(system_addr)) # Invoke malloc with /bin/sh string return ps.try_spawn_shell(binsh_addr, interactive)
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; size = chunksize (victim); if (__glibc_unlikely (size > av->system_mem)) malloc_printerr ("malloc(): corrupted top size");