【小白】Doug Lead 内存分配器之堆上的缓冲区溢出--unlink

1.了解已分配块和未分配块的结构  

【小白】Doug Lead 内存分配器之堆上的缓冲区溢出--unlink

一个空闲块包含指向下一块的前向指针和指向上一块的后向指针  FP和BP

p用来指示上一块内存的状态是已分配还是未分配


2.在free()时,内存块如果条件满足会被合并 和相邻空闲块合并:
被释放块的上一块为空闲块
与被释放的块合并
被释放块的下一块为空闲块
也从双链表中解开 并与被释放块合并

#defineunlink(P, BK, FD) {  \

  FD = P->fd;  \                       

  BK = P->bk;  \

  FD->bk= BK;  \

  BK->fd= FD;  \

【小白】Doug Lead 内存分配器之堆上的缓冲区溢出--unlink

3.可以使用unlink技术进行攻击的有漏洞的程序代码

dlmalloc

#include<stdlib.h>

 #include<string.h>

 intmain(int argc,char *argv[]) {

  char *first, *second, *third;

   first = malloc(666);

   second = malloc(12);

  third = malloc(12);

   strcpy(first,argv[1]); //这里会发生缓冲区溢出,覆盖second

   free(first);

  free(second); //如果第二块内存处于来分配状态(即空闲), free()操作将会试图将其与第一块合并

  free(third);

  return(0);

 }


【小白】Doug Lead 内存分配器之堆上的缓冲区溢出--unlink

second:

第一行4bytes 是一个偶整数,假的大小域,最后一位为0

第二行4bytes显示的是内容:-4

第三行是fd:fp-12(第一个块前12byte处)

第四行是bk:指向一个addr


这样检查第二块是否为空,就要检查第三块的p是否为0,要找到第三块的位置就要用第一块的位置+第二块的大小,而第二块的大小为-4,那么找到的第三块的位置(假)就在第二块的第一行,p为0。

所以会把第一块和第二块合并起来。


执行unlink宏

  FD = P->fd;  \              恶意参数         

  BK = P->bk;  \ 恶意参数

  FD->bk= BK;  \ FD->bk想到于FD+12(第一块起始位置处)赋值为恶意参数 相当于将攻击者提供的4个字节的数据(addr)写到同样是由攻击者指定的4个字节地址处

  BK->fd= FD;  \



ps:第一块的shellcode应该从第12位开始写。因为BK->fd是第一块的地址+8,再覆写4位。