Skip to main content

Overview

The how2heap repository supports multiple glibc versions, allowing you to learn and test heap exploitation techniques across different environments. Each technique is verified to work on corresponding Ubuntu releases that ship with specific glibc versions.
We use Ubuntu’s libc releases as the gold standard. Each technique is verified to work on corresponding Ubuntu releases.

Supported glibc Versions

The repository currently supports the following glibc versions:
  • 2.23 - Ubuntu 16.04 LTS (Xenial)
  • 2.24 - Ubuntu 16.10 (Yakkety)
  • 2.27 - Ubuntu 18.04 LTS (Bionic)
  • 2.31 - Ubuntu 20.04 LTS (Focal)
  • 2.32 - Debian Bullseye / Ubuntu 20.10
  • 2.33 - Ubuntu 21.04
  • 2.34 - Ubuntu 21.10
  • 2.35 - Ubuntu 22.04 LTS (Jammy)
  • 2.36 - Debian Bookworm
  • 2.37 - Experimental
  • 2.38 - Debian Testing
  • 2.39 - Latest stable
  • 2.40 - Development
  • 2.41 - Latest development
Techniques are organized in version-specific directories (glibc_<version>/) to accommodate patches and mitigations introduced in each version.

Testing with Specific Versions

There are two primary approaches to testing heap exploitation techniques with specific glibc versions:

Method 1: Using System libc (Quick Setup)

This is the fastest way to get started. It compiles binaries using your system’s installed libc.
git clone https://github.com/shellphish/how2heap
cd how2heap
make clean base
./malloc_playground
This method links binaries with your system libc. If you want to test with other libc versions, use Method 2 or Method 3.
This method links binaries directly with the target libc version, avoiding symbol versioning issues.
git clone https://github.com/shellphish/how2heap
cd how2heap
H2H_USE_SYSTEM_LIBC=N make v2.23
What this does:
  • Downloads and sets up the specified glibc version
  • Links all binaries against the target libc
  • Includes debug symbols for easier debugging
  • Allows testing any libc version on your host machine
Replace 2.23 with any supported version (2.23, 2.27, 2.31, 2.35, 2.39, etc.)

Method 3: Docker-Based Approach

This uses Docker containers to compile binaries inside an old Ubuntu environment, ensuring compatibility with the target libc version.
git clone https://github.com/shellphish/how2heap
cd how2heap

# Prepare the target binary
make base
./glibc_run.sh 2.30 ./malloc_playground -d -p
Verify the setup:
# Check the RUNPATH
readelf -d -W malloc_playground | grep RUNPATH

# Check the interpreter
readelf -l -W malloc_playground | grep interpreter

# Debug with correct symbols
gdb -q -ex "start" ./malloc_playground

Using H2H_USE_SYSTEM_LIBC

The H2H_USE_SYSTEM_LIBC environment variable controls which compilation method is used:
ValueBehavior
Y (default)Uses your system’s installed libc
NDownloads and links against specific glibc version
Examples:
# Use system libc (fast, but limited to your system version)
make v2.35

# Download and link with glibc 2.35 (slower first time, more flexible)
H2H_USE_SYSTEM_LIBC=N make v2.35

Version-Specific Compilation

The Makefile provides targets for each supported version:
# Build all techniques for glibc 2.23
make v2.23

# Build all techniques for glibc 2.27
make v2.27

# Build all techniques for glibc 2.35
make v2.35

# Build all techniques for glibc 2.39
make v2.39

# Build all techniques for glibc 2.41
make v2.41

Testing Techniques

You can automatically test all techniques for a specific version:
# Test all glibc 2.39 techniques
make test version=2.39
This will run each technique up to 20 times to account for ASLR and randomization.

Docker vs Native Approach

Docker Approach

Advantages:
  • Guarantees environment compatibility
  • Isolated from host system
  • Can use old Ubuntu versions
  • No conflicts with system libraries
Disadvantages:
  • Requires Docker installation
  • Slower build times
  • Additional complexity
  • Larger disk space usage

Native Approach (H2H_USE_SYSTEM_LIBC=N)

Advantages:
  • Faster compilation
  • Direct debugging with gdb
  • Includes debug symbols
  • Works on any host system
  • No Docker required
Disadvantages:
  • May encounter symbol versioning issues
  • Requires handling multiple libc versions
  • First download can be slow
For most users, the native approach with H2H_USE_SYSTEM_LIBC=N is recommended. It provides the best balance of speed, flexibility, and debugging capability.

Prerequisites

Before compiling techniques, ensure you have the required packages:
# Required packages
sudo apt-get install patchelf zstd wget build-essential make

# Ensure python is available
sudo ln -s /usr/bin/python3 /usr/bin/python

Troubleshooting

Symbol Versioning Issues

If you encounter symbol versioning errors when using LD_PRELOAD:
# Use H2H_USE_SYSTEM_LIBC=N to link directly
H2H_USE_SYSTEM_LIBC=N make v2.35

Missing libc Version

If a specific libc version is not available:
# Update the glibc-all-in-one list
cd glibc-all-in-one
./update_list
cd ..

Compilation Errors

Ensure all dependencies are installed:
sudo apt-get install build-essential gcc make patchelf zstd wget

Example Workflow

Here’s a complete workflow for testing a technique on glibc 2.35:
# Clone the repository
git clone https://github.com/shellphish/how2heap
cd how2heap

# Build for glibc 2.35 with debug symbols
H2H_USE_SYSTEM_LIBC=N make v2.35

# Run a specific technique
./glibc_2.35/fastbin_dup

# Debug with gdb
gdb ./glibc_2.35/fastbin_dup

# Or use with a heap exploitation debugger
gdb -q -ex "source ~/pwndbg/gdbinit.py" -ex "start" ./glibc_2.35/fastbin_dup

Additional Resources

For more information on setting up your environment:
  • [Getting Started Guide/quickstart)
  • [Heap Exploitation Tools/tools/debugging-tools)
  • [Debugging Heap Issues/tools/debugging-tools)

Build docs developers (and LLMs) love