💀 Expert

Heap Exploitation

Heap exploitation targets the dynamic memory allocator (like malloc/free in C). It is generally more complex than stack-based exploitation due to the non-linear nature of heap management and the complexity of modern allocators like glibc's ptmalloc.

Allocator Basics

When a program requests memory (`malloc`), the allocator finds a suitable chunk. When freed (`free`), the chunk is added to a list of free chunks (bins) for reuse.

Chunks and Bins

Memory on the heap is managed in chunks. Each chunk has metadata (size, flags) preceding the user data. Free chunks are organized into lists called bins based on their size and usage:

  • Fastbins: Small chunks, LIFO (Last-In, First-Out), single-linked list. Fast but less secure.
  • Tcache (Thread Local Cache): Very fast, per-thread bin introduced in newer glibc. Very exploitable (no locking, minimal checks).
  • Unsorted Bin: Recently freed chunks that haven't been sorted into specific bins yet.
  • Small/Large Bins: Standard bins for other sizes.

Common Vulnerabilities

Use-After-Free (UAF)

Occurs when a program continues to use a pointer after the memory it points to has been freed. If the attacker can allocate a new object in that freed space, they can control the data the dangling pointer references.

Double Free

Freeing the same chunk twice can corrupt the allocator's internal structures (like the fastbin or tcache linked list), leading to arbitrary write primitives or overlapping chunks.

Heap Grooming (Feng Shui)

Manipulating the heap layout by carefully allocating and freeing chunks to set up the heap in a predictable state for exploitation.

Example: Use-After-Free Walkthrough

Consider a `User` struct with a function pointer.

c

struct User {
    char name[16];
    void (*greet)(); // Function pointer at offset 16
};
  
  1. Allocation: Program allocates `u1` (size 24).
    u1 = malloc(sizeof(User));
  2. Free: Program frees `u1`, but keeps the pointer.
    free(u1);
    The chunk is added to a bin (e.g., tcache).
  3. Reallocation (The Attack): Attacker triggers an allocation of the same size. The allocator returns the same chunk that `u1` points to.
    char *evil = malloc(24);
  4. Overwrite: Attacker writes data to `evil`. Since `evil` and `u1` point to the same memory, `u1`'s data is overwritten.
    strcpy(evil, "AAAA...[Address of system]");
  5. Trigger: Program calls `u1->greet()`.
    u1->greet();
    Instead of the greeting function, it jumps to the address the attacker wrote (e.g., `system`).

Tools

  • pwndbg / GEF: GDB plugins essential for visualizing the heap state, bins, and chunks.
  • libheap: Python library for examining glibc heap structures.