堆利用-fastbin attack

发布于 2023-05-06  646 次阅读


ctf出题一般都是基于ubuntu16.04或者ubuntu18.04,对应的glibc版本是2.23和2.27。 所以fastbin attack不仅可以开阔视野熟悉堆分配算法,而且可以用来打ctf。

C语言程序使用malloc来分配内存空间,free来释放内存空间,但是malloc怎样来既要兼顾分配速度又要兼顾管理内存分配的数据结构必须简单且防止申请大量的小空间内存造成浪费呢?有一个函数库叫glibc,它实现的malloc采用一种比较有趣的方式来分配内存,我们每一次malloc得到的空间都会被一个结构体struct malloc chunk来管理,同时有一个分配区arena记录了空闲的chunk的位置,例如我们执行语句void *p=malloc(0x20),申请一块大小为0x20字节的内存块,这个内存块被一个叫做struct malloc chunk的结构体来管理,该结构体如下:

首先第一个成员是prev_size,其在64位系统下为八个字节,如果前一个chunk是空闲的,则prev_size表示前一个chunk的大小,如果前一个chunk不是空闲的,那么该域没有实际意义。

第二个成员size表示当前堆块的大小,其最后三个二进制位有特殊含义,在计算大小的时候统一为0,前边文章有详细说过,后三位依次为NON_MAIN_ARENA,我们简称A位,记录当前chunk是否属于主线程,1表示不属于,0表示属于;IS_MAPPED,简称M位,记录当前chunk是否由mmap分配的;PREV_INUSE简称P位,记录前一个chunk是否被使用,1为使用状态,0为free状态;fast chunk的该位始终为1,因为P位的设置是为了方便堆块的合并,而fast chunk本身是为了快速分配和释放而设计的,它的合并时机是很特殊的,所以该位总为1,防止过多的堆合并操作。

第三第四个成员是 fd 与 bk 指针,fd指向后一个空闲堆块,bk指向前一个空闲堆块。用户申请的内存空间就是从fd处开始的,在申请内存的时候,写入数据,就会覆盖掉fd指针 ,不过别担心,由于堆块正在被使用,没有被free掉,所以此时fd与bk指针没有实际意义,一旦堆块被free掉之后 ,fd与bk就有其意义, 此时fd bk会根据具体情况,被free函数填入符合要求的指针,也就指向了前一个 后一个 free状态的堆块,有一个大坑要注意,bk与PREV_SIZE都有前这个说法,但是两个前是不一样的,bk指针的前是链表区的前,PREV_SIZE的前表示内存顺序的前。

第五第六个成员是 fd_nextsize指针和bk_nextsize指针只在large chunk中出现,表示的是后一个堆块的大小和前一个堆块的大小。

arena

arena主要管理着空间堆块的基本情况,它的名字叫分配区,不同线程一般而言有不同的分配区,但这点不绝对,arena的数量有分配规则,主线程的arena叫做main arena,是一个全局变量,在gdb中可以直接用命令查看。同时,分配区的数据结构 struct malloc_state,一个arena的类型就是struct malloc_state,如下:


穿过云层我试着努力向你奔跑