前言
由於目前看到 heap 題都像看到鬼一樣
所以開始讀 how2heap
我偏好看完一種利用方式就找個題目練習 或是自己出
因此有了這篇 Writeup
題目
檔案在我的 github 裡
這隻程式可以儲存、尋找、刪除字串
存字串的時候如果包含空格 例: “deadbeef hihi”
會被切成兩個部分 “deadbeef”, “hihi”
不過在刪除的時候只要搜尋 “hihi”
就可以刪掉整個 “deadbeef hihi”
Bug
leak stack address
0x400A40 這個 function 可以 leak stack address
input_sentence 不會把最後一個 Byte 設為 0
所以只要塞 0x30 個字到 nptr 就有機會把 stack address 吐出來
use-after-free
這一段是在做搜尋 然後找到字串後會詢問是否刪除
sentence_list 會指向 sentence_node
sentence_node 結構大概長這樣:
雖然刪除的時候會刪掉字串內容
但是 sentence_list 不會被清除
只要想辦法讓他再找到同個字串就可以 double free
( 其實直接找 ‘\x00’ 就可以了 詳情請參考這篇 )
另外搜尋字串一開始會 malloc 一個空間出來
會在函數的尾端 free 掉
但是並不會清除內容
所以可以利用它重設 sentence_list 裡的字串值
我的解法
要小心 malloc 出來的 chunk size 不要落在 0x30
因為會跟 sentence_node 衝到
所以放出來的 chunk size 我控制在 0x40
而且在 return address 附近
0x0000000000000040 這樣的值比較好找 XD
a 字串前面放八個空白是因為 chunk size 0x40 被 free 的時候
前面八個 Byte 會被拿去用來指向其他一樣大小的 free chunk
也就是 free chunk 結構裡的 fd
search_sentence 只做查詢的動作 不會刪除東西
剛好 fastbin 狀態為 HEAD->a->b->TAIL
所以查詢時調整一下 chunk size 就能拿到 a chunk
然後把字串塞進去
因為最後會被 free 掉且不會清除內容
所以我們的 a 字串的 a 又回來了!
Get double free!
成功寫到 return address 之後
要先把能寫的 stack 放大
不然會塞不下 ROP…
leak 在 main function return address 的附近
用來放我的第一個 ROP ( 第四行 )
這邊加上偏移後會落在 input_sentence 後面
然後繼續輸入下一次的 ROP
我利用它本身輸入字串的函數 (0x4009B0)
把值寫進去
缺點是 rdx 如果剛好是 0
只要出現 0x0a 這個 Byte 就會被濾掉
剩下就是 leak libc base address
跳到 one_gadget 就拿到 shell 了!
( 我不是在當下解的 所以 libc offset 會不准 )
看到別人的 writeup 之後發現 libc base address
還可以利用 smallbin 拿到 詳情請看這裡
這世界存在著各種奇技淫巧
完整的 code 在我的 github 裡