1. 程式人生 > >看雪wifi萬能鑰匙CTF年中賽 第四題 writeup(2)

看雪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~~~