Intro to Heap Exploitation
Ringkasan
TLDRThis talk covers the fundamentals of heap memory management in binary exploitation, explaining how the heap functions, the allocation and deallocation of memory, and the challenges involved in efficient memory management. The speaker introduces heap structure, the role of malloc, and various heap exploitation techniques, notably use after free and double free attacks. It emphasizes the need for understanding heap dynamics to exploit memory-related vulnerabilities effectively and discusses advanced tactics that could be utilized in exploitation.
Takeaways
- 🗂️ The heap is crucial for dynamic memory allocation in programming.
- 💾 Malloc is the API used to request memory from the heap.
- ⚠️ Use after free can lead to serious security vulnerabilities.
- ❌ Double free errors can create memory corruption opportunities.
- ⚡ Fast bins enhance the efficiency of memory allocation for small sizes.
- 🧩 Understanding heap structure is key to effective binary exploitation.
- 🔄 Circular linked lists in the heap can leak libc addresses.
- 🔍 Memory checks in modern libc help mitigate exploitation risks.
- 🔗 Overlapping allocations can corrupt data and lead to exploits.
- ⚙️ Techniques for heap exploitation vary by libc version, necessitating awareness of implementations.
Garis waktu
- 00:00:00 - 00:05:00
The speaker introduces heap memory management, highlighting its complexity in binary exploitation. They aim to simplify the subject by explaining the heap's architecture and its role in exploits.
- 00:05:00 - 00:34:38
The heap is described as a mechanism for dynamic memory allocation, allowing programmers to request memory that persists beyond function calls. The heap manages large memory pages, breaking them into smaller chunks for efficient usage.
Peta Pikiran
Video Tanya Jawab
What is a heap in memory management?
A heap is a region of a process's memory used for dynamic memory allocation, where memory can be allocated and freed at runtime.
What is the role of malloc in memory allocation?
Malloc is a function in C that requests a specified number of bytes from the heap, returning a pointer to the allocated memory.
What is a use after free attack?
A use after free attack occurs when a program continues to use a memory allocation after it has been freed, potentially leading to memory corruption.
What are fast bins in the heap?
Fast bins are special bins in the heap that efficiently manage small chunks of memory for quick allocation and deallocation.
How does a double free exploit work?
A double free exploit occurs when a program attempts to free the same memory chunk twice, creating inconsistencies in the memory management and often leading to exploitation.
What problems can arise from inefficient memory allocation in the heap?
Inefficient memory allocation can lead to increased latency in memory requests and potential vulnerabilities like fragmentation.
Why is understanding the heap crucial for binary exploitation?
Understanding the heap helps in identifying vulnerabilities that can be exploited to manipulate memory operations and gain control over execution.
What are some common heap exploitation techniques?
Common techniques include use after free, double free, and manipulating heap structures to forge arbitrary memory addresses.
How can one leak libc addresses using the heap?
By manipulating the doubly linked and circular structure of the free list in the heap, one can leak libc addresses, as the pointers in the list may point to locations within the libc.
What precautions do modern libc implementations take against heap exploitation?
Modern libc implementations include checks to prevent certain heap exploitation techniques, such as preventing double frees or ensuring that freed chunks do not form cycles.
Lihat lebih banyak ringkasan video
MASSIVE AI News : AGI Secret UNLOCKED! o3, GPT5, OpenAI Moves Faster And Stunning Humanoid Robots
This GPT-5 NEWS Could Change EVERYTHING...
History of Rock Episode 03 Part 1/4
David Rosenberg: "Investors are Betting on a 1-in-20 Event"
All about Canada for Kids | Learn about this fun country's history and culture
gmod shenanigans
- 00:00:01okay this is intro to heap
- 00:00:03um it's one of the uh spookier topics in
- 00:00:06binary exploitation
- 00:00:08but hopefully it shouldn't be very
- 00:00:10spooky during this talk
- 00:00:12so uh we'll start by kind of going
- 00:00:15through
- 00:00:16what the heap is and like how the heap
- 00:00:20is designed and then we'll go into the
- 00:00:22actual
- 00:00:23like using it to exploit stuff
- 00:00:26but understanding what the heap is and
- 00:00:29like how it works is
- 00:00:30pretty key to understanding all the
- 00:00:32exploits so we'll go pretty far in depth
- 00:00:35on that first
- 00:00:38okay so what exactly is a heap
- 00:00:41and what does it do right when we're
- 00:00:43writing
- 00:00:44c code we want some some way that we can
- 00:00:47ask for
- 00:00:48a kind of memory that's not going to go
- 00:00:51away after our function has finished
- 00:00:53executing
- 00:00:55and really what we want is we just want
- 00:00:58like some api that we can ask hey give
- 00:01:01me
- 00:01:01n bytes of memory and then it will give
- 00:01:04us back
- 00:01:05a pointer to in bytes of memory um
- 00:01:08and then we can use that however we want
- 00:01:10and then when we're finally done with
- 00:01:12that memory we just give it back
- 00:01:14so that's essentially the api that we
- 00:01:15want um
- 00:01:17and the question is how do we how do we
- 00:01:20implement this and it turns out to be
- 00:01:24harder than you may expect so
- 00:01:28um one of the main problems with this
- 00:01:31uh is that the like a program can only
- 00:01:34request entire pr
- 00:01:35uh entire pages from from the operating
- 00:01:38system so um
- 00:01:40if you if your program needs more memory
- 00:01:42it can only request
- 00:01:44memory in uh big chunks of
- 00:01:484096 bytes which
- 00:01:52usually we're not going to want big
- 00:01:54chunks of 4096 bytes we may want
- 00:01:57like 20 bytes or something like that so
- 00:02:01uh really what we want to do is
- 00:02:04take these big chunks and break them up
- 00:02:08into smaller chunks
- 00:02:10and then have some code that manages uh
- 00:02:13these smaller chunks for us so that we
- 00:02:15don't have to deal with
- 00:02:17uh making sure that we don't allocate
- 00:02:19the same memory twice or something like
- 00:02:20that
- 00:02:21so we essentially just want uh like a
- 00:02:23program that's going to solve all these
- 00:02:25problems for us
- 00:02:27that we don't have to worry about and
- 00:02:29that's what the heap does
- 00:02:32so the way that the heap works kind of
- 00:02:35under
- 00:02:36the hood is it it starts off by
- 00:02:39requesting a really big
- 00:02:40chunk called the top chunk or the
- 00:02:42wilderness chunk
- 00:02:45and this is just like a massive
- 00:02:47contiguous region of memory that the
- 00:02:49heap has allocated
- 00:02:51um and when when we ask it for
- 00:02:54um smaller regions so say i ask for 50
- 00:02:57bytes from the heap
- 00:02:59what it's going to do is it's going to
- 00:03:00split the wilderness chunk
- 00:03:03into a a little region of 50 bytes
- 00:03:07and a big region that's like the rest of
- 00:03:11the wilderness chunk
- 00:03:12and then it's just going to hand those
- 00:03:1450 bytes to us
- 00:03:16so um
- 00:03:19like subsequent calls to to the uh
- 00:03:22malloc which is the like allocation api
- 00:03:25call
- 00:03:26um we'll just like break off a piece of
- 00:03:29the wilderness chunk and hand it to us
- 00:03:31and there's this uh
- 00:03:36struct in in libsy called the heap
- 00:03:40main arena which kind of keeps track of
- 00:03:43all of the high level heap metadata
- 00:03:45which
- 00:03:46uh the heap main arena keeps track of
- 00:03:49like where the wilderness chunk lives
- 00:03:51and um some other stuff that we'll talk
- 00:03:54about later
- 00:03:55but the arena's not terribly important
- 00:03:57in this talk
- 00:04:00okay so i just said that the arena isn't
- 00:04:03terribly important but here i have a
- 00:04:05picture describing what it looks like
- 00:04:07so um the main arena is just destruct it
- 00:04:11has
- 00:04:11like some pointers in it um to
- 00:04:14various like heap metadata things and
- 00:04:17the important thing in this picture is
- 00:04:19that there's a
- 00:04:19there's just a pointer to the top chunk
- 00:04:22of the main arena so
- 00:04:24uh when you want to break off memory it
- 00:04:26just looks up this pointer in the main
- 00:04:28arena struct
- 00:04:29breaks off some memory there and hands
- 00:04:31it back to
- 00:04:34back to like the user program
- 00:04:37okay so um
- 00:04:40that's allocation allocation kind of
- 00:04:43makes sense right
- 00:04:44uh when we when we we just like cut some
- 00:04:47memory off
- 00:04:48the top chunk shrinks um and then we
- 00:04:50give that memory back
- 00:04:52so um where it gets kind of
- 00:04:55kind of complicated is when we talk
- 00:04:57about
- 00:04:58um i guess there's another picture of uh
- 00:05:01allocation i don't know why i have so
- 00:05:03many pictures of this but yeah this is
- 00:05:04this is what it looks like if you were
- 00:05:06to allocate two chunks
- 00:05:07you get like chunk a chunk b and then
- 00:05:09you have the top chunk down here which
- 00:05:11is like
- 00:05:11really big so it's just splitting the
- 00:05:14chunks
- 00:05:15kind of sequentially as you as you might
- 00:05:18expect
- 00:05:21so where it gets complicated is when we
- 00:05:23want to give the memory back
- 00:05:25right so say say we've allocated 50
- 00:05:28bytes
- 00:05:29uh and we've we've uh
- 00:05:32finished using these 50 bytes that we
- 00:05:34were using
- 00:05:35we want to give it back to the heap so
- 00:05:37the heap can reuse this memory
- 00:05:40um and
- 00:05:43uh this is this is where it gets kind of
- 00:05:46hard right because
- 00:05:47what we really want to do is kind of
- 00:05:49reattach the memory
- 00:05:51to the to the top chunk um
- 00:05:54but we can't do this in most cases
- 00:05:57unless the the chunk that we're freeing
- 00:05:59is like
- 00:06:00right next to the top chunk in memory
- 00:06:02like they're they're literally touching
- 00:06:04and then we can
- 00:06:04just make them into one big chunk if
- 00:06:07they're like disjoint in memory we can't
- 00:06:09recombine them so we have to do
- 00:06:10something
- 00:06:11uh like more interesting in order to
- 00:06:14put them together so here's a case where
- 00:06:18like we can't recombine the the
- 00:06:20top chunk in the chunk that we're
- 00:06:21freeing right so if we have like
- 00:06:23chunk a that we're freeing and there's
- 00:06:25chunk b in between them we can't
- 00:06:27put chunk a back onto the top chunk
- 00:06:29because
- 00:06:31chunk b is in the way if we were to free
- 00:06:34chunk b then we could like
- 00:06:37combine them all back into one chunk but
- 00:06:40until we free chunk b
- 00:06:41we can't do that
- 00:06:45so instead what we're going to do is
- 00:06:47we're going to
- 00:06:49take the free chunk and put it in a list
- 00:06:51of free chunks
- 00:06:53and then when we when we allocate later
- 00:06:55we'll just look through this list
- 00:06:57and see if there's any suitably sized
- 00:06:59chunks
- 00:07:01that we can that we can give to the user
- 00:07:04um and if if there is no such
- 00:07:06suitably sized chunk then we will take
- 00:07:08it from the top chunk
- 00:07:10um now if you're actually writing
- 00:07:13like a user program right you would want
- 00:07:17this like free list lookup code to be
- 00:07:20extremely fast right you don't want your
- 00:07:22code to be
- 00:07:23uh stuck in libsy looking for uh like
- 00:07:27free memory in the in the free list the
- 00:07:30whole time
- 00:07:31um so the the malloc
- 00:07:34uh like heap designers have have really
- 00:07:38like gone out of their way to make this
- 00:07:40efficient um
- 00:07:41and a lot of this efficiency is what
- 00:07:43we're going to be exploiting
- 00:07:46okay so this is kind of what i was
- 00:07:48describing in
- 00:07:49in the last thing where it's like you
- 00:07:51have a list of free chunks
- 00:07:53and in this implementation the chunks
- 00:07:56have like no restriction on
- 00:07:58uh what size they are you just put all
- 00:08:00the free chunks in a list
- 00:08:02right and the issue here is that if i'm
- 00:08:04looking for a chunk of size
- 00:08:060x 100 i'm going to have to look through
- 00:08:10like all the chunks until i find one
- 00:08:13that is bigger than 0x100
- 00:08:15right so um
- 00:08:18this is going to be really slow because
- 00:08:19it like worst case i have to look
- 00:08:21through
- 00:08:21the entire free list to
- 00:08:25to allocate my chunk like i may look
- 00:08:27through the entire free list
- 00:08:29determine there was no free chunk of
- 00:08:31this size and then just allocate from
- 00:08:33the top chunk anyway so i just wasted a
- 00:08:35bunch of time
- 00:08:36um so so this is not efficient enough we
- 00:08:38need to come up with a
- 00:08:40much more efficient way to do heap
- 00:08:43allocations
- 00:08:46so the the main idea that we use
- 00:08:50is we bucket the chunks
- 00:08:53by their size so for every size chunk
- 00:08:57there is a separate free list um and
- 00:08:59these
- 00:09:00these free lists are called bins so
- 00:09:03every every size chunk goes in a
- 00:09:05different bin
- 00:09:06um and uh
- 00:09:11the the idea is like um
- 00:09:15if if the the bins are kind of done by
- 00:09:18size
- 00:09:19in order to find a chunk of a specific
- 00:09:22size
- 00:09:23we only have to look through the bin of
- 00:09:25that size
- 00:09:28and then we we greatly reduce the number
- 00:09:30of free chunks we have to look through
- 00:09:32because we're only looking through like
- 00:09:34the portion that are
- 00:09:36probably the right size um
- 00:09:40and in fact uh there are some
- 00:09:43some uh bins called fast bins
- 00:09:46in the heap which are for really small
- 00:09:49chunks so
- 00:09:50size like 0x10 to 0xb0
- 00:09:55and this is essentially like the the
- 00:09:58idea is
- 00:09:59that allocations of small size are made
- 00:10:02very frequently
- 00:10:04so we want the uh the like free list
- 00:10:07lookup code to be
- 00:10:08really simple and really fast
- 00:10:12and because it's really simple and
- 00:10:13really fast
- 00:10:15it's easy to exploit for ctfs because
- 00:10:18uh the code is is pretty simple um
- 00:10:24yeah so so um a fast bin
- 00:10:27right as i was talking about on the
- 00:10:29previous slide
- 00:10:30it's just a singly linked list of free
- 00:10:33chunks that are all of the same size
- 00:10:35um so when you when you allocate
- 00:10:39for a small chunk size uh what it's
- 00:10:42going to do
- 00:10:42is just let's say let's say i'm trying
- 00:10:44to allocate a chunk of size
- 00:10:46like uh 25 right it's going to round
- 00:10:50that up
- 00:10:50to the nearest small chunk size which
- 00:10:53would be
- 00:10:54uh 32 bytes um
- 00:10:57because it's a multiple of eight
- 00:11:00so 32 bytes um
- 00:11:04and then we just go to the fast bin for
- 00:11:07things that are size 32 bytes
- 00:11:10and just find uh the first thing in the
- 00:11:13fast bin
- 00:11:14because that element is free so we just
- 00:11:16we just pull that
- 00:11:17element out and now we have somewhere to
- 00:11:22put our uh 25 bytes
- 00:11:25so here's here's what a uh what this
- 00:11:27this
- 00:11:28fast bin looks like so we have um
- 00:11:30essentially just a
- 00:11:31linked list of free chunks all of the
- 00:11:34same size
- 00:11:35right so uh when we
- 00:11:39uh allocate something of size 0x80
- 00:11:43we're just going to pull free chunk a
- 00:11:45because it's
- 00:11:46like it's unallocated memory and it's of
- 00:11:49the right size
- 00:11:50and then we just kind of shift the
- 00:11:52linked list over one
- 00:11:55and then if we allocate again we'll get
- 00:11:57free chunk b
- 00:11:59um okay and so
- 00:12:02uh i guess also we should say if we were
- 00:12:06to
- 00:12:06free some other chunk let's call it
- 00:12:10chunk d
- 00:12:11we would put free chunk d in front of
- 00:12:13free chunk a
- 00:12:14so it kind of gets pushed on to the
- 00:12:16front
- 00:12:18and then if we were to allocate again we
- 00:12:20would get free chunk d
- 00:12:21and then we get free chunk a free chunk
- 00:12:23b and free chunk c
- 00:12:25and then if we completely exhaust the
- 00:12:27fast bin will start pulling stuff off of
- 00:12:29the top chunk again
- 00:12:31okay so uh yeah the idea is that every
- 00:12:35chunk in the in the list is the same
- 00:12:37size
- 00:12:38so we don't have to do this really slow
- 00:12:40search we can just take the head of the
- 00:12:42list
- 00:12:46there are other bin types in the heap
- 00:12:49i'll talk about one later but uh they're
- 00:12:52not
- 00:12:52really important uh they they come up in
- 00:12:56a lot of more complicated attacks but
- 00:12:59we probably won't talk about those
- 00:13:01attacks today
- 00:13:02um it it the only the only real
- 00:13:06difference is that uh the other bins are
- 00:13:09doubly linked and circular so uh instead
- 00:13:12of just being a singly linked list like
- 00:13:14the
- 00:13:14fast bins um there's like a backward
- 00:13:17point or two that points backwards
- 00:13:19um and it's also like a circular list
- 00:13:23um but yeah that won't really be
- 00:13:26important until the end of the talk and
- 00:13:28we'll talk about it later again
- 00:13:30okay so that's the kind of basic idea of
- 00:13:34a heap in general
- 00:13:35um we'll talk quickly about the
- 00:13:38specifics of how
- 00:13:39the uh glib c heap is implemented
- 00:13:42because that's probably what you would
- 00:13:44be exploiting in a ctf
- 00:13:46so uh first of all the
- 00:13:49um in glib c when when we have these
- 00:13:53um these uh the free list
- 00:13:56uh the the pointer the linked list
- 00:13:59pointer is called
- 00:14:00fd for forward um
- 00:14:03and the the uh the backward pointer
- 00:14:06if there is one is called bk for
- 00:14:08backward um
- 00:14:11so there's there's those two things to
- 00:14:13be aware of and then there's also
- 00:14:15the fact that every chunk is allocated
- 00:14:18with an additional eight bytes
- 00:14:20uh preceding it specifying the size so
- 00:14:23um here's a picture of like um a free
- 00:14:26chunk in an allocated chunk so
- 00:14:28when we have an allocated chunk we just
- 00:14:30have a chunk with a bunch of user data
- 00:14:33and the the pointer points to the start
- 00:14:35of the user data
- 00:14:36and then eight bytes uh the eight bytes
- 00:14:39before the user data
- 00:14:40there's like a little size um
- 00:14:43attached to it so um
- 00:14:47essentially when you when you allocate
- 00:14:49uh like
- 00:14:50say 20 bytes you actually get 28 bytes
- 00:14:55because you're you're getting this size
- 00:14:57thing that you're unable to use
- 00:14:59when you're actually writing user data
- 00:15:01into it and then
- 00:15:03the idea is that when you free a chunk
- 00:15:07instead of keeping track of the linked
- 00:15:10list somewhere else
- 00:15:11you just turn the chunk into a linked
- 00:15:13list node
- 00:15:14so uh when when a chunk is free
- 00:15:18instead of having user data in it it has
- 00:15:21all of the
- 00:15:21like chunk metadata in it like the
- 00:15:23forward pointer and backward pointer
- 00:15:25and like the size of the uh
- 00:15:28of the next chunk and the size of the
- 00:15:30previous chunk
- 00:15:33and a bunch of other stuff like this but
- 00:15:35we only really care about the forward
- 00:15:36pointer in this talk
- 00:15:38so remember this is just the um in the
- 00:15:41free list
- 00:15:42the forward pointer just points to the
- 00:15:44next free chunk
- 00:15:46um okay so
- 00:15:50we'll note now talk about um kind of
- 00:15:54how these attacks are going to work so
- 00:15:56there's there's generally two
- 00:15:58methods of um
- 00:16:01of doing like a heap exploit one is
- 00:16:05uh kind of trying to get overlapping
- 00:16:07allocations
- 00:16:09so we we try to cause the heap to
- 00:16:11allocate
- 00:16:12two structs at the same underlying
- 00:16:14memory
- 00:16:16so we may allocate like an object
- 00:16:19and a string at the same memory and when
- 00:16:22we
- 00:16:23when we write to the string it's going
- 00:16:25to mess up the object
- 00:16:27and vice versa if we write to the object
- 00:16:29it's going to
- 00:16:31mess with the string so
- 00:16:34once we have kind of overlapping
- 00:16:36allocations of two different structs
- 00:16:39we can do uh several things to
- 00:16:42um get control of the return uh
- 00:16:46uh of the instruction pointer um
- 00:16:50but the the general idea is we're either
- 00:16:53going to overwrite a function pointer
- 00:16:55in the struct by say writing to a string
- 00:16:59and there's an object that has a
- 00:17:01function pointer in it
- 00:17:03and then we can we can call that
- 00:17:04function and we will
- 00:17:06then have control over the instruction
- 00:17:08pointer or
- 00:17:09we just uh do something more interesting
- 00:17:12and
- 00:17:14cause a stack overflow by like
- 00:17:17corrupting the object in a in a really
- 00:17:19creative way so maybe maybe there's like
- 00:17:21a uh maybe our our struct
- 00:17:25is a string with a length on it or
- 00:17:27something like that
- 00:17:28and we're able to overwrite the length
- 00:17:30field in this struct
- 00:17:32then we're able to cause like a stack
- 00:17:34buffer overflow and we just have to
- 00:17:36exploit things normally
- 00:17:40okay so this is kind of what this
- 00:17:42picture looks like we have
- 00:17:45like an object here on the left and a
- 00:17:47string here on the right and they have
- 00:17:48the exact same
- 00:17:49underlying memory so if we were to write
- 00:17:53into the string we're going to like
- 00:17:54overwrite
- 00:17:55the objects like v table and the objects
- 00:17:59members and generally just cause
- 00:18:03really bad things to happen in the
- 00:18:04program
- 00:18:06we won't really focus on what you do at
- 00:18:09this point we'll more focus on
- 00:18:12how to actually get this overlapping
- 00:18:14allocation in the first place
- 00:18:16because once you have the overlapping
- 00:18:17allocation it kind of just reduces to
- 00:18:20normal binary exploitation okay
- 00:18:23and the other the other idea is uh
- 00:18:27instead of doing overlapping allocations
- 00:18:29we just try to
- 00:18:31um get the heap to allocate memory
- 00:18:34that's outside of the heap
- 00:18:36so uh for example we get the heap to
- 00:18:38allocate
- 00:18:40uh like stack memory and we we can
- 00:18:43overwrite the return address by just
- 00:18:45writing into the chunk that it gives us
- 00:18:47or we try to get the heap to allocate us
- 00:18:49like global offset table
- 00:18:51uh memory as as our allocation and then
- 00:18:54we
- 00:18:55when we write into our struct we'll be
- 00:18:57overwriting uh global offset table
- 00:18:59entries
- 00:19:01um so these these are the kind of two
- 00:19:04main ideas
- 00:19:04is um having
- 00:19:08like overlapping allocations and having
- 00:19:11uh like arbitrary forged
- 00:19:14chunks at uh attacker-controlled
- 00:19:17addresses
- 00:19:19okay so now we actually get into um
- 00:19:22some specific attacks so the first one
- 00:19:24that we'll talk about
- 00:19:25is a use after free um
- 00:19:29so this is kind of the simplest heap
- 00:19:33exploit
- 00:19:34um and we'll first talk about using a
- 00:19:37use after free to get overlapping
- 00:19:39allocations
- 00:19:41so uh the idea of a use after free
- 00:19:45is that we're allowed to uh read or
- 00:19:47write
- 00:19:48to um an allocation after it's already
- 00:19:51been freed
- 00:19:52so um we we have some object and memory
- 00:19:57we free it uh and then we we continue
- 00:20:01doing things to that object as if it's
- 00:20:03still valid memory
- 00:20:06and the idea here is that
- 00:20:10the next time we call malloc with this
- 00:20:12specific
- 00:20:13chunk size we're going to get this
- 00:20:15memory that we've just freed
- 00:20:17so we kind of get an overlapping
- 00:20:20allocation for free
- 00:20:21um just by like we have we have this
- 00:20:25chunk that
- 00:20:26has like uh uh is being used as
- 00:20:29as if it's valid memory although it's
- 00:20:31already been freed
- 00:20:32and this chunk is also uh in the free
- 00:20:35list
- 00:20:36so when we allocate next um
- 00:20:40a chunk of size 0x80 we're going to
- 00:20:43um get back the same chunk so we have
- 00:20:46like uaf
- 00:20:47chunk a and then we have allocated chunk
- 00:20:50a and they they have the same memory
- 00:20:52um so now if we do something to the uaf
- 00:20:55chunk a
- 00:20:56um it does the same thing to the
- 00:20:59allocated chunk a and vice versa so
- 00:21:01this is the same thing like say
- 00:21:03allocated chunk a is a string and uaf
- 00:21:05chunk a is
- 00:21:06an object uh we can mess with the object
- 00:21:09by writing to the string
- 00:21:12okay so um that's kind of the
- 00:21:16the um the idea of
- 00:21:19uh like the overlapping allocation uaf
- 00:21:22it's kind of
- 00:21:23just for free just by allocating again
- 00:21:26so how do we how do we forge a chunk
- 00:21:28uh into like an arbitrary memory address
- 00:21:33so notice that by writing to the free
- 00:21:35chunk we can
- 00:21:36we can mess with the linked list
- 00:21:38pointers
- 00:21:40so uh if we have our uaf
- 00:21:43chunk uh on the left here uh and we're
- 00:21:47able to write into this chunk as if it's
- 00:21:49still
- 00:21:49a valid allocation um when we write to
- 00:21:52the first eight bytes of this chunk
- 00:21:54we're
- 00:21:54actually going to overwrite the uh the
- 00:21:57forward pointer
- 00:21:58um so this is also going to overwrite
- 00:22:02the forward pointer for the chunk in the
- 00:22:04free list
- 00:22:04because they are the same memory right
- 00:22:08so the idea is that when we when we
- 00:22:11overwrite
- 00:22:12this this forward pointer um
- 00:22:15it's actually kind of saying hey there's
- 00:22:18um in the free list
- 00:22:22i'm pointing to some some random memory
- 00:22:24address that's attacker controlled
- 00:22:26so let's say we have we have like
- 00:22:30um we have like a free chunk and then we
- 00:22:33have
- 00:22:34our our chunk that's our malicious chunk
- 00:22:37and the malicious chunk
- 00:22:38is kind of the uh um
- 00:22:42i get i guess it's the one that has the
- 00:22:44the same memory as the uaf
- 00:22:46chunk and then we have uh we've
- 00:22:48overwritten
- 00:22:49the forward pointer of this of this
- 00:22:51malicious chunk
- 00:22:52um so now the the heap is going to think
- 00:22:55that there's another element in the free
- 00:22:57list
- 00:22:58and it's just off wherever we tell it
- 00:23:01so um we could overwrite the forward
- 00:23:05pointer with like a global offset table
- 00:23:07address and now when we when we allocate
- 00:23:10uh the forged chunk we will get a global
- 00:23:13offset table
- 00:23:14uh address which is really bad
- 00:23:18um so yeah um
- 00:23:22after allocating like so so the idea is
- 00:23:25that we will allocate this free chunk a
- 00:23:27we'll get that memory well i'll allocate
- 00:23:30this malicious chunk
- 00:23:31and we'll get that memory and then we
- 00:23:34allocate again
- 00:23:34and we get the forged chunk that's like
- 00:23:36not in the heap
- 00:23:37uh so we we end up allocating memory
- 00:23:41that's at an arbitrary address and then
- 00:23:43we can use this to
- 00:23:45write to an arbitrary address so
- 00:23:48yeah then then we can just use this
- 00:23:50chunk to overwrite arbitrary memory like
- 00:23:52the global offset table or the return
- 00:23:54address
- 00:23:55um or whatever target you want
- 00:23:58really um so here's a specific example
- 00:24:02we would we would just overwrite this
- 00:24:04forward pointer with the global offset
- 00:24:06table address
- 00:24:07um and then this forged chunk will
- 00:24:11uh be in the global offset table
- 00:24:14so when we write to it we'll be
- 00:24:16overwriting global offset table entries
- 00:24:22okay so um in practice this doesn't
- 00:24:26quite work
- 00:24:27because malloc checks to make sure that
- 00:24:29the size of
- 00:24:32the size member that's before the chunk
- 00:24:35matches the the bin size that we're
- 00:24:37allocating so
- 00:24:39uh if we're if we're doing this exploit
- 00:24:42on
- 00:24:42the um on the
- 00:24:46xerox 80 fast then we would expect
- 00:24:49the or the heap expects this size
- 00:24:52argument
- 00:24:52up here to be 0x80 um so if we were to
- 00:24:57uh point this uh if we if the the
- 00:25:01the forged chunk points to something
- 00:25:03where
- 00:25:04the eight bytes preceding it are not
- 00:25:060x80
- 00:25:07uh the program is going to stop running
- 00:25:10and say like hey you have a heap error
- 00:25:12um so we need to
- 00:25:15uh the way that we get around this is we
- 00:25:17we write 0x80 somewhere
- 00:25:20in memory and then we just point to
- 00:25:22eight bytes past that
- 00:25:24um and then when we allocate the forged
- 00:25:27chunk it
- 00:25:28everything works out and the heaps is
- 00:25:30fine
- 00:25:32uh okay so now we talk about double
- 00:25:36freeze
- 00:25:36um double freeze are uh pretty similar
- 00:25:39to a use after free
- 00:25:41it's just a little bit more complicated
- 00:25:44so the idea of a double free is we're
- 00:25:47allowed to write to already allocated
- 00:25:50chunks
- 00:25:51and we're able to free a pointer twice
- 00:25:55so as you may notice from the name
- 00:25:58double free we are freeing something
- 00:26:02twice
- 00:26:03okay so um
- 00:26:06the idea here is that if you if you free
- 00:26:10some chunk a twice uh then you get
- 00:26:13this chunk a twice in the free list
- 00:26:16right
- 00:26:16and if you think about it this is
- 00:26:19creating
- 00:26:20a like um a cycle in this linked list
- 00:26:24because
- 00:26:25free chunk a points to free chunk a
- 00:26:28which points to free chunk a which
- 00:26:30points to free chunk a and so on
- 00:26:32so if we were to keep allocating we
- 00:26:35would just get free chunk a
- 00:26:36over and over and over again so
- 00:26:40um this kind of just gives us uh the
- 00:26:43the overlapping allocations for free
- 00:26:45right because if we just allocate twice
- 00:26:47we get the same exact memory
- 00:26:50and if we allocate however many times we
- 00:26:52want we still get the same exact memory
- 00:26:56so yeah if we allocate a chunk of size
- 00:26:590x80
- 00:27:00we just get uh chunk a um
- 00:27:07and then uh if we were to
- 00:27:10uh what is this slide saying the slide
- 00:27:14doesn't seem correct
- 00:27:15uh we allocate a chunk of size 0x80 we
- 00:27:19get free chunk a
- 00:27:20that's correct uh yeah the head of the
- 00:27:23list just stays free chunk a because
- 00:27:25this is a cyclic
- 00:27:26list right um so if we allocate
- 00:27:30again we just get chunk a again
- 00:27:34um and yeah this is enough for an
- 00:27:36overlapping allocation because we just
- 00:27:38every time we allocate something inside
- 00:27:400x80 we get chunk a
- 00:27:42from now on
- 00:27:45okay so uh now we we do the
- 00:27:49um the forged chunk case and this this
- 00:27:52kind of just reduces
- 00:27:54to the uaf so
- 00:27:57um if we uh have this
- 00:28:00this uh like cyclic thing when we
- 00:28:04when we allocate uh something of size
- 00:28:060x80
- 00:28:07we get chunk a and chunk a is still in
- 00:28:10the free list
- 00:28:12so when we when we overwrite the forward
- 00:28:14pointer
- 00:28:15of the allocated chunk uh or i guess
- 00:28:18when we overwrite the first eight bytes
- 00:28:20of the allocated chunk
- 00:28:21we're overriding forward pointer of the
- 00:28:23free chunk um
- 00:28:25so this messes with the free list again
- 00:28:27and we can just forge a chunk again
- 00:28:31okay so again in practice this has some
- 00:28:35issues
- 00:28:36so the heap has checks to make sure that
- 00:28:38you're not
- 00:28:39freeing the head of the free list so
- 00:28:41essentially
- 00:28:42the heap tries to make sure that you're
- 00:28:44not making this
- 00:28:46uh cyclic list with one
- 00:28:49element um and in order to get around
- 00:28:53this we just have to add an additional
- 00:28:55chunk in between because it only checks
- 00:28:58whether the head is the same as the
- 00:29:00thing you're currently freeing it
- 00:29:01doesn't actually check to make sure
- 00:29:02you're not
- 00:29:03introducing any cycle so
- 00:29:06if we just put in a cycle of two chunks
- 00:29:10then it works so if we
- 00:29:11free a we free b we free a again
- 00:29:15we get uh a points to b
- 00:29:18points to a points to b points to a and
- 00:29:20so on
- 00:29:21so there's still a cycle it's just
- 00:29:24length two now and
- 00:29:25the exploit works the same way um
- 00:29:30it's just we we can't do it with only
- 00:29:32one node because the heap will notice
- 00:29:34and crash the program
- 00:29:37okay so uh i've said a lot of things
- 00:29:41and i i feel like i should mention at
- 00:29:44this point that
- 00:29:45um the these heap exploits are very
- 00:29:48dependent
- 00:29:49on uh which libsy version you're using
- 00:29:52so
- 00:29:53depending on exactly
- 00:29:56which version you're using you may have
- 00:29:59a
- 00:30:00varying difficulty trying to get these
- 00:30:02attacks to work
- 00:30:03so for example this check right here was
- 00:30:07introduced in
- 00:30:08some libc version and if you're using
- 00:30:11a libsy version before that you don't
- 00:30:13have to deal with this
- 00:30:15and in later libsy versions there's more
- 00:30:18and more checks
- 00:30:19so depending on the lipsy version that
- 00:30:22you're trying to attack
- 00:30:23you have to get around more and more uh
- 00:30:27complicated checks um
- 00:30:31i won't really touch on exactly which
- 00:30:33lipsy versions
- 00:30:34things work on you'll probably just have
- 00:30:36to
- 00:30:38kind of figure that out yourself usually
- 00:30:40you can just read the libsy source code
- 00:30:43the malloc source code in particular is
- 00:30:45not super complicated so it's
- 00:30:48it's definitely understandable if you
- 00:30:49know like basic c
- 00:30:53okay so uh we we've kind of
- 00:30:56touched on the two main exploit types
- 00:30:59the use after free and double free
- 00:31:02um generally work on all libsy versions
- 00:31:06um and now we're gonna talk about
- 00:31:09kind of more more advanced tactics so
- 00:31:13use after free and double free are
- 00:31:15generally the
- 00:31:17most basic heap exploits
- 00:31:21and you you will see them everywhere
- 00:31:24some of the advanced tactics kind of get
- 00:31:26really spooky
- 00:31:27and i'm only really going to talk about
- 00:31:29one because i think it's uh particularly
- 00:31:32useful
- 00:31:34okay so remember i said at the very
- 00:31:36beginning of the talk
- 00:31:37that uh when we're doing allocations and
- 00:31:40freeze that are larger than fast bin
- 00:31:43size
- 00:31:44so 0x c 0
- 00:31:47and bigger um
- 00:31:50the free list is instead doubly linked
- 00:31:53and circular
- 00:31:54so instead of just being the singly
- 00:31:56linked thing um it's doubly linked and
- 00:31:59circular and
- 00:32:02the idea here is that we are able to
- 00:32:05leak
- 00:32:06a heap address this says leak heap
- 00:32:09addresses this should be leak lib c
- 00:32:11addresses so we're able to leak
- 00:32:13addresses
- 00:32:14uh of libsy uh by doing this and that
- 00:32:18that doesn't sound correct right because
- 00:32:20we're only really dealing with stuff in
- 00:32:21the heap
- 00:32:23um but this works because
- 00:32:26uh the heap has to keep track of where
- 00:32:29the free list is
- 00:32:30so they're the the head of the free list
- 00:32:33is actually
- 00:32:34in libsy itself so there's a there's a
- 00:32:37fake chunk in libsy
- 00:32:39so that the heap can kind of keep track
- 00:32:41of where the free list lives
- 00:32:43so this is kind of what this looks like
- 00:32:45so there's this
- 00:32:46this gray chunk that's like not a real
- 00:32:48chunk
- 00:32:49that lives somewhere in libsy in the in
- 00:32:52the
- 00:32:53main arena struct and um
- 00:32:58uh when we have things in the free list
- 00:33:00the forward pointer of this
- 00:33:02um of this like fake chunk just points
- 00:33:06to the next thing
- 00:33:07in the in the free list uh and the
- 00:33:10like backwards pointers are set up in
- 00:33:12such a way that the the linked list like
- 00:33:14makes sense
- 00:33:15and is circular so if there's only one
- 00:33:18chunk in there like this
- 00:33:20notice that if we were to print the
- 00:33:23forward
- 00:33:24pointer it would sorry print the forward
- 00:33:27pointer of the free chunk
- 00:33:29we would be printing a lib c address
- 00:33:31because
- 00:33:32the heap arena bin head here
- 00:33:35is in lib c so
- 00:33:39um this gives us a really easy way to
- 00:33:42leak libc addresses um
- 00:33:45just using the heap which sounds super
- 00:33:48spooky
- 00:33:49um yeah so printing the forward or
- 00:33:52backward pointer
- 00:33:53um of a free chunk
- 00:33:56um that's like
- 00:34:00this size and points to the right place
- 00:34:02is going to leak a libsy address to us
- 00:34:05um and this address is going to be like
- 00:34:07some address
- 00:34:08uh offset in the main arena struct which
- 00:34:11is
- 00:34:12uh you can just find the main arena
- 00:34:13struct in ellipses
- 00:34:15like there's a there's a symbol for it
- 00:34:17and you can just look it up
- 00:34:19cool okay that's that's the end of the
- 00:34:21talk i'll open it for questions now i
- 00:34:23i realize that this talk uh may be a bit
- 00:34:26confusing
- 00:34:27um just because the topic material is
- 00:34:30kind of hard
- 00:34:31to wrap your head around so
- 00:34:34yeah if anybody has questions
- heap
- memory management
- malloc
- exploitation
- use after free
- double free
- fast bins
- libc
- binary exploitation
- C programming