堆的结构
malloc chunk
1 | chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
free chunk
1 | chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
在fasted bin中是LIFO
在unsorted bin 中是FIFO
堆叠技巧
http://4ngelboy.blogspot.com/2016/10/span-display-block-overflow-hidden_10.html
这位师傅的blog里讲的很详细了。
malloc_consolidate
简介
malloc_consolidate() 函数是定义在 malloc.c 中的一个函数,用于将 fastbin 中的空闲 chunk 合并整理到 unsorted_bin 中以及进行初始化堆的工作,在 malloc() 以及 free() 中均有可能调用 malloc_consolidate() 函数。
malloc_consolidate调用条件
1. malloc large bin
假如malloc的size大于small bin的范围,先调用malloc_consolidate将fastbin 合并为unsorted bin
在64位系统下,small bin <0x400
在32位系统下,small bin <0x200
2. top chunk不够空间
下面是简单的测试代码
1 |
|
3. 在free函数在各种合并前后chunk之后的size大于FASTBIN_CONSOLIDATION_THRESHOLD 也就是65536
比较容易实现的是与top chunk合并后size大于FASTBIN_CONSOLIDATION_THRESHOLD 具体大概是下面的流程
- 判断chunk是否属于fastbin,如果不是,继续
- 判断chunk是否属于map的,如果不是,继续
- 假如下一个chunk是top chunk,合并
- 判断当前chunk的size是否大于FASTBIN_CONSOLIDATION_THRESHOLD,假如大于,调用malloc_consolidate
测试代码如下
1 |
|
堆的leak大致方法
首先需要leak的内容:
1.主模块的基地址
2.heap的基地址
3.libc.so的基地址
常规流程是通过获取main_arena地址,因为main_arena存在于libc.so中可以通过计算偏移得到libc.so的基地址。再根据main_arena地址获得hook地址
然后要么system + binsh 要么one_gadget getshell
可供leak的漏洞
- 堆内存未初始化
- 堆溢出
- Use-After-Free
- 越界读
- heap extend
以上都可以进行leak。
UAF
uaf漏洞产生的主要原因是释放了一个堆块后,并没有将该指针置为NULL,这样导致该指针处于悬空的状态,同样被释放的内存如果被恶意构造数据,就有可能会被利用。
根本原因:
1 | 应用程序调用free()释放内存时,如果内存块小于256kb,dlmalloc并不马上将内存块释放回内存,而是将内存块标记为空闲状态。这么做的原因有两个:一是内存块不一定能马上释放会内核(比如内存块不是位于堆顶端),二是供应用程序下次申请内存使用(这是主要原因)。当dlmalloc中空闲内存量达到一定值时dlmalloc才将空闲内存释放会内核。如果应用程序申请的内存大于256kb,dlmalloc调用mmap()向内核申请一块内存,返回返还给应用程序使用。如果应用程序释放的内存大于256kb,dlmalloc马上调用munmap()释放内存。dlmalloc不会缓存大于256kb的内存块,因为这样的内存块太大了,最好不要长期占用这么大的内存资源。 |
(所以你看到的某些ptr = null , ptr = 0。 然后进入到堆块里查看内容,发现堆块里的内容还是能看得到以前写入的数据,但是不能读取,就是这了。它被打上了空闲标记,但是没有真正清除(大概是这个意思吧?))
一种是直接进行free,且没有进行任何限制的
这种直接malloc,delete,show。
另一种就是*没悬空,其他该置零的置零。
UAF配合fasted bin的cyclic list(double free)
off by one
off by one 配合chunk overlap ;unlink
堆的杂记
注意一点。
动态链接:
第一次放入unsorted bin里面的堆块地址距离main_arena为0x58
main_arena = leak_addr - 0x58
malloc_hook_addr = main_arena_addr - 0x10
静态链接:
第一次放入unsorted bin里面的堆块地址距离malloc_hook为0xD0
overlapping
前向:
修改第一个堆块的size位即可
后向:
修改要覆盖的最后一个堆块的p位和prev_size位即可。