【小白】Doug Lead 内存分配器之堆上的缓冲区溢出--unlink
1.了解已分配块和未分配块的结构
一个空闲块包含指向下一块的前向指针和指向上一块的后向指针 FP和BP
p用来指示上一块内存的状态是已分配还是未分配
2.在free()时,内存块如果条件满足会被合并 和相邻空闲块合并:
被释放块的上一块为空闲块
与被释放的块合并
被释放块的下一块为空闲块
也从双链表中解开 并与被释放块合并
#defineunlink(P, BK, FD) { \
FD = P->fd; \
BK = P->bk; \
FD->bk= BK; \
BK->fd= FD; \
}
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);
}
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位。