How2heap -- fastbin_dup_into_stack(by glibc-2.23)

how2heap 的 fastbin_dup_into_stack.c 源码

pwndbg 调试观察

先malloc了3块内存

堆块结构:

这里堆信息显示的堆块地址都比栈上存储的堆块地址小0x10,这是因为heap显示的地址是堆块的真正的头部地址,指向的是堆块的第一个数据prev_size,而栈上存储的地址是返回给用户使用的指针fd的位置,pre_size和size字段在64位操作系统上都是8字节大小,所以前面占了0x10,导致看到的两个地址相差0x10大小

至于申请的堆块大小为0x20,实际size位显示的却比申请大小大1字节,这是因为size字段低三比特位为特殊的flag值

分别为

​ NON_MAIN_ARENA, 记录当前堆是否不属于主线程,1表示不属于,0表示属于

​ IS_MAPPED, 记录当前堆是否是由mmap分配的

​ PREV_INUSE, 记录前一个堆块是否被分配(就是是否在使用状态)

但是fastbin为了快速分配使用,在fast chunk被free掉的时候并不会将后一个chunk的PREV_INUSE位置零

fd、bk指针在堆块处于分配状态的时候,堆结构体偏移fd的位置就用来存储数据,当堆块处于空闲状态的时候,fd、bk指针就分别记录“物理”相邻的前()一空闲堆块、后()一空闲堆块的地址,用于对应空闲链表的管理

此处演示的是fastbin范围的堆块,如果是largebin范围的堆块,再往下还有两个指针 fd_nextsize、bk_nextsize

fd_nextsize、bk_nextsize指针在large chunk处于空闲状态的时候使用,分别用于记录前()一个与当前chunk大小不同的第一个空闲chunk和后()一个与当前chunk大小不同的第一个chunk

然后free掉a

free前

free后

这时候如果我们再次free(a),程序就会crash,因为这时候a对应的堆地址被存放到fastbin的链表头部,又因为堆块a的大小在fastbin的范围内,free的时候会检测当前free的对象是否处于fastbins的头部,如果是,则执行Malloc_printerr(报错)并退出程序

那么绕过该机制的方法就是free掉一个相同大小的chunk,这样fastbin空闲链表里的情况就是

现在我们就可以再次 free(a)

free(a)的时候ptmalloc内存管理器会检测到fastbin空闲链表头部是b,所以允许free(a),这样a的chunk头地址就会再次被放到fastbin空闲链表头部,且指向“前一个”空闲堆块b,这样就产生了 a -> b -> a -> b -> a … 的循环链表的情况,这样我们就能重复malloc到一个chunk

接下来做了一次malloc,返回的chunk a的地址存到了指针d中

可以看到在堆信息中并没有看到新的chunk产生,因为malloc的大小为8,64位系统的MIN_CHUNK_SIZE为32bit,即至少包含PREV_SIZE, SIZE, *FD, *BK四个字段,所以分配的最小chunk大小为0x20,内存中size字段为0x21,而fastbin的内存分配策略是exact fit,即只释放跟申请内存大小恰好相等的堆块,而且是FIFO(First In First Out)机制,所以这里申请了8字节大小的chunk,分配到的就是之前释放的,在fastbin头部位置的chunk a

可以看到在fastbin空闲链表中,chunk b 移动到了链表的头部,而刚刚被malloc的,本应移出空闲链表的 chunk a 则移动到了链表尾部,fastbin空闲链表代表0x20大小的数组指向的仍然是一个循环链表

再一次malloc,将chunk a 移到链表头

这时候我们就可以通过修改chunk a的fd指针域,指向栈上一个地址,如果这个地址的后(高地址)8个字节存储的值正好是0x20,ptmalloc就会判断这是一个合法的堆块,该地址就会加入到空闲链表中,因为这个地址是写在chunk a的fd指针域,是chunk a指向的前面一个“空闲堆块”

那么我们下一次malloc就会分配到chunk a,再次malloc就会分配到栈空间了

malloc 8字节

此时的fastbin

之前栈空间上伪造的chunk已经移动到链表头了

再次malloc就能拿到栈空间

这就是free完没有将指针置NULL产生的 “dangling pointer” 产生的 “Double Free” 漏洞产生的 “Use After Free” 攻击的完整分析过程

安全建议

malloc出来的指针free之后要置NULL


版权声明:本文为m0_56642842原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。