其他
large chunk分配过程调试
本文为看雪论坛优秀文章
看雪论坛作者ID:dolphindiv
一
代码简介
#include<stdio.h>
#include<stdlib.h>
int main(){
int *p1 =malloc(8);
int *p2 =malloc(8);
fprintf(stderr,"malloc two fastbin chunk: p1=%p p2=%p\n",p1,p2);
void * p3 = malloc(0x500); //malloc large chunk from top chunk
void * p4 = malloc(0x8); //void the freed large chunk consolidated with top chunk
void * p5 = malloc(0x600); //malloc another large chunk
void * p6 = malloc(0x8); //void the freed large chunk consolidated with top chunk
free(p3); //free p3 into unsortedbin
free(p5); //free p5 into unsortedbin
void * p7 = malloc(0x550); //malloc large chunk, remove p3 p5 into largebin
fprintf(stderr,"malloc large chunk:p7=%p\n",p7);
}
二
申请large chunk过程调试
在 free(p3)处设置断点,运行程序,命中断点,然后单步执行free(p5),执行完之后,可以看到chunk p3、chunk p5已经释放到unsortedbin。
(一)在各种bin中搜索合适大小的chunk时,将p3、p5从unsortedbin移到largebin中。
使用s命令进入 malloc.c进行单步调试。
3591行代码的作用是检查fastbin(小于0x80字节)中是否有合适的chunk,显然没有,继续执行到3649行。
3649行代码的作用是检查smallbin(小于0x400字节)中是否有合适的chunk,显然没有,继续执行到3711行。
3711、3712行代码的作用是计算large bin的idx,判断fastbins中是否有释放的chunk。如果有,调用malloc_consolidate()整理fastbins,并放入unsorted bin。malloc_consolidate()先向后合并空闲的chunk,再向前合并空闲的chunk,最后将合并的chunk放入unsorted bin。
搜索到unsortedbin中第1个chunk,即victim。
bck为victim后面的chunk,即unsortedbin中第2个chunk。
进行victim大小合法性检查(大于2 * SIZE_SZ,且小于 av->system_mem)后,计算victim的大小。
程序执行到3759行,当请求的chunk属于smallbin、unsortedbin只有一个chunk为lastremainder并且满足拆分条件时,就将其拆分。这里不满足条件。
程序执行到3788、3789行,将victim从unsortedbin中取出。
如果victim的大小正好等于请求chunk的大小,则将victim返回给用户。这里不满足条件。
如果chunk大小不合适,就将其插入对应的bin中。插入过程也就是双链表插入节点的过程。其中插入largebin的操作最为复杂,因为涉及到修改fd_nextsize和bk_nextsize指针。
此时largenbin为空,修改victim的fd_nextsize和bk_nextsize指向victim自身。
最后修改bk和fd指针,将victim掺入到largebin中。
然后再次执行3742行处的while循环,按照以上过程,将unsortedbin中0x5555557567c0处的大小为0x600字节的chunk放入另外1个largebin。
程序执行到这里,p3、p5两个chunk分别移到对应大小的largebin中,第一个循环结束。
(二)遍历largebin,找到合适大小的chunk,进行切分操作,将用户申请的chunk返回给用户,剩余部分移到unsortedbin中。
根据前面计算的largebin idx,计算出largebin的头结点0x7ffff7dce0e0 ,这个头结点指向大小为0x500的chunk(0x555555756290),显然这个大小小于用户申请的大小,3919至3921行的判断条件不满足。
程序执行3987行,对idx进行加1操作,并计算出下一个largebin的头结点。
继续寻找next_bin,地址为0x7ffff7dce110 ,即搜索到chunk p5(大小为0x600)所在的largebin,此时bit=256 ,已经不满足(bit & map) == 0的条件,跳出while循环。
取出largebin( 0x7ffff7dce110 )中的chunk p5(大小为0x600)为victim。
程序执行到4030行代码处,计算victim的大小。
验证完victim的大小大于请求chunk的大小后,将victim的大小减去请求chunk的大小,并进行unlink操作,将victim从largebin中解链。
如果victim中剩余部分的大小小于MINSIZE,则将整个victim返回给用户,显然不成立。可以看到,unlink操作后,0x600字节大小的largebin中已经没有victim。
对victim进行切分操作,将0x550大小的chunk返回给用户,并将剩余部分remainder插入unsortedbin。内层第二个循环到此结束。
看雪ID:dolphindiv
https://bbs.pediy.com/user-home-717768.htm
# 往期推荐
2. Android漏洞挖掘三板斧——drozer+Inspeckage(Xposed)+MobSF
3.CVE-2017-17215(华为HG532远程命令执行漏洞)复现学习
6. CVE-2012-3569 VMware OVF Tool格式化字符串漏洞分析
球分享
球点赞
球在看
点击“阅读原文”,了解更多!