看雪wifi萬能鑰匙CTF年中賽 第四題 writeup(2)
上一篇題解是學習的poyoten的姿勢,這個呢,是學習到了loudy大神的姿勢
首先呢:要把sys_rva和put_rva以及free_rva換成本地libc的偏移值,姿勢如圖
按照第一篇的方法,給程式碼加上gdb斷點
gdb.attach(p, 'b *0x400ce9 \nb *0x400d01 \nb *0x400b62')
然後看看程式在執行的時候發生了什麼
首先是多個create建立堆,注意一一和資料結構的指標對應好
上圖表示:0x6020c0這裡儲存的是指標,指標指向的是各個堆塊的大小(也就是4個create的160位元組大小)
上圖表示的是heap中的資料儲存,說明4個create成功建立
這裡的0x6020e0,是heap的資料儲存的結構體,一個heap資料是16個位元組,第一個8個位元組是ptr指標,指向的資料存放的地址;第二個8個位元組是flag的一個標記,flag=1表示當前的heap是正在使用中的
其實,最關鍵的是這個create(-2)會發生什麼?
分析一下heap的資料結構
6020c0地址這裡儲存的是每個堆塊的大小,除錯下可以看到
6020e0這裡是個指標,儲存的是我們輸入的堆塊內容的地址的值,6020e8這個地方是個flag的標記,說明這個堆塊是否用過了
所以!這個-2!
會導致分配的記憶體資料的值,會覆蓋掉第0塊記憶體的大小
因為6020e0[-2],這個地址,其實是6020c0!(6020e0這個結構體的大小是0x10的,-2相當於兩個偏移)
看下我們的除錯結果
這裡的0x64,說明create(-2)已經成功了
接下來是對payload =p64(0x0)+p64(0xa1)+p64(ptr_addr-0x18)+p64(ptr_addr-0x10)+'a'*0x80+p64(0xa0)+p64(0xb0)
注意到每個堆塊的大小都是0xa0
p64(0x0) + p64(0xa1)表示前一個chunk正在使用中,當前chunk尺寸為0xa0
p64(X-0x18) + p64(X - 0x10)表示的fd和bk的指向地址(unlink的標準操作)
p64(0xa0) + p64(0xb0)表示前一個chunk未使用,大小為0xa0,當前chunk的尺寸為0xb0
所以我們修改的是“-2”的unlink
payload2 =p64(0x0)+p64(0x1)+p64(0xa)+p64(0x602018)+p64(1)+p64(0x603110)+p64(0xa)+p64(0x602020)
edit_ex('0',payload2)
這裡,p64(0x0)是heap[“-2”]的沒有被使用的標記
p64(0x1) + p64(0xa)是修改的heap[-1]
p64(0x602018) + p64(1)是修改的heap[0]
p64(0x603110) + p64(0xa)是修改的heap[1]
p64(0x602020)是修改的heap[2]
602018:free的got地址!
602020:puts的got地址!
所以,是殊途同歸的,都是想要利用unlink,來修改free成system來提權
這裡說明了free被覆蓋成了puts的地址
我們可以利用puts函式把puts的地址輸出,再根據libc的偏移,計算出system的地址
再覆蓋到free的got表中
於是,system('/bin/sh')提權,得到flag~~~