Fastbin Attack 1
首先需要了解:
- fastbin大小(32位16-64Byte, 64位32-128Byte),fastbins中的chunk不改變它的
prev_inuse標志,也就無法被合并 - 首塊double free檢查,當一個chunk被free進fastbin前,會看看鏈表的第一個chunk【main_arena直接指向的塊】是不是該chunk,如果是,說明double free了就報錯,而對于鏈表后面的塊,并沒有進行驗證。
fastbin attack 是一類漏洞的利用方法,是指所有基于 fastbin 機制的漏洞利用方法。這類利用的前提是:
- 存在堆溢出、use-after-free 等能控制 chunk 內容的漏洞
- 漏洞發生于 fastbin 類型的 chunk 中
如果細分的話,可以做如下的分類:
- Fastbin Double Free
- House of Spirit
- Alloc to Stack
- Arbitrary Alloc
其中,前兩種主要漏洞側重于利用 free 函數釋放真的 chunk 或偽造的 chunk,然后再次申請 chunk 進行攻擊,后兩種側重于故意修改 fd 指針,直接利用 malloc 申請指定位置 chunk 進行攻擊。
原理
fastbin attack 存在的原因在于 fastbin 是使用單鏈表來維護釋放的堆塊的,并且由 fastbin 管理的 chunk 即使被釋放,其 next_chunk 的 prev_inuse 位也不會被清空。

數據結構回顧
- free chunk結構

- main arena預覽

- allocated chunk結構

Fastbin Double Free
fastbin 的 chunk 可以被多次釋放,因此可以在 fastbin 鏈表中存在多次。這樣導致的后果是多次分配可以從 fastbin 鏈表中取出同一個堆塊,相當于多個指針指向同一個堆塊,結合堆塊的數據內容可以實現類似于類型混淆 (type confused) 的效果。Fastbin Double Free 能夠成功利用主要有兩部分的原因
- fastbin 的堆塊被釋放后 next_chunk 的 pre_inuse 位不會被清空
- fastbin 在執行 free 的時候僅驗證了 main_arena 直接指向的塊,即鏈表指針頭部的塊。對于鏈表后面的塊,并沒有進行驗證。
typedef struct _chunk
{
long long pre_size;
long long size;
long long fd;
long long bk;
} CHUNK,*PCHUNK;
CHUNK bss_chunk;
int main(void)
{
void *chunk1,*chunk2,*chunk3;
void *chunk_a,*chunk_b;
bss_chunk.size=0x21;
chunk1=malloc(0x10);
chunk2=malloc(0x10);
free(chunk1);
free(chunk2);
free(chunk1);
chunk_a=malloc(0x10);
*(long long *)chunk_a=&bss_chunk;
malloc(0x10);
malloc(0x10);
chunk_b=malloc(0x10);
printf("%p",chunk_b);
return 0;
}
構造 main_arena=>chunk1=>chun2=>chunk1 的鏈表。之后第一次調用 malloc 返回 chunk1 之后修改 chunk1 的 fd 指針指向 bss 段上的 bss_chunk,之后我們可以看到 fastbin 會把堆塊分配到這里。
gcc fb_df.c -g -no-pie
輸出的值為 0x601090,這個值位于 bss 段中正是我們之前設置的CHUNK bss_chunk
值得一提的是,我們在 main 函數的第一步就進行了bss_chunk.size=0x21;的操作,這是因為_int_malloc 會對欲分配位置的 size 域進行驗證,如果其 size 與當前 fastbin 鏈表應有 size 不符就會拋出異常。
通過 fastbin double free 我們可以使用多個指針控制同一個堆塊,這可以用于篡改一些堆塊中的關鍵數據域或者是實現類似于類型混淆的效果。 如果更進一步修改 fd 指針,則能夠實現任意地址分配堆塊的效果 (首先要通過驗證),這就相當于任意地址寫任意值的效果。
參考