Pwnable.tw-Secret Garden
Author
libc
glibc all in one 中沒有 2.23-0ubuntu5
所以去網路上找libc
https://launchpad.net/ubuntu/xenial/amd64/libc6/2.23-0ubuntu5
把i386載下來
1 | dpkg -X libc6_2.23-0ubuntu5_amd64.deb . |
在libs裡面就有ld跟libc了
patchelf直接patch上去
1 | patchelf --set-interpreter ld-2.23.so seethefile |
IDA
main
1 | void __fastcall __noreturn main(__int64 a1, char **a2, char **a3) |
總共有五個功能
menu
1 | int create() |
會先malloc一塊0x28大小的chunk(簡稱flower chunk),並初始化該chunk為0
再來讀取size,並malloc(size)
1 | 0x58f085d47470 0x0 0x30 Used None None |
先看flower chunk的內部
1 | pwndbg> x/10xg 0x58f085d47470 |
delete
1 | int delete() |
會去free name chunk
他會去檢查heap_arr是否為空
free完後會把 heap_arr所指向的 flower chunk設為0
這邊有double free,因為他沒有把heap_arr清空
clean
1 | unsigned __int64 clean() |
當name被刪掉的話,會去free flower chunk
show
1 | int show() |
分析
上述提到有double free,有任意寫,那目前難點就是leak libc,因為是2.23,leak libc後就可以直接改malloc hook或free hook
那就開排heap吧
我們可以任意malloc一塊任意大小的chunk,用unsorted bin,來leak libc,因為我們可以任意控name chunk,他malloc只會清掉flower chunk,所以想辦法malloc回來就可以leak libc
當初沒有注意到name chunk不會清空,以為flower跟name chunk都會被清空,所以想要利用unlink的方式將chunk推到他清空的範圍外(把flower chunk清空0~4當成name chunk),後來發現不用那麼複雜www
1 | from pwn import * |
這邊先malloc一塊大chunk,再來malloc一塊小chunk,防止unsorted bin chunk跟top chunk合併,之後free掉大chunk
可以看到大chunk fd bk都有libc address
之後malloc一塊 0x450,然而他會先malloc一塊0x30(從unsorted bin裡面割出去)
所以我們先clean,把原來的0x30 free掉,在malloc
就可以乾淨的拿到chunk了
並且我malloc後會蓋到fd,所以我們把fd padding成a,收bk的libc
之後就是老步驟,開attach gdb 找offset
1 | from pwn import * |
到目前為止已經leaklibc
那就來打double free
先觀察malloc hook 跟 free hook附近
free hook附近一片空白,那就打malloc hook
1 | chunk2 -> chunk3 -> chunk 2 -> ... |
malloc chunk 2,把chunk偽造於 malloc hook - 0x23
1 | chunk 3 -> chunk 2 -> mallochook - 0x23 |
malloc三次拿到
1 | from pwn import * |
當我打到這裡我發現了一件事
就是system(0x28)
會crash
也就是說透過修改malloc hook成system不可行
嘗試跳onegadget
1 | naup@naup-virtual-machine:~/Desktop/pwn/pwnable/secret_garden$ one_gadget libc_64.so.6 |
但試了許多次都沒辦法成功
因為並沒有滿足條件
突然想到之前在看house of roman有個trick,透過觸發 malloc_err 可以觸發到 malloc_hook
https://ctf-wiki.org/pwn/linux/user-mode/heap/ptmalloc2/house-of-roman/
試了一下成功get shell
exploit
本第第二第三第四個one gadget都可以用,但是遠端只有第二個可以用
1 | from pwn import * |
沒想到之前在 house of roman的梗會在這裡用到
File Structure打法
在打的過程中有想到另一種打法,去修改 _IO_2_1_stdout_
vtable,以下是利用方式
leak libc方式跟上方一樣
而leak heap方式是malloc三塊大chunk,用large bin 的fd_nextsize來leak
free三塊後之後malloc三塊
用show leak中間那塊就行了
1 | from pwn import * |
接下來用 fastbin dup構造任意寫,要寫哪裡觀察一下IO stdout內容,
要在這邊構造fake chunk非常容易,因為有很多的7…,可以當作size來malloc
另外看到_IO_2_1_stdout_+208
那行第二個是vtable
我們目標是攻擊__printf_chk,他會呼叫到 xsputn(vtable中的第八個),我們將vtable指向 IO_2_1_stdout自己本身讓第八個剛好是onegadget
1 | struct _IO_jump_t |
一步步來,首先是將fake chunk寫在這裡
並將原本stdout上有的蓋回去
1 | from pwn import * |
接下來我們在 0xffffffff 後蓋上onegadget (IO stdout + 200),並將vtable改成 IO stdout + 0x90
0x90+0x38(vtable 第八個) = 200
也就是 IO stdout + 200 會變成xsputn
換幾個onegadget測試最後一個會成功
exploit
1 | from pwn import * |
成功