[pwn]fastbin attack
文章目录
fastbin attack原理
fastbin attack是利用fastbin分配原理的漏洞,利用要求是我们能够修改“已释放”堆块。通常情况下与double free、use after free和chunk extend连用。
首先简单介绍一下fastbin的分配流程:
fastbins是管理在malloc_state结构体重的一串单向链表,分为0x20-0x807个链表(默认情况下)。每个表头对应一个长度不超过4个的单向链表。
- 每次释放对应大小的堆块都会被连入对应大小的链表中(链表长度<4)。
- 每次分配会优先从fastbins中分配对应大小的区块。
如下图:
由chunk的bk指针域指向下一个空闲fastbin堆块,最后一个空闲堆块的bk指针为0。申请堆块的时候会将表中第一个堆块分配,然后表头指向第一个堆块指向的下一个堆块,如下图:
如果下一个堆块为0就说明分配完了,表头指向空即可。关于fastbin的更详细信息和chunk结构等可以参阅《ptmalloc源码分析》。接下来就三种典型的可以利用fastbin attack的漏洞进行简单介绍
double free
double free+fastbin attack的利用场景通常是这样的,当程序有double free漏洞时,我们通过申请两个fastbin大小的堆块1和2,还是以0x30举例,然后分别释放chunk 1和chunk 2,fastbin的链表结构就会如下图:
这时由于有double free漏洞,再释放chunk 1,链表就会变成这样一个循环链表:
表头指向chunk1,chunk1指向chunk2,chunk2又指回chunk1。那么这时按照如下步骤:
- 申请一个new chunk 1:
- 将new chunk 1的指针域修改为要修改的地址-0x10以上:
- 申请一个new chunk 2:
- 再申请一个new chunk 3(new chunk 3是和new chunk 1重合的)
- 这时可以发现,fastbin链表已经指向了我们想要修改的地址了,只要再申请一个堆块就会申请到想要修改的地址,然后只要编辑这个堆块便可完成任意地址写。
use after free
use after free来利用fastbin attack也非常简单。首先,申请一个对应fastbin区间内的堆块并释放:
接着利用use after free将这个已释放堆块的指针域修改,修改为想要修改的地址:
然后和double free的后半段类似,再申请两个堆块便可申请到想要修改的地址处,之后编辑即可。
chunk extend
chunk extend是一种限制比较少的堆利用方式,通常通过off by one或off by null或者其他堆溢出来利用。
chuank extend利用需要的条件是:
- 可以进行堆布局
- 可以溢出至少一个字节
chunk extend的原理是,首先申请三个堆块:
这里size 0x18是堆块的大小,1是前一个堆块占用位,先通过编辑堆块A然后通过off by one来溢出到堆块B的size域,并将其修改为0x18+0x18+1(其实就是size B+size C,然后前一个堆块占用1):
这时释放堆块B,由于大小在fastbins中,所以(堆块C的)下一个堆块的前一个堆块使用位不会被置0,再释放C,arena中对应的bins就会指向B和C,如图:
这时只要再申请一个0x40的大小的堆块,就可以将B+C这个“合成”堆块申请回来,然后就可以操作还在bins中的C堆块C了,将其指针为修改为想要任意写的地址,如free_got:
然后再申请一个大小为0x20的堆块,将C申请回来,这时bins就会指向freegot,接下来再申请空间就会申请到freegot了:
再次申请一个0x20大小的堆块就会申请到free_got所在的地方,这时就可以修改为任意的值了。
需要注意的点
在申请fastbin时会有两个检测:
- 检测你要malloc的freechunk的大小是否在该chunk所在的fastbin链的大小尺寸范围内
- 检测你这个freechunk的size成员的PREV_INUSE为是否为1,为1才可以通过检测(libc2.23没有)
而以libc-2.23为例,如果想要使用fastbin attack来修改malloc_hook为onegadget的话,只是将修改地址写成malloc_hook_addr-0x10是通过不了检验的,一个固定用法是修改成malloc-0x23,下面通过一道题来演示一下chunk extend来利用fastbin attack修改malloc为onegadget的。
0ctf:babyheap
题目:0ctfbabyheap
首先查看安全策略:
全开,基本堆题目日常操作。然后逆向查看程序逻辑:
基本就是一个典型的堆题目,可以自由