Don't like this style? Click here to change it! blue.css

Welcome .... Click here to logout

Daily Reminder: Mom's Spaghetti

Our compass through all of this is the desire for the following comfort food:

You're babies today and we're going to learn the warmth and love of the dining room table. So that as you venture into the wilderness you'll do your best to recreate this ritual in ever harsher environments.

Class 22: Generating Leaks pt. 2


Reminder of the narrative structure:

It's "easy" just:

This simple trick breaks in three ways:

Problem 1: TOP CHUNK

OK the first issue is that your chunk will get "consolidated" with the top chunk.

The top chunk is the "wilderness" which is the boundary between allocated space and unallocated space.

There is always a number of bytes left in the top chunk stored at the boundary so the allocator can decide if there is room for the chunk you want.

Solution to Problem 1: malloc malloc free

Just always make sure you have a barrier chunk between you and the wilderness.

Think Jon Snow and the great wall keeping out the wildlings.


You'll see this top chunk business in the "free flowchart" in the "consolidate with top chunk" branch/box

Problem 2: Safe-Linking

In glibc 2.32 and beyond the singly linked lists in the heap use "safe-linking"

Safe-linking literally does this:

#define PROTECT_PTR(pos, ptr, type)  \
    ((type)((((size_t)pos) >> PAGE_SHIFT) ^ ((size_t)ptr)))
#define REVEAL_PTR(pos, ptr, type)   \
        PROTECT_PTR(pos, ptr, type)

That is it XORs addesses with the heap address bit-shifted by 12.

Still again: it encrypts addresses with the RANDOM PART of the heap address, skipping those bottom 12 "000" bits

My pythonic pseudo-code hopefully makes this clear:

OK so how do we get around this?

Solution A: just decrypt it

This encryption isn't very strong, so if you've leaked it you can pretty quickly un-encrypt the leak:

BOOKMARK this script it's useful to keep around.

Solution B: change your glibc?

OK this isn't a solution so much as an excuse to teach you something very valuable.

It's not a solution because you don't get to pick the version of glibc used on the target server.

It IS USEFUL because the version on the server won't match your test environment so you MUST KNOW HOW TO EMULATE their environment.

Linking to a different glibc

The TLDR is this:


There are other ways to do this but I find this one liner useful for students to know.

To fetch a copy of the library for any version of glibc use this tool:

Most of the time a CTF problem will provide you the glibc, often they do not provide the linker.

Solution C: get out of tcache

Question: What is tcache?

We need to talk out the Tale of the 5 bins which are the 5 ways that glibc tries to recycle chunks.

The 5 bins are:

Safe-linking only applies to tcache and fastbins.

tcache is the first choice for recycling chunks.

If you can change things around a little bit you can get your free'd chunk to live in the unsorted bin.

Our first trick for "getting out of tcache" is to ask for something large than the biggest chunk tcache holds:

PROBLEM 3: not a glibc leak

We finally get a leak. It's a leak into the heap...

That's nice I guess but it's not a glibc leak.


If you get a heap leak that is what it takes for you to ENCRYPT your own pointers in the future.

So hold on to this for the second phase of MOM'S SPAGHETTI

But GLIBC leaks are better

OK well the Solution C above actually gets a glibc leak. So that's cool.

Will leak an unencrypted glibc leak.

tcache and fastbins are singly linked lists

unsorted bin and small/largebins are doubly linked

A doubly linked list will point back to the HEAD of the linked list.

That HEAD lives in glibc's main_arena a data structure we're going to want to learn about.

SIDE QUEST: Linked Lists

Remember these?

The basic idea is that linked lists are just a sequence of pointers.

Here is a diagram of what linked singly-linked chunks look like:

Here is how adding a chunk to a "bin"/linked-list works:

Here is how popping a chunk from a "bin"/linked-list works:

Here is a "doubly linked" list which is the unsorted bin:

SIDE QUEST: the tale of the 5 bins (part 1: tcache)

The job here is to know WHY each of the 5 bins exists.

Then to know HOW to get a chunk linked into any of the 5 bins.

tcache: a "per thread" mini-heap kept in the heap

This is the newest bin and probably should be the last one to understand because it's wackier than the others.

The why of it is that parallel computing will LOCK the glibc main_arena (all other bins) and if you're doing multi-threaded stuff you make it silly if they all wait for each other anyway.

So how does tcache work?

It is a set of singly-linked lists where EVERY CHUNK in each tcache-bin has a FIXED SIZE.

The SIZES go from 0x20 to 0x410, so anything larger than that will NOT go into tcache when free'd, instead it goes into the UNSORTED BIN (which is doubly linked to glibc).

ALSO tcache LIMITS THE SIZE OF EACH BIN, so they keep track of HOW MANY chunks are in each BIN (linked-list) for each size.

The limit is 7, an 8th chunk of that size will no longer go into tcache (it might go into the fastbins).

The reason for the limit it to make sure DEFRAGMENTATION doesn't get too bad.

The struct as treasure map

That diagram above is a sort of treasure map saying how to process data in the teal tcache segment we've been seeing every time we run vis.

Make a free some chunks and watch the struct move.



Heap Reference Guides: