Home heap利用方式总结
Post
Cancel

heap利用方式总结

0x00 malloc workflow

heap-malloc_workflow.drawio

流程详细版

0x01 fastbin_dup

利用条件

程序存在double free漏洞

目的

  • fastbin array使用单链表实现,free的时候会对free-list进行检查,所以我们不能free同一个chunk两次。但是可以在两次free之间增加一次对其他chunk的free,从而绕过检查顺利执行,然后malloc三次,就得到了两个指向同一区域的指针

步骤

  • a = malloc(8) = 0x602010
  • b = malloc(8) = 0x602030
  • c = malloc(8) = 0x602050
  • free(a)
  • free(b)
  • free(a)
  • d = malloc(8) = 0x602010
  • e = malloc(8) = 0x602030
  • f = malloc(8) = 0x602010

图解

heap-fastbin_dup.drawio

高版本下的区别

libc大于2.27下,引入了tcache,所以需要先把tcache填满(size=7),然后用calloc申请内存。

calloc不请求tcache

0x02 fastbin_dup_into_stack

利用条件

程序存在double free漏洞

目的

接着fastbin_dup的思路,point d指向了一个还在fastbins array的chunk,对该chunk写入数据就可以覆盖该fastbin的结构,来获取一个指向任意地址的指针。如果可以对该指针读或者写的话,我们就有了任意地址读/写

步骤

  • unsigned long long stack_var = 0x20
  • a = malloc(8);b = malloc(8);c = malloc(8)
  • free(a);free(b);free(a)
  • d = malloc(8)
  • d = (unsigned long long) (((char*)&stack_var) - 8)
  • malloc(8)
  • malloc(8) == ((char*)&stack_var) + 8

图解

heap-fastbin_dup_to_stack.drawio

0x03 fastbin_dup_consolidate

利用条件

程序存在double free漏洞

目的

fastbins除了在两次free之中加入另外一个free之外,还可以借助large bin中的malloc_consolidate来绕过检查达到double free的目的.

达到的效果就是fastbin_dup

64位下,largebin[0] 对应的size=0x410

步骤

  • 填满0x50大小的tcache
  • a=calloc(0x40)
  • free(a)
  • b=malloc(0x400) // malloc一个largebin大小的chunk,触发malloc_consolidate,merge到top chunk/unsortedbin
  • free(a) // a和b现在指向同一个chunk,所以可以free(a)
  • c=malloc(0x400)
  • b==c

图解

0x04 unsafe_unlink

利用条件

free 的 chunk 前后存在空闲 chunk, 也可以通过溢出值覆盖需要 free 的 chunk 的 P 位, 能控制需要 unlink 的 chunk 的内容.

要free的chunk不能在fastbin范围内,因为fastbin的P位是1,不会触发unlink

目的

可以对一个全局指针ptr进行内存布局,然后借助unlink操作实现任意地址读写

  • 通常ptr是一个data pointer(意思指向的是chunk 的data部分,所以如果要做unlink利用的话,要伪造整个chunk,而不单单是fake fd和fake bk)
  • 可以利用它去改变其他存在&ptr附近的pointer,然后再利用这些pointer去造成任意地址读写。如果存在function pointer,可以更直接的控制eip

步骤

  • 绕过(P->fd->bk != P || P->bk->fd != P) = False检查
    • fd = &ptr - 0x18
    • bk = &ptr - 0x10
  • 绕过(chunksize(P) != prev_size (next_chunk(P)) == False检查
    • 修改对应的prev_inuse和prev_size
  • unlink执行后
    • ptr = ptr - 0x18
    • ptr[3]可以修改ptr指向的内容

图解

0x05 house_of_spirit

利用条件

  • 想要控制的目标区域前后一段都是可控的
  • 存在可以被覆盖的堆指针
  • 一般是在栈上做利用,故需要栈溢出

heap-house_of_sprit.drawio

目的

覆盖一个堆指针,使其指向可控的区域,构造好相关数据,释放堆指针时会将该区域作为chunk放到fastbin里,再申请这块区域,就可以改写目标区域

步骤

  • 伪造堆块,在可控的区域1和2构造数据,将目标区域伪造成一个fastbin chunk
  • 覆盖堆指针指向伪造的fastbin chunk
  • 释放伪造的fastbin chunk到fastbin
  • 申请刚刚释放的chunk,使得可以向目标区域写入数据

图解

heap-house_of_sprit.drawio

0x06 posion_null_byte

见shrink_the_chunk

0x07 shrink_the_chunk

利用条件

存在off-by-one null byte的漏洞

目的

创造出overlap chunk,进而更改其他chunk的中内容

主要利用unlink做合并的特性来达到目的

步骤

这个步骤意义不大,建议直接看图

图解

heap-shrink_the_chunk.drawio

高版本下的区别

https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c

2.29引入,这个利用用到了unsorted bin,所以也受到了影响。

但是上面的利用方式其实已经是对于这个patch的绕过了

如果是低版本的glibc,都不用提前在chunk中写那个0x100

image-20220921222002006

0x07 entend the chunk

利用条件

存在off-by-one漏洞

目的

创造出overlap chunk,进而修改其他chunk的内容

进而变成构造任意指针,从而任意地址读写

跟shrink很像,但主要是加大size,直接吃掉后面的chunk,只要后面的chunk header有对上就好

挖坑

中间那个chunk有必要这么大吗? 需要用到unsorted bin?

如果用到unsorted bin,那么也会收到这个patch的影响,(unsorted bin中chunk取出来时会做unlink,就要做prev_size和size的检查)在2.29之后使用受限

https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c

所以还是那句话,中间那个chunk有必要这么大吗? 如果不进入unsorted bin,是不是就不会做检查了

步骤

  • A = malloc(0x30); B = malloc(0x160); C = malloc(0x30)
  • free(A)
  • malloc(0x38), 填入数据,并且触发off-by-one漏洞,修改chunk B的size一字节。使得chunk B的size大小等于chunk B、C总和。size=0x1B1
  • free(B),free B的时候会把C顺带着吃掉。然后放入top chunk或者unsorted bin
  • malloc(0x1a0),造成chunk C的overlap

图解

1heap-entend the chunk.drawio

house_of_lore

overlapping_chunk

同extend_the_chunk

overlapping_chunk2

同shrink_the_chunk

house_of_force

image-20220915220557755

高版本下的区别

https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=30a17d8c95fbfb15c52d1115803b63aaa73a285c

2.29后不可用

image-20220921222609325

image-20220921222558914

unsorted_bin_attack

image-20220918130923741

image-20220918133738841

高版本下的区别

https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=b90ddd08f6dd688e651df9ee89ca3a69ff88cd0c

2.29后不可用

image-20220921222627711

image-20220921222635259

large_bin_attack

house_of_einherjar

tcache_dup

高版本下的区别

做了double free检测,每个tcache chunk增加了一个key字段,其实就是tcache_perthread_struct指针,释放chunk的时候,会检查当前线程中tcache_perthread_struct是否已经释放过这个chunk,释放过就会crash掉。

主要针对tcache dup,不过改掉key就可以绕过

image-20220921222741335

image-20220921222839345

image-20220921222903017

tcache_poisoning

tcache_house_of_spirit

house_of_botcake

house_stashing_unlink_attack

fastbin_reverse_into_tcache

house_of_mind_fastbin

house_of_storm

heap编年史

  • glibc 2.32 引入safe-linking

    • https://research.checkpoint.com/2020/safe-linking-eliminating-a-20-year-old-malloc-exploit-primitive/

    • https://www.anquanke.com/post/id/206457

    • bypass
    • https://www.researchinnovations.com/post/bypassing-the-upcoming-safe-linking-mitigation
    • https://www.anquanke.com/post/id/207770
    • https://cloud.tencent.com/developer/article/1643954
  • 2021.8.1 glibc2.34发布,取消了free_hook, malloc_hook, realloc_hook等一众hook全局变量

​ https://developers.redhat.com/articles/2021/12/17/why-glibc-234-removed-libpthread

参考链接

  • https://github.com/shellphish/how2heap
  • https://bbs.pediy.com/thread-259269.htm
This post is licensed under CC BY 4.0 by the author.

ctfwiki - stack overflow

HITCON-Traning lab1-lab15