# shellphish/how2heap: a versioned library of glibc heap exploitation techniques

> how2heap is a C repository that demonstrates heap exploitation primitives against specific glibc versions, with each technique tied to an Ubuntu libc release. It is a teaching and reference tool for CTF players and vulnerability researchers, not a runtime library.

**shellphish/how2heap** — A repository for learning various heap exploitation techniques.

- Repository: https://github.com/shellphish/how2heap
- Stars: 8,895 · Forks: 1,288
- Language: C
- License: MIT
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/shellphish-how2heap

## What problem shellphish/how2heap solves and who it is for

glibc's allocator changes between releases. A technique that works against glibc 2.23 can be dead against 2.31, and the patch that killed it is often a single commit in malloc.c. Learning heap exploitation from a blog post is therefore unreliable: the post usually omits which libc it targeted. how2heap addresses that by shipping each technique as a standalone C file, grouped by the glibc version it was verified against, and by listing a Glibc-Version column and a patch link in the README table. The README states the repository uses Ubuntu's libc releases as the gold standard and that each technique is verified on the corresponding Ubuntu release.

The audience is narrow and technical. You need to read C, understand chunk headers and freelists, and be comfortable compiling and running binaries under a debugger. The README points to an in-browser debug option: several table rows carry an arrow link to wargames.ret2.systems levels named after the technique, so a reader can step through a technique without a local setup. That is the closest thing to an onboarding path in the repository.

## How the versioned layout and Makefile drive each technique

The repository root holds three version-independent files: first_fit.c, calc_tcache_idx.c, and malloc_playground.c. Everything else lives under a directory named for a libc version, from glibc_2.23 through glibc_2.43, plus an obsolete directory. The Makefile derives its build targets from that layout rather than from a hand-written list: TECH_BINS is every .c file matching glibc_*/*.c, and BASE_BINS is every top-level .c file. That means adding a technique to a version directory is enough for the build to pick it up, with no Makefile edit.

The version list is explicit in the Makefile, and the download rules are generated from it. Running a download target for a version resolves a libc package name from glibc-all-in-one's list, falling back to old_list when the version is not in the current list, then downloads it. The glibc-all-in-one directory is a git submodule, so the libc binaries are not in the repository itself; the Makefile initializes the submodule and runs ./update_list before any download. Compilation uses -std=c99 -g with -ldl, and the README notes that apt source libc6 retrieves the libc source on a Debian-based system, which is how you read the allocator code a technique depends on.

## Installing how2heap and running a technique for a specific glibc

There is no package to install. The repository is cloned, and the Dockerfile shows the intended environment: Ubuntu 20.04 with binutils, gcc, make, vim, patchelf, python-is-python3, python3-pip and requests, then a clone of the repository into /root/how2heap. If you prefer a container, build from the shipped Dockerfile, which ends in an interactive bash shell in the working directory.

```dockerfile
from ubuntu:20.04
run apt-get update && apt-get install -y binutils git make vim gcc patchelf python-is-python3 python3-pip
run pip3 install requests
run git clone --depth 1 https://github.com/shellphish/how2heap /root/how2heap
workdir /root/how2heap
```

On a host, clone with submodules so glibc-all-in-one is present, then ask make what it can do. The help target prints the available commands, including the per-version build and test forms.

```bash
make help
```

Build a single version's techniques. The README and Makefile use the form make v2.39, and the same pattern works for any version in the list. The build produces one binary per .c file in that directory.

```bash
make v2.39
```

Run the test target for a version to execute every technique in that directory. This is the quickest way to see which ones still behave as documented on your machine.

```bash
make test version=2.39
```

After the build, the binaries sit next to their sources, so you can run or debug one directly. The README recommends reading the libc source alongside the technique via apt source libc6.

## Where how2heap stops being the right tool

The repository is teaching material, and it behaves like it. The README table is the only index of what is current: rows are marked latest, or bounded by a version such as < 2.29 or < 2.43, and each patched row links to the glibc commit that closed it. Nothing verifies those bounds for you. If your target runs a libc that is not in the version list, or a distribution build with backported fixes, the table cannot tell you whether a technique applies.

A second limit is the environment assumption. The Dockerfile pins Ubuntu 20.04, and the Makefile downloads libc builds through glibc-all-in-one and patches binaries with patchelf. That works for local study, but it is not a harness for testing a real target binary: there is no loader-selection script or runner beyond the Makefile targets. Techniques also assume a specific bug class is already available to you, such as a single null byte overflow or a use-after-free. If you have an arbitrary read or write, most of these files are the wrong starting point. Finally, the repository does not document rollback, so if a version build fails you are left with make clean and make distclean, which removes built binaries and downloaded libcs respectively.

## how2heap compared with a general allocator study path

The obvious alternative is to read glibc's malloc.c directly, which the README half-encourages by pointing at apt source libc6. That approach gives you the allocator as it is, including the checks that make a technique fail, but it gives you no runnable example and no mapping from a primitive to an attack. It is also slow: you have to construct your own test cases to see first-fit behavior or tcache index math.

A second alternative is a fuzzing or symbolic-execution setup, such as the Driller work associated with the same research group, which searches for inputs that reach a crash rather than demonstrating a named primitive. Those tools answer a different question. how2heap tells you what a technique is and which libc versions allow it; a fuzzer tells you whether a particular binary can be driven into a fault. For someone learning the allocator, the repository's two base files, first_fit.c and calc_tcache_idx.c, are a cheaper starting point than either, because they show allocator behavior with no exploitation step at all.

## Maintenance, licence and the cost of following glibc releases

The repository is not archived, and the last push was on 2026-05-15. The version directories run to glibc_2.43, and glibc_ChangeLog.md sits at the root, which together indicate the project tracks new libc releases rather than freezing at one. The practical upgrade cost falls on you: when a technique's version bound changes, you re-read the linked patch commit and recheck the table row. There is no release feed published in the repository, so the table and the directory listing are the state you have.

The licence is MIT, stated in the repository metadata and shipped as LICENSE at the root. That is permissive and permits reuse with attribution, but it says nothing about the glibc source or the downloaded libc binaries, which carry their own licences from their upstream projects. Treat the technique files and any libc you download as separate licensing questions, and check the terms of whatever libc build you pull through glibc-all-in-one.

## Conclusion

Adopt how2heap if you are learning heap exploitation, preparing for CTF pwn challenges, or need a reference for how a specific glibc version behaves. Do not adopt it as a runtime dependency or as a general memory-safety course; it assumes you already read C and understand malloc internals. Before relying on any technique, verify the glibc version your target actually uses against the version directory or the Glibc-Version column for that file, because a technique marked latest in the table may not apply to an older release, and the README does not document rollback or a supported-version policy beyond the table.

## FAQ

### What glibc version does a how2heap technique apply to?

Each technique file lives in a directory named for the libc version it was verified against, and the README table adds a Glibc-Version column with bounds such as < 2.29 or < 2.43. Rows marked latest have no upper bound listed. Check both before assuming a technique works on your target.

### How do I install and build how2heap?

There is no package. Clone the repository with its submodules, or build the shipped Dockerfile, which installs gcc, make, patchelf and the rest on Ubuntu 20.04. Then run make help to see the commands, make v2.39 to build one version's techniques, or make test version=2.39 to run them.

### Can I debug a how2heap technique in a browser?

Yes. Several rows in the README table carry an arrow link to a wargames.ret2.systems level named after the technique, which the README describes as debugging the technique in your browser. The remaining rows have no such link.

## Sources

- [Issues](https://github.com/shellphish/how2heap/issues)
- [License: MIT](https://github.com/shellphish/how2heap/blob/master/LICENSE)
- [README](https://github.com/shellphish/how2heap/blob/master/README.md)
- [shellphish/how2heap on GitHub](https://github.com/shellphish/how2heap)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/shellphish-how2heap
