大小:
32位:16-64字节 0x10-0x40
64位:32-128字节 0x20-0x80
chunk 的大小而不是申请的内存的大小(申请的内存加上 chunk 头)
fastbinsY 是一个数组,相同大小的 chunk 放在一个数组元素指向的链表里面
单向链表后进先出,fastbinsY 数组中每一个元素指向该链表的尾结点,尾结点在通过 fd 指针指向前一个节点
例如:
free(ptr1);
free(ptr2);
最后那么是这样的 fastbin -> ptr2 -> ptr1
空闲的 fastbin chunk 不会被合并,不会修改 chunk 头
拿这个例子做一下实验
可以看出链表来,后释放的 fd 指向上一个的,而不同大小的不会指向
wiki 上的描述,可以看到 chunk1 的 fd 会指向 chunk2 那么如果 chunk1 是我们可控的那么就可以申请任意地址的 fastbin
又是全新的知识 Orz
在目标地址伪造 fastbin chunk,然后释放掉,从而达到分配指定地址的 chunk 的目的
有一些条件:
fake chunk 的 ISMMAP 位不能为 1,因为 free 时,如果是 mmap 的 chunk,会单独处理
fake chunk 地址需要对齐, MALLOC_ALIGN_MASK
fake chunk 的 size 大小需要满足对应的 fastbin 的需求,同时也得对齐
fake chunk 的 next chunk 的大小不能小于 2 * SIZE_SZ,同时也不能大于av->system_mem
fake chunk 对应的 fastbin 链表头部不能是该 fake chunk,即不能构成 double free 的情况
通过构造 fake chunk,然后把它给释放掉,这样再次申请相同大小的 chunk 的时候就会匹配到这里
house-of-spirit 是一种通过堆的 fast bin 机制来辅助栈溢出的方法
如果栈溢出的时候溢出的长度不能覆盖掉返回地址的但是却可以覆盖栈上面一个即将 free 的指针的话,我们可以把这个指针覆盖为栈上的某一个地址,并且把这个地址上伪造一个 chunk,free 之后再次 malloc 就可以申请到栈上面伪造的那一块,这时候就有可能改写返回地址了
通过上面那个程序直观的看一下
gcc -g house_of_spirit.c
首先在程序的第 14 行下个断点 b 14
运行到这里可以看到 fake_chunk 目前还没有被我们写入
我们直接让他写完,再来看一下,已经构造出 fake chunk 了
对 fake_chunk 进行 free 之后
可以看一下 fastbin 现在已经是有了我们构造的那个 fake_chunk 了
接下来再次 malloc 一个相同大小的 chunk 就会把这里申请过去
构造 chunk 的时候要注意绕过一些检查:
后面那三个特殊的标志位前两个必须都为 0,写 size 位的时候直接 0xN0就可以了,然后大小要注意符合 fastbin 的大小,next chunk 的大小也要注意,必须大于 2*SIZE_SZ,小于 av->system_mem
64位下:16< next chunk 的 size < 128
通过修改 fd 指针,指向栈上,从而申请栈上的空间,进而控制返回地址
跟上一个的区别在于这个是往任何可写的地方去分配 chunk
先随便申请两个看一下结构
可以看到申请的第二个上有一个指向第一个的指针
那如果第 2 个的 name 再多写一点,就可以覆盖掉这个指针了
这时候再去 show 就能拿到 puts 的真实地址了,拿到之后就可以计算出 libc 的地址,进而拿到 system 和 '/bin/sh' 的地址
接下来需要伪造一个 chunk,因为枪支的 chunk 大小是 0x40的,而那个计数的东西在 bss 段中 0x804A2A4 的位置,每 add 一个就会 +1,可以用来作为 fake chunk 的 size,只需要多申请几个就可以
这时候可以同时把最后一个的指针改为 fake chunk 的地址(0x804A2A4 + 0x4)
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!