【堆利用】Fastbin Double Free

Double Free是針對fastbin的攻擊,字面意思就是重複釋放內存,也就是兩次free()同一塊內存導致的漏洞。

由於fastbin的機制,在滿足fastbin的chunk在被釋放後它下一個chunk的P位不會被置爲0,也就是說即使當前chunk被釋放掉了,但是他的next_chunk的P爲還依然爲1(1表示前一個chunk正在使用中),但他卻是已經被free()掉了,這樣做的目的是爲了防止chunk被合併(因爲現實證明,就是程序通常會申請小內存塊比較頻繁,如果每次申請釋放都重複分割合併,會導致性能非常低下,這也是爲什麼將P爲置1的原因,P位爲1代表前一個chunk正在使用中,就無法合併了,然後當我們申請的小內存滿足fastbin,就會直接從fastbin中直接返回chunk給我們),對於fastbin的ptmalloc實現而言,在我們free的時候僅僅驗證了main_arena直接指向的塊,也就是鏈表指針頭部的塊。當我們兩次重複free同一塊內存,就會觸發ptmalloc的驗證機制直接報錯double free(_int_free函數的檢測)

ptr = malloc(0x10);
free(ptr);
free(ptr); // 兩次連續重複釋放同一塊內存,就會報錯
// _int_free的檢測機制

但是要繞過這個檢測也非常簡單,因爲上面說了ptmalloc只驗證main_arena指向的塊,也就是頭部塊(就是每次釋放的chunk都和上一次釋放的chunk進行比較,如果發現是同一塊就會報錯)

ptr = malloc(0x10);
ptr1 = malloc(0x10);
free(ptr);
free(ptr1);
free(ptr); // 這樣也達到了重複釋放ptr指向的chunk的目的,但是不會觸發檢測機制,因爲上一次的釋放的事ptr1, 現在釋放的事ptr,只要ptr != ptr1 就會通過檢測,這樣的代碼不會有任何異常

正是因爲這樣,問題來了。
還要回到chunk的結構,我們知道chunk的free釋放以後,它本來的用戶空間會存放它的上一個釋放的chunk的指針,也就是fd指針(fastbin只使用了fd指針,釋放的chunk通過fd指針構成單鏈表,且滿足後進先出)會存放在size域的下一個字段fd,因爲這樣的結構,fastbin中的指針永遠指向最進一次釋放的chunk,申請的時候也是分配fastbin指向的chunk,所以就是一種典型的後進先出(最後釋放的chunk最先被申請)的結構。

第一次我們釋放ptr時候,fastbin指針指向ptr,此時fastbin中不存在已經釋放過的chunk,所以ptr的fd指針指向0
在這裏插入圖片描述
第二次釋放ptr1的時候,由於已經存在之前釋放的ptr,所以ptr1的fd指針就會存放ptr的指針,而且fastbin同時修改指針指向ptr1
在這裏插入圖片描述
第三次當我們又再一次free釋放ptr的時候,雖然之前已經free過了,但是現fastbin指向的chunk是ptr1,(也就是前面說得上一次釋放的chunk),並不會觸發_int_free的檢測機制,所以當又一次釋放完了ptr的時候,此時的結構就變成了,fastbin指向ptr,ptr指向ptr1,ptr1指向ptr,而ptr又指向ptr1
在這裏插入圖片描述
當我們重複釋放ptr,就會形成上面的結構

ptr = malloc(0x10);
ptr.fd = 0x1234; // 修改ptr的fd指針指向0x1234

當我們指向完上述的代碼後,現在又會變成什麼樣?

在這裏插入圖片描述
當我們再次分配內存的時候

malloc(0x10); // 分配到ptr1
malloc(0x10); // 分配到ptr
ptr_0x1234 = malloc(0x10);	// 再一次分配,內存就分配到了我們指定的位置了 	

這樣的話就可以實現任意地址寫了…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章