1malloc.c源码
#!c
1413 /* Take a chunk off a bin list */
1414 #define unlink(AV, P, BK, FD) {
1415 FD = P->fd;
1416 BK = P->bk;
1417 if (__builtin_expect (FD->bk != P || BK->fd != P, 0))
1418 malloc_printerr (check_action, "corrupted double-linked list", P, AV);
1419 else {
1420 FD->bk = BK;
1421 BK->fd = FD;
1422 if (!in_smallbin_range (P->size)
1423 && __builtin_expect (P->fd_nextsize != NULL, 0)) {
1424 if (__builtin_expect (P->fd_nextsize->bk_nextsize != P, 0)
1425 || __builtin_expect (P->bk_nextsize->fd_nextsize != P, 0))
1426 malloc_printerr (check_action,
1427 "corrupted double-linked list (not small)",
1428 P, AV);
1429 if (FD->fd_nextsize == NULL) {
1430 if (P->fd_nextsize == P)
1431 FD->fd_nextsize = FD->bk_nextsize = FD;
1432 else {
1433 FD->fd_nextsize = P->fd_nextsize;
1434 FD->bk_nextsize = P->bk_nextsize;
1435 P->fd_nextsize->bk_nextsize = FD;
1436 P->bk_nextsize->fd_nextsize = FD;
1437 }
1438 } else {
1439 P->fd_nextsize->bk_nextsize = P->bk_nextsize;
1440 P->bk_nextsize->fd_nextsize = P->fd_nextsize;
1441 }
1442 }
1443 }
1444 }
1445
1446 /*
2.检查机制
if (__builtin_expect (FD->bk != P || BK->fd != P, 0))
malloc_printerr (check_action, "corrupted double-linked list", P, AV);
按照上面检测的源码要求p->fd->bk=p且p->bk->fd=p
3连接方式
这边直接用的星盟师傅讲课时的图
4利用方式demo
这边利用方式比较容理解的话还是heap exploitation
代码的地址
https://github.com/DhavalKapil/heap-exploitation
代码的截图
这一段是定义结构体,然后后面的那一部分都是一些初始化,注意这里我们修改的都是mem指针,也就意味要空出前面的size和pre size的位置,所以如果我们用的大小为0x80,实际的大小应为0x90
然后具体的利用方式
1绕过保护
这段代码不是很清楚(因为是截图),主要的功能是构造一个fake chunk并且能绕过之前说的检测机制,具体原理如下
数据结构和具体位置
pre size +0
size +1
fd +2
bk +3
有上面截图的代码可知fd的值为&chunk1-3,按照检查机制p->fd->bk=&chunk1-3+3=&chunk1,即完美的满足了监测机制,同理p->bk->fd=&chunk1-2+2=&chunk1
2利用源码
这一段代码将堆中的对前一个chunk判断是否被占用的数值 设置为0,当我们后面free时将会与前一个进行合并执行源码中的
else {
1420 FD->bk = BK;
1421 BK->fd = FD;
此时chunk1会指向&chunk1-3的位置,原因仍然是按照上面的计算方法
fd->bk=chunk1-3+3=chunk1=bk=chunk1-2
同理 bk->fd=chunk1-2+2=chunk1=fd=chunk1-3
此时chunk1【3】=chunk1+3=chunk1
此时chunk1[3]=chunk1[0]=chunk1
所以对chunk1【0】修改就会改变chunk1[3]的值,最后的输出结果将会变为hacked,即达到了一个脱链的功能