double free
简介
Double Free 是一种常见的内存漏洞,发生在程序错误地两次释放同一块内存时。程序在使用 free() 函数释放内存后,如果不小心再次释放同一块内存,就会破坏堆内存的管理结构。
这种漏洞让攻击者可以利用程序的错误,操控堆内存的结构,进而可能控制程序的执行流程,执行恶意代码,甚至窃取敏感信息。为了避免这种情况,通常需要在释放内存后将指针设为 NULL,确保不会再次释放同一内存。
原理
fastbin
在 GNU 的 C 标准库实现 glibc 中,堆管理器 ptmalloc 会把较小的 chunk(默认 ≤ 64B)放入 fastbin。
fastbin 的特点:
- 只使用 单向链表
- 只用到
fd指针 - 不会立即进行合并(consolidate)
- LIFO(后进先出)
结构大概是:
1 | struct malloc_chunk { |
对于 fastbin 来说:
- 只使用
fd - 不检查
bk - 不做 unlink 操作
正常的 free 流程(fastbin 情况)
当:
1 | chunk_size <= max_fast |
并且:
1 | 该 chunk 不与 top chunk 相邻 |
则:
- 不进行合并
- 直接插入对应大小的 fastbin 链表头
- free 结束
插入方式是:
1 | free(chunk1) |
double free 原理
如果我们直接
1 | free(chunk1) |
系统就会直接检测到double free。
怎么绕过我们可以
1 | free(chunk1) |
这样系统不会检测到。
那我们怎么利用它呢?

然后我接着申请就会依次申请回来chunk2 ,chunk1,第三次申请就会把malloc_hook当做一个堆块申请过来,我们就可以该他的地址里保存
的内容。
例题
伪代码
1 | void __fastcall __noreturn main(__int64 a1, char **a2, char **a3) |
add函数
1 | unsigned __int64 sub_400A3F() |
可以看到在bss段上的结构题
bss[4 * i]和bss[4 * 1]存的是size
bss[4 * 2]和bss[4 * 3]存的是chunk的地址 bss的数组一个单位是4字节,但是储存地址的时候要8字节所以占用两个单位。
delete函数:
1 | unsigned __int64 sub_400B73() |
在delete函数中可以看到存在UAF漏洞,它只把size置0了,没把chunk置0。
直接放exp,解释都放在注释里了。
1 | # coding=utf8 |