在程式中,free() 被設計來釋放動態配置的記憶體空間。
Double Free 漏洞就是指 同一個記憶體區塊被 free() 了兩次或以上。
這會破壞 malloc/free 的內部資料結構(例如 fastbin freelist、tcache freelist),進而讓攻擊者能夠控制之後 malloc() 返回的記憶體位置。
常見原因:
NULL,導致之後還能被 free()。#include <stdio.h>
#include <stdlib.h>
int main() {
    char *a = malloc(0x40);
    free(a);
    free(a); // 🚨 Double Free
    return 0;
}
| glibc 版本 | 狀態 | 說明 | 
|---|---|---|
| < 2.26 | 高度可利用 | fastbin 沒有太多檢查,Double Free 幾乎可直接利用 | 
| >= 2.26 | 增加檢查 | 引入 tcache,針對連續釋放同一 chunk 有檢查,但仍可透過技巧繞過,例如交錯釋放或偽造 fd | 
假設有一個 chunk A 被 free 了兩次,它會被插入 fastbin freelist 兩次:
fastbin -> A -> A -> ...
之後 malloc() 會依序取出,導致同一個指標被多次分配。
攻擊者可以:
在 glibc 2.26 之後,引入 tcache:
#include <stdio.h>
#include <stdlib.h>
int main() {
    char *a = malloc(0x40);
    char *b = malloc(0x40);
    free(a);
    free(b);
    free(a); // 🚨 Double Free
    return 0;
}
| 步驟 | 操作 | freelist 狀態 | 攻擊者效果 | 
|---|---|---|---|
| 1 | free(a) | a | chunk a 進入 freelist | 
| 2 | free(b) | b -> a | chunk b 進入 freelist | 
| 3 | free(a) again | a -> b -> a | chunk a 再次進入 freelist | 
| 4 | malloc() -> a | b -> a | 指標 a 分配到 chunk a,可控制內容 | 
| 5 | malloc() -> b | a | 指標 b 分配到 chunk b,可操作 a 內容## | 
| 方法 | 說明 | 
|---|---|
| 設指標為 NULL | 每次 free 後將指標設為 NULL,避免重複釋放 | 
| 使用安全記憶體管理 | 如 smart pointer 或 RAII 機制 | 
| glibc 檢查 | 新版 glibc 會檢查 double free,但仍需注意程式邏輯漏洞 |