随笔 - 8  文章 - 0  评论 - 0  阅读 - 339

初学unlink

unlink是我学的第二个堆溢出的知识点,在这之前沉淀了好久的堆概念,非常的混乱,不过好在终于整理的差不多了。

先讲讲malloc和free的运作流程,这也是探究了最久的一个概念,关于heap的结构就不说了。

malloc流程:

1.如果处于mmap的范围,直接调用mmap分配

2.如果所需分配内存在fastbin的范围里会在fastbin里查找空闲的chunk,如找到则结束。

3.如果所需分配的内存在smallbin的范围里,就去smallbin里查找,如找到则结束。

4.如果所需分配的内存不在smallbin里,那么就会先合并fastbin里的chunk(注意合并条件需要chunk相邻)并放入到unsorted bin准备接下去的工作

5.在unsorted bin里查找last_remainder是否大于等于所需分配内存的chunk,如果有大于的,就将其分割出来使用,剩下的称为last_remainder,如果有刚好的大小chunk,则会直接将其使用;如果last_remainder小于所需分配内存的chunk,就会先把此chunk放入 small/large bin 中去,然后去遍历其他在unsortedbin里的chunk,如果有大于的,就将其分割出来使用,其chunk剩下的部分称为last_remainder,如果有刚好的大小chunk,则会直接将其使用,如果此chunk小于所需分配内存,就会先把此chunk放入 small/large bin 中去,接着再重复循环下一个chunk(注意,放入small/large bin的时候还会再判断合并一次)

6.在small bin和large bin中搜索最合适的chunk(不一定是精确大小,如果是大于的话则会进行切块操作,切下剩余的会被放入unsortedbin里当作last_remainder)

7.使用topchunk分配

8.将topchunk放入unsortedbin里,进行内存块申请,分配新的topchunk,然后再由topchunk分配(这种情况下一般是topchunk已经被多次分配而导致变为很小了,所以需要重新申请一块topchunk)

同一个bin里malloc分配查找chunk会从fd指针链的开头开始查找

free流程:

1.如果free的空间是由mmap分配的,则直接归还操作系统

2.如果free的chunk在fastbin的范围内,放入fast bin,结束(以下合并操作不会进行)

3.如果物理相邻的前一个chunk(远离topchunk的)是free(并且不是fastbin里的)的,将前面的chunk合并,并且将两个chunk的size相加覆盖两个chunk中低地址的chunk的size以及修改低地址的chunk的fd和bk指针。然后放入unsorted bin,执行unlink

4.如果后一个chunk是top chunk,则将当前chunk(经过步骤2的合并也一样会)并入top chunk

5.如果后一个chunk时free的(并且不是fastbin里的),将后面的chunk合并,并且将两个chunk的size相加覆盖两个chunk中低地址的chunk的size以及修改低地址的chunk的fd和bk指针。然后放入unsorted bin,执行unlink

6.前后chunk都不是free的,放入unsorted bin

free之后的chunk第一时间只会进入unsortedbin或者fastbin,直到malloc之后才可能会进入到smallbin或其他bin

fastbin的chunk的下一个chunk的prev_size始终为1,也就是说fastbin里chunk始终不会合并

假设free(a);free(c);free(e); 则在非fastbin里的fd指针是e->c->a->main_arena,bk是a->c->e->main_arena

unlink

那先来介绍一下unlink,啥是unlink呢

unlink就是从bin中摘除一个块的操作,而主要的过程就是摘除时会将前后的chunk的fd、bk指针设置好

unlink一般发生在free函数当中,也就是他是free函数中的一个步骤,他会在free某一个块的时候,如果这个块附近有freechunk,那么他就会合并,并且把这个合并完之后的chunk摘除,然后当作一个新的freechunk加入到unsortedbin里,举个例子

这是一个free了两个chunk的unsortbin(请注意,这里的0x7f88e8344b78是unsortbin的头,也有fd和bk指针,fd指针指向0x11ac600,bk指针指向0x11ac440,所以形成一个循环)

假设我此时free了一个和上图两个物理不相邻的chunk,也就是不会导致合并,就会把这个新的freechunk的fd指针指向0x11ac600,bk指向0x7f88e8344b78,然后再修改0x11ac600的bk指针为这个新的freechunk

这都是一些很正常的操作

但是如果我free了一个和上图某一个chunk物理相邻的chunk,就假设是0x11ac600的相邻chunk把,假设我释放了一个地址为0x11ac500的chunk,此时0x11ac6000的bk和fd指针都不为空(unlink需要的条件,实际上,只要unsortbin里有一个chunk,那这个chunk的fd和bk都不为空),那么就会先将其合并,然后将0x7f88e8344b78的fd指针指向0x11ac440,再将0x11ac440的bk指针指向0x7f88e8344b78,也就是摘除0x11ac600,接着因为新freechunk的规则,将0x11ac500的fd指针指向0x11ac440,然后bk指针指向0x7f88e8344b78,然后再将0x11ac440的bk指针指向这个新freechunk:0x11ac500。

刚刚说的第二种情况就是unlink的情况,他会在让处于unsortbin里中间(即bk和fd指针不为空,也就是unsortbin里的任意chunk)的chunk与其他chunk合并的时候被摘除,然后将合并完后的chunk放入unsortbin链表尾部。

在free函数里的unlink的目的很简单,就是为了将合并完后的chunk放入unsortbin链表而已,但是在其他地方可能就只有摘除块的作用而已

接下来看个例题

参考文章:【精选】好好说话之unlink-CSDN博客

2014 HITCON stkof

这个题目有几个函数,依旧是常见的创建,删除,修改

我比较懒,就只针对这篇文章做出几个修改和精进以及说明

 首先是这个检查部分,其实这些都是没什么问题的,为下面的fake_chunk部分铺路

 我一开始看到这个的时候,就很疑惑,这个next_prev设置成0x20为什么能绕过检测,最后知道了之后,我感觉作者在这里搞得有点复杂了

其实就是检测1和检测2,但是他没有说清楚而已,实际上是这样的:

free chunk3的时候 他首先判断了chunk3的PREV_INUSE位是否为0,发现为0,于是依据chunk3的pre_size,得到上一个chunk(也就是得到fake chunk),然后就会去检查这个fake_chunk的size(0x20)和对应的下一个chunk的pre_size(也就是那个next_prev:0x20)是否相等  发现确实相等 于是将fake chunk和chunk3合并,在以上的过程中,没有用到next_size,所以随便用字符串占位就好。

但是通过刚刚的解释,我们其实可以发现,不一定要在pre_size那里写上0x20才可以绕过检测嘛,我直接把fakechunk的size改成0x30不就好了,然后pre_size和nxt_size这两个都不用设置,于是我真的去试了一下,确实也可以,所以我说作者搞复杂了。

还有一个要说明的就是这个

 这里可能有人看不懂,其实就是因为

 这里更改了0x602140的fd和bk指针,所以才变化的。

剩下的也蛮简单的了,应该跟着那篇文章来就没问题,还有不懂的可以跟我交流。

 

posted on   -3  阅读(79)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示