Intro to Heap Exploitation

00:34:38
https://www.youtube.com/watch?v=nnF4Avttbns

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

Dapatkan akses instan ke ringkasan video YouTube gratis yang didukung oleh AI!
Teks
en
Gulir Otomatis:
  • 00:00:01
    okay this is intro to heap
  • 00:00:03
    um it's one of the uh spookier topics in
  • 00:00:06
    binary exploitation
  • 00:00:08
    but hopefully it shouldn't be very
  • 00:00:10
    spooky during this talk
  • 00:00:12
    so uh we'll start by kind of going
  • 00:00:15
    through
  • 00:00:16
    what the heap is and like how the heap
  • 00:00:20
    is designed and then we'll go into the
  • 00:00:22
    actual
  • 00:00:23
    like using it to exploit stuff
  • 00:00:26
    but understanding what the heap is and
  • 00:00:29
    like how it works is
  • 00:00:30
    pretty key to understanding all the
  • 00:00:32
    exploits so we'll go pretty far in depth
  • 00:00:35
    on that first
  • 00:00:38
    okay so what exactly is a heap
  • 00:00:41
    and what does it do right when we're
  • 00:00:43
    writing
  • 00:00:44
    c code we want some some way that we can
  • 00:00:47
    ask for
  • 00:00:48
    a kind of memory that's not going to go
  • 00:00:51
    away after our function has finished
  • 00:00:53
    executing
  • 00:00:55
    and really what we want is we just want
  • 00:00:58
    like some api that we can ask hey give
  • 00:01:01
    me
  • 00:01:01
    n bytes of memory and then it will give
  • 00:01:04
    us back
  • 00:01:05
    a pointer to in bytes of memory um
  • 00:01:08
    and then we can use that however we want
  • 00:01:10
    and then when we're finally done with
  • 00:01:12
    that memory we just give it back
  • 00:01:14
    so that's essentially the api that we
  • 00:01:15
    want um
  • 00:01:17
    and the question is how do we how do we
  • 00:01:20
    implement this and it turns out to be
  • 00:01:24
    harder than you may expect so
  • 00:01:28
    um one of the main problems with this
  • 00:01:31
    uh is that the like a program can only
  • 00:01:34
    request entire pr
  • 00:01:35
    uh entire pages from from the operating
  • 00:01:38
    system so um
  • 00:01:40
    if you if your program needs more memory
  • 00:01:42
    it can only request
  • 00:01:44
    memory in uh big chunks of
  • 00:01:48
    4096 bytes which
  • 00:01:52
    usually we're not going to want big
  • 00:01:54
    chunks of 4096 bytes we may want
  • 00:01:57
    like 20 bytes or something like that so
  • 00:02:01
    uh really what we want to do is
  • 00:02:04
    take these big chunks and break them up
  • 00:02:08
    into smaller chunks
  • 00:02:10
    and then have some code that manages uh
  • 00:02:13
    these smaller chunks for us so that we
  • 00:02:15
    don't have to deal with
  • 00:02:17
    uh making sure that we don't allocate
  • 00:02:19
    the same memory twice or something like
  • 00:02:20
    that
  • 00:02:21
    so we essentially just want uh like a
  • 00:02:23
    program that's going to solve all these
  • 00:02:25
    problems for us
  • 00:02:27
    that we don't have to worry about and
  • 00:02:29
    that's what the heap does
  • 00:02:32
    so the way that the heap works kind of
  • 00:02:35
    under
  • 00:02:36
    the hood is it it starts off by
  • 00:02:39
    requesting a really big
  • 00:02:40
    chunk called the top chunk or the
  • 00:02:42
    wilderness chunk
  • 00:02:45
    and this is just like a massive
  • 00:02:47
    contiguous region of memory that the
  • 00:02:49
    heap has allocated
  • 00:02:51
    um and when when we ask it for
  • 00:02:54
    um smaller regions so say i ask for 50
  • 00:02:57
    bytes from the heap
  • 00:02:59
    what it's going to do is it's going to
  • 00:03:00
    split the wilderness chunk
  • 00:03:03
    into a a little region of 50 bytes
  • 00:03:07
    and a big region that's like the rest of
  • 00:03:11
    the wilderness chunk
  • 00:03:12
    and then it's just going to hand those
  • 00:03:14
    50 bytes to us
  • 00:03:16
    so um
  • 00:03:19
    like subsequent calls to to the uh
  • 00:03:22
    malloc which is the like allocation api
  • 00:03:25
    call
  • 00:03:26
    um we'll just like break off a piece of
  • 00:03:29
    the wilderness chunk and hand it to us
  • 00:03:31
    and there's this uh
  • 00:03:36
    struct in in libsy called the heap
  • 00:03:40
    main arena which kind of keeps track of
  • 00:03:43
    all of the high level heap metadata
  • 00:03:45
    which
  • 00:03:46
    uh the heap main arena keeps track of
  • 00:03:49
    like where the wilderness chunk lives
  • 00:03:51
    and um some other stuff that we'll talk
  • 00:03:54
    about later
  • 00:03:55
    but the arena's not terribly important
  • 00:03:57
    in this talk
  • 00:04:00
    okay so i just said that the arena isn't
  • 00:04:03
    terribly important but here i have a
  • 00:04:05
    picture describing what it looks like
  • 00:04:07
    so um the main arena is just destruct it
  • 00:04:11
    has
  • 00:04:11
    like some pointers in it um to
  • 00:04:14
    various like heap metadata things and
  • 00:04:17
    the important thing in this picture is
  • 00:04:19
    that there's a
  • 00:04:19
    there's just a pointer to the top chunk
  • 00:04:22
    of the main arena so
  • 00:04:24
    uh when you want to break off memory it
  • 00:04:26
    just looks up this pointer in the main
  • 00:04:28
    arena struct
  • 00:04:29
    breaks off some memory there and hands
  • 00:04:31
    it back to
  • 00:04:34
    back to like the user program
  • 00:04:37
    okay so um
  • 00:04:40
    that's allocation allocation kind of
  • 00:04:43
    makes sense right
  • 00:04:44
    uh when we when we we just like cut some
  • 00:04:47
    memory off
  • 00:04:48
    the top chunk shrinks um and then we
  • 00:04:50
    give that memory back
  • 00:04:52
    so um where it gets kind of
  • 00:04:55
    kind of complicated is when we talk
  • 00:04:57
    about
  • 00:04:58
    um i guess there's another picture of uh
  • 00:05:01
    allocation i don't know why i have so
  • 00:05:03
    many pictures of this but yeah this is
  • 00:05:04
    this is what it looks like if you were
  • 00:05:06
    to allocate two chunks
  • 00:05:07
    you get like chunk a chunk b and then
  • 00:05:09
    you have the top chunk down here which
  • 00:05:11
    is like
  • 00:05:11
    really big so it's just splitting the
  • 00:05:14
    chunks
  • 00:05:15
    kind of sequentially as you as you might
  • 00:05:18
    expect
  • 00:05:21
    so where it gets complicated is when we
  • 00:05:23
    want to give the memory back
  • 00:05:25
    right so say say we've allocated 50
  • 00:05:28
    bytes
  • 00:05:29
    uh and we've we've uh
  • 00:05:32
    finished using these 50 bytes that we
  • 00:05:34
    were using
  • 00:05:35
    we want to give it back to the heap so
  • 00:05:37
    the heap can reuse this memory
  • 00:05:40
    um and
  • 00:05:43
    uh this is this is where it gets kind of
  • 00:05:46
    hard right because
  • 00:05:47
    what we really want to do is kind of
  • 00:05:49
    reattach the memory
  • 00:05:51
    to the to the top chunk um
  • 00:05:54
    but we can't do this in most cases
  • 00:05:57
    unless the the chunk that we're freeing
  • 00:05:59
    is like
  • 00:06:00
    right next to the top chunk in memory
  • 00:06:02
    like they're they're literally touching
  • 00:06:04
    and then we can
  • 00:06:04
    just make them into one big chunk if
  • 00:06:07
    they're like disjoint in memory we can't
  • 00:06:09
    recombine them so we have to do
  • 00:06:10
    something
  • 00:06:11
    uh like more interesting in order to
  • 00:06:14
    put them together so here's a case where
  • 00:06:18
    like we can't recombine the the
  • 00:06:20
    top chunk in the chunk that we're
  • 00:06:21
    freeing right so if we have like
  • 00:06:23
    chunk a that we're freeing and there's
  • 00:06:25
    chunk b in between them we can't
  • 00:06:27
    put chunk a back onto the top chunk
  • 00:06:29
    because
  • 00:06:31
    chunk b is in the way if we were to free
  • 00:06:34
    chunk b then we could like
  • 00:06:37
    combine them all back into one chunk but
  • 00:06:40
    until we free chunk b
  • 00:06:41
    we can't do that
  • 00:06:45
    so instead what we're going to do is
  • 00:06:47
    we're going to
  • 00:06:49
    take the free chunk and put it in a list
  • 00:06:51
    of free chunks
  • 00:06:53
    and then when we when we allocate later
  • 00:06:55
    we'll just look through this list
  • 00:06:57
    and see if there's any suitably sized
  • 00:06:59
    chunks
  • 00:07:01
    that we can that we can give to the user
  • 00:07:04
    um and if if there is no such
  • 00:07:06
    suitably sized chunk then we will take
  • 00:07:08
    it from the top chunk
  • 00:07:10
    um now if you're actually writing
  • 00:07:13
    like a user program right you would want
  • 00:07:17
    this like free list lookup code to be
  • 00:07:20
    extremely fast right you don't want your
  • 00:07:22
    code to be
  • 00:07:23
    uh stuck in libsy looking for uh like
  • 00:07:27
    free memory in the in the free list the
  • 00:07:30
    whole time
  • 00:07:31
    um so the the malloc
  • 00:07:34
    uh like heap designers have have really
  • 00:07:38
    like gone out of their way to make this
  • 00:07:40
    efficient um
  • 00:07:41
    and a lot of this efficiency is what
  • 00:07:43
    we're going to be exploiting
  • 00:07:46
    okay so this is kind of what i was
  • 00:07:48
    describing in
  • 00:07:49
    in the last thing where it's like you
  • 00:07:51
    have a list of free chunks
  • 00:07:53
    and in this implementation the chunks
  • 00:07:56
    have like no restriction on
  • 00:07:58
    uh what size they are you just put all
  • 00:08:00
    the free chunks in a list
  • 00:08:02
    right and the issue here is that if i'm
  • 00:08:04
    looking for a chunk of size
  • 00:08:06
    0x 100 i'm going to have to look through
  • 00:08:10
    like all the chunks until i find one
  • 00:08:13
    that is bigger than 0x100
  • 00:08:15
    right so um
  • 00:08:18
    this is going to be really slow because
  • 00:08:19
    it like worst case i have to look
  • 00:08:21
    through
  • 00:08:21
    the entire free list to
  • 00:08:25
    to allocate my chunk like i may look
  • 00:08:27
    through the entire free list
  • 00:08:29
    determine there was no free chunk of
  • 00:08:31
    this size and then just allocate from
  • 00:08:33
    the top chunk anyway so i just wasted a
  • 00:08:35
    bunch of time
  • 00:08:36
    um so so this is not efficient enough we
  • 00:08:38
    need to come up with a
  • 00:08:40
    much more efficient way to do heap
  • 00:08:43
    allocations
  • 00:08:46
    so the the main idea that we use
  • 00:08:50
    is we bucket the chunks
  • 00:08:53
    by their size so for every size chunk
  • 00:08:57
    there is a separate free list um and
  • 00:08:59
    these
  • 00:09:00
    these free lists are called bins so
  • 00:09:03
    every every size chunk goes in a
  • 00:09:05
    different bin
  • 00:09:06
    um and uh
  • 00:09:11
    the the idea is like um
  • 00:09:15
    if if the the bins are kind of done by
  • 00:09:18
    size
  • 00:09:19
    in order to find a chunk of a specific
  • 00:09:22
    size
  • 00:09:23
    we only have to look through the bin of
  • 00:09:25
    that size
  • 00:09:28
    and then we we greatly reduce the number
  • 00:09:30
    of free chunks we have to look through
  • 00:09:32
    because we're only looking through like
  • 00:09:34
    the portion that are
  • 00:09:36
    probably the right size um
  • 00:09:40
    and in fact uh there are some
  • 00:09:43
    some uh bins called fast bins
  • 00:09:46
    in the heap which are for really small
  • 00:09:49
    chunks so
  • 00:09:50
    size like 0x10 to 0xb0
  • 00:09:55
    and this is essentially like the the
  • 00:09:58
    idea is
  • 00:09:59
    that allocations of small size are made
  • 00:10:02
    very frequently
  • 00:10:04
    so we want the uh the like free list
  • 00:10:07
    lookup code to be
  • 00:10:08
    really simple and really fast
  • 00:10:12
    and because it's really simple and
  • 00:10:13
    really fast
  • 00:10:15
    it's easy to exploit for ctfs because
  • 00:10:18
    uh the code is is pretty simple um
  • 00:10:24
    yeah so so um a fast bin
  • 00:10:27
    right as i was talking about on the
  • 00:10:29
    previous slide
  • 00:10:30
    it's just a singly linked list of free
  • 00:10:33
    chunks that are all of the same size
  • 00:10:35
    um so when you when you allocate
  • 00:10:39
    for a small chunk size uh what it's
  • 00:10:42
    going to do
  • 00:10:42
    is just let's say let's say i'm trying
  • 00:10:44
    to allocate a chunk of size
  • 00:10:46
    like uh 25 right it's going to round
  • 00:10:50
    that up
  • 00:10:50
    to the nearest small chunk size which
  • 00:10:53
    would be
  • 00:10:54
    uh 32 bytes um
  • 00:10:57
    because it's a multiple of eight
  • 00:11:00
    so 32 bytes um
  • 00:11:04
    and then we just go to the fast bin for
  • 00:11:07
    things that are size 32 bytes
  • 00:11:10
    and just find uh the first thing in the
  • 00:11:13
    fast bin
  • 00:11:14
    because that element is free so we just
  • 00:11:16
    we just pull that
  • 00:11:17
    element out and now we have somewhere to
  • 00:11:22
    put our uh 25 bytes
  • 00:11:25
    so here's here's what a uh what this
  • 00:11:27
    this
  • 00:11:28
    fast bin looks like so we have um
  • 00:11:30
    essentially just a
  • 00:11:31
    linked list of free chunks all of the
  • 00:11:34
    same size
  • 00:11:35
    right so uh when we
  • 00:11:39
    uh allocate something of size 0x80
  • 00:11:43
    we're just going to pull free chunk a
  • 00:11:45
    because it's
  • 00:11:46
    like it's unallocated memory and it's of
  • 00:11:49
    the right size
  • 00:11:50
    and then we just kind of shift the
  • 00:11:52
    linked list over one
  • 00:11:55
    and then if we allocate again we'll get
  • 00:11:57
    free chunk b
  • 00:11:59
    um okay and so
  • 00:12:02
    uh i guess also we should say if we were
  • 00:12:06
    to
  • 00:12:06
    free some other chunk let's call it
  • 00:12:10
    chunk d
  • 00:12:11
    we would put free chunk d in front of
  • 00:12:13
    free chunk a
  • 00:12:14
    so it kind of gets pushed on to the
  • 00:12:16
    front
  • 00:12:18
    and then if we were to allocate again we
  • 00:12:20
    would get free chunk d
  • 00:12:21
    and then we get free chunk a free chunk
  • 00:12:23
    b and free chunk c
  • 00:12:25
    and then if we completely exhaust the
  • 00:12:27
    fast bin will start pulling stuff off of
  • 00:12:29
    the top chunk again
  • 00:12:31
    okay so uh yeah the idea is that every
  • 00:12:35
    chunk in the in the list is the same
  • 00:12:37
    size
  • 00:12:38
    so we don't have to do this really slow
  • 00:12:40
    search we can just take the head of the
  • 00:12:42
    list
  • 00:12:46
    there are other bin types in the heap
  • 00:12:49
    i'll talk about one later but uh they're
  • 00:12:52
    not
  • 00:12:52
    really important uh they they come up in
  • 00:12:56
    a lot of more complicated attacks but
  • 00:12:59
    we probably won't talk about those
  • 00:13:01
    attacks today
  • 00:13:02
    um it it the only the only real
  • 00:13:06
    difference is that uh the other bins are
  • 00:13:09
    doubly linked and circular so uh instead
  • 00:13:12
    of just being a singly linked list like
  • 00:13:14
    the
  • 00:13:14
    fast bins um there's like a backward
  • 00:13:17
    point or two that points backwards
  • 00:13:19
    um and it's also like a circular list
  • 00:13:23
    um but yeah that won't really be
  • 00:13:26
    important until the end of the talk and
  • 00:13:28
    we'll talk about it later again
  • 00:13:30
    okay so that's the kind of basic idea of
  • 00:13:34
    a heap in general
  • 00:13:35
    um we'll talk quickly about the
  • 00:13:38
    specifics of how
  • 00:13:39
    the uh glib c heap is implemented
  • 00:13:42
    because that's probably what you would
  • 00:13:44
    be exploiting in a ctf
  • 00:13:46
    so uh first of all the
  • 00:13:49
    um in glib c when when we have these
  • 00:13:53
    um these uh the free list
  • 00:13:56
    uh the the pointer the linked list
  • 00:13:59
    pointer is called
  • 00:14:00
    fd for forward um
  • 00:14:03
    and the the uh the backward pointer
  • 00:14:06
    if there is one is called bk for
  • 00:14:08
    backward um
  • 00:14:11
    so there's there's those two things to
  • 00:14:13
    be aware of and then there's also
  • 00:14:15
    the fact that every chunk is allocated
  • 00:14:18
    with an additional eight bytes
  • 00:14:20
    uh preceding it specifying the size so
  • 00:14:23
    um here's a picture of like um a free
  • 00:14:26
    chunk in an allocated chunk so
  • 00:14:28
    when we have an allocated chunk we just
  • 00:14:30
    have a chunk with a bunch of user data
  • 00:14:33
    and the the pointer points to the start
  • 00:14:35
    of the user data
  • 00:14:36
    and then eight bytes uh the eight bytes
  • 00:14:39
    before the user data
  • 00:14:40
    there's like a little size um
  • 00:14:43
    attached to it so um
  • 00:14:47
    essentially when you when you allocate
  • 00:14:49
    uh like
  • 00:14:50
    say 20 bytes you actually get 28 bytes
  • 00:14:55
    because you're you're getting this size
  • 00:14:57
    thing that you're unable to use
  • 00:14:59
    when you're actually writing user data
  • 00:15:01
    into it and then
  • 00:15:03
    the idea is that when you free a chunk
  • 00:15:07
    instead of keeping track of the linked
  • 00:15:10
    list somewhere else
  • 00:15:11
    you just turn the chunk into a linked
  • 00:15:13
    list node
  • 00:15:14
    so uh when when a chunk is free
  • 00:15:18
    instead of having user data in it it has
  • 00:15:21
    all of the
  • 00:15:21
    like chunk metadata in it like the
  • 00:15:23
    forward pointer and backward pointer
  • 00:15:25
    and like the size of the uh
  • 00:15:28
    of the next chunk and the size of the
  • 00:15:30
    previous chunk
  • 00:15:33
    and a bunch of other stuff like this but
  • 00:15:35
    we only really care about the forward
  • 00:15:36
    pointer in this talk
  • 00:15:38
    so remember this is just the um in the
  • 00:15:41
    free list
  • 00:15:42
    the forward pointer just points to the
  • 00:15:44
    next free chunk
  • 00:15:46
    um okay so
  • 00:15:50
    we'll note now talk about um kind of
  • 00:15:54
    how these attacks are going to work so
  • 00:15:56
    there's there's generally two
  • 00:15:58
    methods of um
  • 00:16:01
    of doing like a heap exploit one is
  • 00:16:05
    uh kind of trying to get overlapping
  • 00:16:07
    allocations
  • 00:16:09
    so we we try to cause the heap to
  • 00:16:11
    allocate
  • 00:16:12
    two structs at the same underlying
  • 00:16:14
    memory
  • 00:16:16
    so we may allocate like an object
  • 00:16:19
    and a string at the same memory and when
  • 00:16:22
    we
  • 00:16:23
    when we write to the string it's going
  • 00:16:25
    to mess up the object
  • 00:16:27
    and vice versa if we write to the object
  • 00:16:29
    it's going to
  • 00:16:31
    mess with the string so
  • 00:16:34
    once we have kind of overlapping
  • 00:16:36
    allocations of two different structs
  • 00:16:39
    we can do uh several things to
  • 00:16:42
    um get control of the return uh
  • 00:16:46
    uh of the instruction pointer um
  • 00:16:50
    but the the general idea is we're either
  • 00:16:53
    going to overwrite a function pointer
  • 00:16:55
    in the struct by say writing to a string
  • 00:16:59
    and there's an object that has a
  • 00:17:01
    function pointer in it
  • 00:17:03
    and then we can we can call that
  • 00:17:04
    function and we will
  • 00:17:06
    then have control over the instruction
  • 00:17:08
    pointer or
  • 00:17:09
    we just uh do something more interesting
  • 00:17:12
    and
  • 00:17:14
    cause a stack overflow by like
  • 00:17:17
    corrupting the object in a in a really
  • 00:17:19
    creative way so maybe maybe there's like
  • 00:17:21
    a uh maybe our our struct
  • 00:17:25
    is a string with a length on it or
  • 00:17:27
    something like that
  • 00:17:28
    and we're able to overwrite the length
  • 00:17:30
    field in this struct
  • 00:17:32
    then we're able to cause like a stack
  • 00:17:34
    buffer overflow and we just have to
  • 00:17:36
    exploit things normally
  • 00:17:40
    okay so this is kind of what this
  • 00:17:42
    picture looks like we have
  • 00:17:45
    like an object here on the left and a
  • 00:17:47
    string here on the right and they have
  • 00:17:48
    the exact same
  • 00:17:49
    underlying memory so if we were to write
  • 00:17:53
    into the string we're going to like
  • 00:17:54
    overwrite
  • 00:17:55
    the objects like v table and the objects
  • 00:17:59
    members and generally just cause
  • 00:18:03
    really bad things to happen in the
  • 00:18:04
    program
  • 00:18:06
    we won't really focus on what you do at
  • 00:18:09
    this point we'll more focus on
  • 00:18:12
    how to actually get this overlapping
  • 00:18:14
    allocation in the first place
  • 00:18:16
    because once you have the overlapping
  • 00:18:17
    allocation it kind of just reduces to
  • 00:18:20
    normal binary exploitation okay
  • 00:18:23
    and the other the other idea is uh
  • 00:18:27
    instead of doing overlapping allocations
  • 00:18:29
    we just try to
  • 00:18:31
    um get the heap to allocate memory
  • 00:18:34
    that's outside of the heap
  • 00:18:36
    so uh for example we get the heap to
  • 00:18:38
    allocate
  • 00:18:40
    uh like stack memory and we we can
  • 00:18:43
    overwrite the return address by just
  • 00:18:45
    writing into the chunk that it gives us
  • 00:18:47
    or we try to get the heap to allocate us
  • 00:18:49
    like global offset table
  • 00:18:51
    uh memory as as our allocation and then
  • 00:18:54
    we
  • 00:18:55
    when we write into our struct we'll be
  • 00:18:57
    overwriting uh global offset table
  • 00:18:59
    entries
  • 00:19:01
    um so these these are the kind of two
  • 00:19:04
    main ideas
  • 00:19:04
    is um having
  • 00:19:08
    like overlapping allocations and having
  • 00:19:11
    uh like arbitrary forged
  • 00:19:14
    chunks at uh attacker-controlled
  • 00:19:17
    addresses
  • 00:19:19
    okay so now we actually get into um
  • 00:19:22
    some specific attacks so the first one
  • 00:19:24
    that we'll talk about
  • 00:19:25
    is a use after free um
  • 00:19:29
    so this is kind of the simplest heap
  • 00:19:33
    exploit
  • 00:19:34
    um and we'll first talk about using a
  • 00:19:37
    use after free to get overlapping
  • 00:19:39
    allocations
  • 00:19:41
    so uh the idea of a use after free
  • 00:19:45
    is that we're allowed to uh read or
  • 00:19:47
    write
  • 00:19:48
    to um an allocation after it's already
  • 00:19:51
    been freed
  • 00:19:52
    so um we we have some object and memory
  • 00:19:57
    we free it uh and then we we continue
  • 00:20:01
    doing things to that object as if it's
  • 00:20:03
    still valid memory
  • 00:20:06
    and the idea here is that
  • 00:20:10
    the next time we call malloc with this
  • 00:20:12
    specific
  • 00:20:13
    chunk size we're going to get this
  • 00:20:15
    memory that we've just freed
  • 00:20:17
    so we kind of get an overlapping
  • 00:20:20
    allocation for free
  • 00:20:21
    um just by like we have we have this
  • 00:20:25
    chunk that
  • 00:20:26
    has like uh uh is being used as
  • 00:20:29
    as if it's valid memory although it's
  • 00:20:31
    already been freed
  • 00:20:32
    and this chunk is also uh in the free
  • 00:20:35
    list
  • 00:20:36
    so when we allocate next um
  • 00:20:40
    a chunk of size 0x80 we're going to
  • 00:20:43
    um get back the same chunk so we have
  • 00:20:46
    like uaf
  • 00:20:47
    chunk a and then we have allocated chunk
  • 00:20:50
    a and they they have the same memory
  • 00:20:52
    um so now if we do something to the uaf
  • 00:20:55
    chunk a
  • 00:20:56
    um it does the same thing to the
  • 00:20:59
    allocated chunk a and vice versa so
  • 00:21:01
    this is the same thing like say
  • 00:21:03
    allocated chunk a is a string and uaf
  • 00:21:05
    chunk a is
  • 00:21:06
    an object uh we can mess with the object
  • 00:21:09
    by writing to the string
  • 00:21:12
    okay so um that's kind of the
  • 00:21:16
    the um the idea of
  • 00:21:19
    uh like the overlapping allocation uaf
  • 00:21:22
    it's kind of
  • 00:21:23
    just for free just by allocating again
  • 00:21:26
    so how do we how do we forge a chunk
  • 00:21:28
    uh into like an arbitrary memory address
  • 00:21:33
    so notice that by writing to the free
  • 00:21:35
    chunk we can
  • 00:21:36
    we can mess with the linked list
  • 00:21:38
    pointers
  • 00:21:40
    so uh if we have our uaf
  • 00:21:43
    chunk uh on the left here uh and we're
  • 00:21:47
    able to write into this chunk as if it's
  • 00:21:49
    still
  • 00:21:49
    a valid allocation um when we write to
  • 00:21:52
    the first eight bytes of this chunk
  • 00:21:54
    we're
  • 00:21:54
    actually going to overwrite the uh the
  • 00:21:57
    forward pointer
  • 00:21:58
    um so this is also going to overwrite
  • 00:22:02
    the forward pointer for the chunk in the
  • 00:22:04
    free list
  • 00:22:04
    because they are the same memory right
  • 00:22:08
    so the idea is that when we when we
  • 00:22:11
    overwrite
  • 00:22:12
    this this forward pointer um
  • 00:22:15
    it's actually kind of saying hey there's
  • 00:22:18
    um in the free list
  • 00:22:22
    i'm pointing to some some random memory
  • 00:22:24
    address that's attacker controlled
  • 00:22:26
    so let's say we have we have like
  • 00:22:30
    um we have like a free chunk and then we
  • 00:22:33
    have
  • 00:22:34
    our our chunk that's our malicious chunk
  • 00:22:37
    and the malicious chunk
  • 00:22:38
    is kind of the uh um
  • 00:22:42
    i get i guess it's the one that has the
  • 00:22:44
    the same memory as the uaf
  • 00:22:46
    chunk and then we have uh we've
  • 00:22:48
    overwritten
  • 00:22:49
    the forward pointer of this of this
  • 00:22:51
    malicious chunk
  • 00:22:52
    um so now the the heap is going to think
  • 00:22:55
    that there's another element in the free
  • 00:22:57
    list
  • 00:22:58
    and it's just off wherever we tell it
  • 00:23:01
    so um we could overwrite the forward
  • 00:23:05
    pointer with like a global offset table
  • 00:23:07
    address and now when we when we allocate
  • 00:23:10
    uh the forged chunk we will get a global
  • 00:23:13
    offset table
  • 00:23:14
    uh address which is really bad
  • 00:23:18
    um so yeah um
  • 00:23:22
    after allocating like so so the idea is
  • 00:23:25
    that we will allocate this free chunk a
  • 00:23:27
    we'll get that memory well i'll allocate
  • 00:23:30
    this malicious chunk
  • 00:23:31
    and we'll get that memory and then we
  • 00:23:34
    allocate again
  • 00:23:34
    and we get the forged chunk that's like
  • 00:23:36
    not in the heap
  • 00:23:37
    uh so we we end up allocating memory
  • 00:23:41
    that's at an arbitrary address and then
  • 00:23:43
    we can use this to
  • 00:23:45
    write to an arbitrary address so
  • 00:23:48
    yeah then then we can just use this
  • 00:23:50
    chunk to overwrite arbitrary memory like
  • 00:23:52
    the global offset table or the return
  • 00:23:54
    address
  • 00:23:55
    um or whatever target you want
  • 00:23:58
    really um so here's a specific example
  • 00:24:02
    we would we would just overwrite this
  • 00:24:04
    forward pointer with the global offset
  • 00:24:06
    table address
  • 00:24:07
    um and then this forged chunk will
  • 00:24:11
    uh be in the global offset table
  • 00:24:14
    so when we write to it we'll be
  • 00:24:16
    overwriting global offset table entries
  • 00:24:22
    okay so um in practice this doesn't
  • 00:24:26
    quite work
  • 00:24:27
    because malloc checks to make sure that
  • 00:24:29
    the size of
  • 00:24:32
    the size member that's before the chunk
  • 00:24:35
    matches the the bin size that we're
  • 00:24:37
    allocating so
  • 00:24:39
    uh if we're if we're doing this exploit
  • 00:24:42
    on
  • 00:24:42
    the um on the
  • 00:24:46
    xerox 80 fast then we would expect
  • 00:24:49
    the or the heap expects this size
  • 00:24:52
    argument
  • 00:24:52
    up here to be 0x80 um so if we were to
  • 00:24:57
    uh point this uh if we if the the
  • 00:25:01
    the forged chunk points to something
  • 00:25:03
    where
  • 00:25:04
    the eight bytes preceding it are not
  • 00:25:06
    0x80
  • 00:25:07
    uh the program is going to stop running
  • 00:25:10
    and say like hey you have a heap error
  • 00:25:12
    um so we need to
  • 00:25:15
    uh the way that we get around this is we
  • 00:25:17
    we write 0x80 somewhere
  • 00:25:20
    in memory and then we just point to
  • 00:25:22
    eight bytes past that
  • 00:25:24
    um and then when we allocate the forged
  • 00:25:27
    chunk it
  • 00:25:28
    everything works out and the heaps is
  • 00:25:30
    fine
  • 00:25:32
    uh okay so now we talk about double
  • 00:25:36
    freeze
  • 00:25:36
    um double freeze are uh pretty similar
  • 00:25:39
    to a use after free
  • 00:25:41
    it's just a little bit more complicated
  • 00:25:44
    so the idea of a double free is we're
  • 00:25:47
    allowed to write to already allocated
  • 00:25:50
    chunks
  • 00:25:51
    and we're able to free a pointer twice
  • 00:25:55
    so as you may notice from the name
  • 00:25:58
    double free we are freeing something
  • 00:26:02
    twice
  • 00:26:03
    okay so um
  • 00:26:06
    the idea here is that if you if you free
  • 00:26:10
    some chunk a twice uh then you get
  • 00:26:13
    this chunk a twice in the free list
  • 00:26:16
    right
  • 00:26:16
    and if you think about it this is
  • 00:26:19
    creating
  • 00:26:20
    a like um a cycle in this linked list
  • 00:26:24
    because
  • 00:26:25
    free chunk a points to free chunk a
  • 00:26:28
    which points to free chunk a which
  • 00:26:30
    points to free chunk a and so on
  • 00:26:32
    so if we were to keep allocating we
  • 00:26:35
    would just get free chunk a
  • 00:26:36
    over and over and over again so
  • 00:26:40
    um this kind of just gives us uh the
  • 00:26:43
    the overlapping allocations for free
  • 00:26:45
    right because if we just allocate twice
  • 00:26:47
    we get the same exact memory
  • 00:26:50
    and if we allocate however many times we
  • 00:26:52
    want we still get the same exact memory
  • 00:26:56
    so yeah if we allocate a chunk of size
  • 00:26:59
    0x80
  • 00:27:00
    we just get uh chunk a um
  • 00:27:07
    and then uh if we were to
  • 00:27:10
    uh what is this slide saying the slide
  • 00:27:14
    doesn't seem correct
  • 00:27:15
    uh we allocate a chunk of size 0x80 we
  • 00:27:19
    get free chunk a
  • 00:27:20
    that's correct uh yeah the head of the
  • 00:27:23
    list just stays free chunk a because
  • 00:27:25
    this is a cyclic
  • 00:27:26
    list right um so if we allocate
  • 00:27:30
    again we just get chunk a again
  • 00:27:34
    um and yeah this is enough for an
  • 00:27:36
    overlapping allocation because we just
  • 00:27:38
    every time we allocate something inside
  • 00:27:40
    0x80 we get chunk a
  • 00:27:42
    from now on
  • 00:27:45
    okay so uh now we we do the
  • 00:27:49
    um the forged chunk case and this this
  • 00:27:52
    kind of just reduces
  • 00:27:54
    to the uaf so
  • 00:27:57
    um if we uh have this
  • 00:28:00
    this uh like cyclic thing when we
  • 00:28:04
    when we allocate uh something of size
  • 00:28:06
    0x80
  • 00:28:07
    we get chunk a and chunk a is still in
  • 00:28:10
    the free list
  • 00:28:12
    so when we when we overwrite the forward
  • 00:28:14
    pointer
  • 00:28:15
    of the allocated chunk uh or i guess
  • 00:28:18
    when we overwrite the first eight bytes
  • 00:28:20
    of the allocated chunk
  • 00:28:21
    we're overriding forward pointer of the
  • 00:28:23
    free chunk um
  • 00:28:25
    so this messes with the free list again
  • 00:28:27
    and we can just forge a chunk again
  • 00:28:31
    okay so again in practice this has some
  • 00:28:35
    issues
  • 00:28:36
    so the heap has checks to make sure that
  • 00:28:38
    you're not
  • 00:28:39
    freeing the head of the free list so
  • 00:28:41
    essentially
  • 00:28:42
    the heap tries to make sure that you're
  • 00:28:44
    not making this
  • 00:28:46
    uh cyclic list with one
  • 00:28:49
    element um and in order to get around
  • 00:28:53
    this we just have to add an additional
  • 00:28:55
    chunk in between because it only checks
  • 00:28:58
    whether the head is the same as the
  • 00:29:00
    thing you're currently freeing it
  • 00:29:01
    doesn't actually check to make sure
  • 00:29:02
    you're not
  • 00:29:03
    introducing any cycle so
  • 00:29:06
    if we just put in a cycle of two chunks
  • 00:29:10
    then it works so if we
  • 00:29:11
    free a we free b we free a again
  • 00:29:15
    we get uh a points to b
  • 00:29:18
    points to a points to b points to a and
  • 00:29:20
    so on
  • 00:29:21
    so there's still a cycle it's just
  • 00:29:24
    length two now and
  • 00:29:25
    the exploit works the same way um
  • 00:29:30
    it's just we we can't do it with only
  • 00:29:32
    one node because the heap will notice
  • 00:29:34
    and crash the program
  • 00:29:37
    okay so uh i've said a lot of things
  • 00:29:41
    and i i feel like i should mention at
  • 00:29:44
    this point that
  • 00:29:45
    um the these heap exploits are very
  • 00:29:48
    dependent
  • 00:29:49
    on uh which libsy version you're using
  • 00:29:52
    so
  • 00:29:53
    depending on exactly
  • 00:29:56
    which version you're using you may have
  • 00:29:59
    a
  • 00:30:00
    varying difficulty trying to get these
  • 00:30:02
    attacks to work
  • 00:30:03
    so for example this check right here was
  • 00:30:07
    introduced in
  • 00:30:08
    some libc version and if you're using
  • 00:30:11
    a libsy version before that you don't
  • 00:30:13
    have to deal with this
  • 00:30:15
    and in later libsy versions there's more
  • 00:30:18
    and more checks
  • 00:30:19
    so depending on the lipsy version that
  • 00:30:22
    you're trying to attack
  • 00:30:23
    you have to get around more and more uh
  • 00:30:27
    complicated checks um
  • 00:30:31
    i won't really touch on exactly which
  • 00:30:33
    lipsy versions
  • 00:30:34
    things work on you'll probably just have
  • 00:30:36
    to
  • 00:30:38
    kind of figure that out yourself usually
  • 00:30:40
    you can just read the libsy source code
  • 00:30:43
    the malloc source code in particular is
  • 00:30:45
    not super complicated so it's
  • 00:30:48
    it's definitely understandable if you
  • 00:30:49
    know like basic c
  • 00:30:53
    okay so uh we we've kind of
  • 00:30:56
    touched on the two main exploit types
  • 00:30:59
    the use after free and double free
  • 00:31:02
    um generally work on all libsy versions
  • 00:31:06
    um and now we're gonna talk about
  • 00:31:09
    kind of more more advanced tactics so
  • 00:31:13
    use after free and double free are
  • 00:31:15
    generally the
  • 00:31:17
    most basic heap exploits
  • 00:31:21
    and you you will see them everywhere
  • 00:31:24
    some of the advanced tactics kind of get
  • 00:31:26
    really spooky
  • 00:31:27
    and i'm only really going to talk about
  • 00:31:29
    one because i think it's uh particularly
  • 00:31:32
    useful
  • 00:31:34
    okay so remember i said at the very
  • 00:31:36
    beginning of the talk
  • 00:31:37
    that uh when we're doing allocations and
  • 00:31:40
    freeze that are larger than fast bin
  • 00:31:43
    size
  • 00:31:44
    so 0x c 0
  • 00:31:47
    and bigger um
  • 00:31:50
    the free list is instead doubly linked
  • 00:31:53
    and circular
  • 00:31:54
    so instead of just being the singly
  • 00:31:56
    linked thing um it's doubly linked and
  • 00:31:59
    circular and
  • 00:32:02
    the idea here is that we are able to
  • 00:32:05
    leak
  • 00:32:06
    a heap address this says leak heap
  • 00:32:09
    addresses this should be leak lib c
  • 00:32:11
    addresses so we're able to leak
  • 00:32:13
    addresses
  • 00:32:14
    uh of libsy uh by doing this and that
  • 00:32:18
    that doesn't sound correct right because
  • 00:32:20
    we're only really dealing with stuff in
  • 00:32:21
    the heap
  • 00:32:23
    um but this works because
  • 00:32:26
    uh the heap has to keep track of where
  • 00:32:29
    the free list is
  • 00:32:30
    so they're the the head of the free list
  • 00:32:33
    is actually
  • 00:32:34
    in libsy itself so there's a there's a
  • 00:32:37
    fake chunk in libsy
  • 00:32:39
    so that the heap can kind of keep track
  • 00:32:41
    of where the free list lives
  • 00:32:43
    so this is kind of what this looks like
  • 00:32:45
    so there's this
  • 00:32:46
    this gray chunk that's like not a real
  • 00:32:48
    chunk
  • 00:32:49
    that lives somewhere in libsy in the in
  • 00:32:52
    the
  • 00:32:53
    main arena struct and um
  • 00:32:58
    uh when we have things in the free list
  • 00:33:00
    the forward pointer of this
  • 00:33:02
    um of this like fake chunk just points
  • 00:33:06
    to the next thing
  • 00:33:07
    in the in the free list uh and the
  • 00:33:10
    like backwards pointers are set up in
  • 00:33:12
    such a way that the the linked list like
  • 00:33:14
    makes sense
  • 00:33:15
    and is circular so if there's only one
  • 00:33:18
    chunk in there like this
  • 00:33:20
    notice that if we were to print the
  • 00:33:23
    forward
  • 00:33:24
    pointer it would sorry print the forward
  • 00:33:27
    pointer of the free chunk
  • 00:33:29
    we would be printing a lib c address
  • 00:33:31
    because
  • 00:33:32
    the heap arena bin head here
  • 00:33:35
    is in lib c so
  • 00:33:39
    um this gives us a really easy way to
  • 00:33:42
    leak libc addresses um
  • 00:33:45
    just using the heap which sounds super
  • 00:33:48
    spooky
  • 00:33:49
    um yeah so printing the forward or
  • 00:33:52
    backward pointer
  • 00:33:53
    um of a free chunk
  • 00:33:56
    um that's like
  • 00:34:00
    this size and points to the right place
  • 00:34:02
    is going to leak a libsy address to us
  • 00:34:05
    um and this address is going to be like
  • 00:34:07
    some address
  • 00:34:08
    uh offset in the main arena struct which
  • 00:34:11
    is
  • 00:34:12
    uh you can just find the main arena
  • 00:34:13
    struct in ellipses
  • 00:34:15
    like there's a there's a symbol for it
  • 00:34:17
    and you can just look it up
  • 00:34:19
    cool okay that's that's the end of the
  • 00:34:21
    talk i'll open it for questions now i
  • 00:34:23
    i realize that this talk uh may be a bit
  • 00:34:26
    confusing
  • 00:34:27
    um just because the topic material is
  • 00:34:30
    kind of hard
  • 00:34:31
    to wrap your head around so
  • 00:34:34
    yeah if anybody has questions
Tags
  • heap
  • memory management
  • malloc
  • exploitation
  • use after free
  • double free
  • fast bins
  • libc
  • binary exploitation
  • C programming