malloc_consolidate+unlink+rop
1. amd64(作者本地測試為kali,遠端測試環境為ubuntu16.04),無libc要求,已經上傳遠端測試libc
2. 開啟aslr
gcc -no-pie main.c -o main ; strip main
題目可以給出 bin 與 libc 供下載,也可以僅給出 bin 檔案,透過查詢 libc-db 的方式找到對應 libc 版本號(作為一隻 pwn 狗,建議給出 libc,省去大家查 libc 的浪費的生命)
1. 首先給使用者輸入姓名,此時以 malloc 一個 chunk 的方式儲存使用者的輸入
2. 給了 4 個功能,create、delete、edit、show,其中show功能無效
3. create 函式可以申請一個小於 4096 位元組的 chunk,並往裡面寫入資料,然後置flag位為1,同時用一個全域性變數 number 來記錄已申請的 chunk 個數,number不得大於4。
4. delete 函式可以 free 一個指標並置 flag 位為 0,但是不檢查是否已經 free 這個指標。
5. edit 檢查 flag 位,只能修改已經 flag 為 1 的 chunk。
6. 資料結構如下:
1. uaf,在dele一個指標後沒有清零,可以再次 free 這個 freed 的指標。
2. 漏洞什麼的。
1. 主要利用 fastbin 的 malloc_consolidate 這個函式來造成 unlink,後面再佈置棧構造 ropchain 即可。
2.
在申請 large bin 的時候,會將 freed fastbin 的 inuse 位清零,同時進行合併,將合併後的堆塊放入
unsortbins 中。然後遍歷 unsortbins,按照大小分別放入 smallbins 和 largebins 中。
3.
這時利用 uaf,free 一個 fastbin,也就是我們剛才申請的 0x30 大小的塊,將它鏈入 fastbins
的單向連結串列中。因為當我們從fastbins中分配不會置後一個 chunk 的 inuse位為1,但是由於之前的
malloc_consolidate 已經使得該 fastbin 的後一個 chunk 的 inuse 位為 0,所以造成一個矛盾,是的我們能夠
unlink。
4.
分配一個 0x20 大小的 chunk,置後一個 chunk 的 presize 位為我們剛才分配的fastbin 的大小,為 unlink
做準備,0x20 會從之前合併的 smallbins 中切割,然後該 smallbins 移到 unsortbins 中,併成為
last_remainder。
5.
修改 0x30 的 fastbin,並填充 unlink 的 payload,再在之後分配一個 smallbin 大小的 chunk,使得
unsortbin 中的 chunk 移到smallbins(因為 unsortbins 有一個 check,會檢查第一個 chunk 的 bk
是否指向 unsortbin 的頭),最後 delete 觸發 unlink。
6. 接下來的事情就簡單了,修改 fflush 的 got 表為 add rsp 8; ret 的 gadget,然後用rop 洩露 libc 基址,最後修改 free_got 為 system 即可。
7. free 一個事先寫好 /bin/sh\0 的 chunk 拿 shell 即可。
PS:
因為可以 malloc 任意大小,還有 uaf,漏洞略大,但已經盡力避免未預料解法了。
PPS:
好像國內的 CTF 還沒見過考 malloc_consolidate的,也可能我比賽打的少了XD...