【逆向學習記錄】堆漏洞利用之Unlink

1 概述

前面雖然學習了堆的chunk及調試了部分簡單的案例,瞭解chunk的結構,但是針對堆的漏洞利用,還需要一個完整的實踐來進一步的驗證

參考:
ctf pwn中的unlink exploit堆利用
CTF-wifi–unlink
Linux堆溢出漏洞利用之unlink

2 Unlink操作

2.1 正常unlink的過程

在這裏插入圖片描述

P->fd->bk = P->bk.
P->bk->fd = P->fd.

2.2 利用過程

在ctf-wiki存在這麼一句話,我開始的時候,思考了半天,也不知道什麼意思,後來在這篇文章中發現一點蛛絲馬跡Linux堆溢出漏洞利用之unlink,這篇文章中,有個free的圖表,非常清晰

那麼 unlink 具體執行的效果是什麼樣子呢?我們可以來分析一下

FD=P->fd = target addr -12
BK=P->bk = expect value
FD->bk = BK,即 *(target addr-12+12)=BK=expect value
BK->fd = FD,即 *(expect value +8) = FD = target addr-12
看起來我們似乎可以通過 unlink 直接實現任意地址讀寫的目的,但是我們還是需要確保 expect value +8 地址具有可寫的權限。

比如說我們將 target addr 設置爲某個 got 表項,那麼當程序調用對應的 libc 函數時,就會直接執行我們設置的值(expect value)處的代碼。需要注意的是,expect value+8 處的值被破壞了,需要想辦法繞過

在這裏插入圖片描述
這裏爲了理解的更加深刻,我也手動畫一下,依然採用上面文章中的標識(32位)
在這裏插入圖片描述
由於P是可寫的,因此上面的第一條和第二條是主動寫進去的:

1、P->fd = FD = target addr -12
2、P->bk = BK =shell_code

unlink之後,執行兩個公式:

P->fd->bk = P->bk.
P->bk->fd = P->fd.

3、推導過程

P->fd->bk = P->bk 
---->  FD->bk = BK = shell_code
----> *(target addr-12+12) = BK = shell_code

4、推導過程

P->bk->fd = P->fd
----> BK->fd = FD = target_addr - 12
----> *(shell_code +8) = FD = target addr-12

因此在CTF-wiki中,任意地址寫的含義就是
執行unlink之後,可以

*(target addr) 修改爲 shell_code的地址
*(shell_code +8) 修改爲 target addr-12

在這裏插入圖片描述
因此:如果要修改Free的Got表的值,就需要將free_got_addr - 12 寫入P-> fd中,將修改後的內容比如system的真實地址,寫入P->bk中,經過unlink之後,addr中指向的內容就變成了system的地址了

2.3 unlink中的檢查

新版本的libc添加了檢查項:unlink時執行的檢查,以前的unlink是沒有檢查的,很容易利用,不過現在多了兩項檢查,所以在利用時候要繞過這些檢查。

Function Security Check Error
unlink chunk size是否等於next chunk(內存意義上的)的prev_size corrupted size vs. prev_size
unlink 檢查是否P->fd->bk == P 以及 P->bk->fd == P corrupted double-linked list

也就是說
在這裏插入圖片描述
內存意義上的size 等於next chunk(內存意義上的)的prev_size
檢查:P->fd->bk == P 以及 P->bk->fd == P

然後我們發現:
第一條比較好滿足也比較容易操作:同時分配兩個堆,將第一個堆進行溢出操作,寫第二個chunk的pre-size寫成當前p堆的大小。
第二條操作起來就比較複雜:需要找一段內存,恰好滿足上述條件
【CTF-Wiki】
首先我們通過覆蓋,將P的 FD 指針指向了 fakeFD,將 nextchunk 的 BK 指針指向了 fakeBK 。那麼爲了通過驗證,我們需要

fakeFD -> bk == P <=> *(fakeFD + 12) == P
fakeBK -> fd == P <=> *(fakeBK + 8) == P

在這裏插入圖片描述
unlink之後,執行兩個公式:

P->fd->bk = P->bk.
P->bk->fd = P->fd.

得到

fakeFD -> bk = fakeBK <=> *(fakeFD + 12) = fakeBK
fakeBK -> fd = fakeFD <=> *(fakeBK + 8) = fakeFD

如果讓 fakeFD + 12 和 fakeBK + 8 指向同一個指向 P 的指針,那麼:

*P = P - 8
*P = P - 12

最終達到的效果:
即通過此方式,P 的指針指向了比自己低 12 的地址處。此方法雖然不可以實現任意地址寫,但是可以修改指向 chunk 的指針,這樣的修改是可以達到一定的效果的。

因此,整個推導過程就是這樣了,最後記住了結論:P 的指針指向了比自己低 12 的地址處

3 unlink 堆漏洞利用案例

…待補充

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