【技術分享】Glibc-2.23 源碼分析——free部分(上)
前言
終于抽出時間對glibc動態內存管理部分源碼進行初略的探究,試著從源碼和動調來分析free函數執行過程和一些pwn的攻擊技巧,分析的不是很全面,有錯誤的地方望提出指正,共同進步。
Free in fastbin
正常情況下的free in fastbin
測試代碼

Free -> libc_free,正常進入 free(p1)時,free_hook為空,修改free_hook為onegadget或者其他payload 可以任意執行

非mmap空間,進入 int_free()

Chunk_size的檢查


Chunk_size <= 0x80 進入 fastbin的處理

對相鄰下一塊chunk進行size的對齊檢查

Fastbin 建立 與串聯鏈表 部分


觸發double free 異常
free(p1);free(p1);
此時free_chunk與 old相等 導致報錯

Double free繞過方式
測試代碼

Double free p1需要先釋放另一個滿足此fastbin size的堆塊,修改old

運行結果

再次申請一個fastbin size的chunk,修改chunk的fd指針后,完成use after free,控制fastbin的申請區域
Use after free
代碼

釋放堆塊后未對指針置空,并且能修改指針的情況下,可以直接use after free
運行結果:
之后第二次的malloc(0x20 ~ 0x2f)的申請 可以請求到構造的fake_chunk地址上。

Malloc in fastbin
測試代碼

Fastbin 處理代碼 位于 int_malloc(),類似于int_free()中fastbin處理,是一個相互的逆過程

fastbins鏈表結構為 main_arena + 0x10 -> p2 -> p1->0

對于取出fastbins表頭的校驗

之后對fastbin[0x20]表進行替換列表頭的操作

之后對取出chunk的size進行檢測(偽造size需要滿足size移位之后等于對應的idx,即 若idx=7時fake_size應滿足 0x70 ~ 0x7f)

程序運行結果

Free in unsortedbins
第一次進行free_in_unsortedbin
測試代碼

由free() -> __int_free(),不滿足之前對于fastbin的檢測后,接著進行下面的邏輯判斷,對于top_chunk的保護以及size是否對齊的判斷

之后進入 unsortedbin 的處理部分(涉及 chunk overlap繞過技巧)

之后進入 unsortedbin 的鏈表處理,此時 fwd == bck,之后進行unsortedbin雙鏈表的串聯

此時的鏈表示意圖,為了方便展示將fwd 和 bck分開放置

堆塊向前overlapping
測試代碼

通過置空prev_inuse 設置fake prev_size 欺騙unsortedbins的合并堆塊機制

構造合適的prev_size 可以使堆塊合并在已經被free的unsortedbin上,吞并未被釋放的p2,p3

fake_prev_size = size_p1 + size_p2 + size_p3 = 0xb0 + 0x20 + 0x20 = 0xf0
之后重寫寫上size+ prev_size 的chunk頭和下一塊堆塊的prev_size后,完成堆塊的吞并

之后再申請出制定大小的堆塊后,可以用于構造fastbin中的use after free


Unlink
測試代碼
How2heap/glibc-2.23/unsafe_unlink.c
Unlink觸發過程,偽造上一個堆塊已被釋放

unlink函數源代碼

構造的堆塊

Gdb沒有掛載到unlink函數 直接分析匯編代碼對應源碼
p->prev_size 是否為0

builtin_expect (P->fd_nextsize->bk_nextsize != P, 0)

builtin_expect (P->bk_nextsize->fd_nextsize != P, 0)

之后匯編代碼邏輯

目標地址 0x601068(P->fd_nextsize -> bk_nextsize P->bk_nextsize -> fd_nextsize 為同一地址)
目標地址先被寫上 p->bk_nextsize(0x601058)

接著寫上 p->fd_nextsize(0x601050)

Unlink構造條件
1.偽造 被釋放堆塊的prev_inuse和prev_size
2.偽造被釋放堆塊的prev_chunk 的 fd_nextsize 和 bk_nextsize
3.fd_nextsize = target – 0x18 bk_nextsize = target – 0x10,目標地址target 被寫上 fd_nextsize
Malloc in unsortedbins
正常處理邏輯
測試代碼

對 0x128 的unsortedbins 申請 0x100的chunk
unsortedbin 申請chunk代碼段在 _int_malloc()函數中


運行效果:清空unsortedbins的操作為在 main_arena中清空 bins 表

之后 通過bck賦值變量fwd

改變申請的堆塊的fd和bk指針

申請出的chunk被串入雙鏈表

之后將申請出的chunk寫上正確的size,并將剩余的bin串入 unsortedbins 并且寫上size


Remainder 堆塊的設置


House_of_lore
若雙鏈表的bk指針被篡改指向偽造區域,并且在偽造的區域滿足fd指針等于victim,申請到的堆地址將可控
測試代碼:
how2heap/glibc-2.23/house_of_lore.c
先利用正常情況free一個smallbin進入 unsortedbins

此時雙鏈表正常,之后篡改 unsortedbin的bk指針

之后進入 _int_malloc()的處理的校驗邏輯

偽造的堆塊被串聯進入 bin

再次申請smallbins,申請到了偽造區域
