看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

Editor發表於2017-06-29


今天週五了!看雪CTF 2017 比賽進行至第四題

截止至今天中午12點,第四題破解人數為14人!


看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

攻擊方排名前十名稍有變動,比賽排名有人升、有人降。

有兩位選手表現格外引人關注,

loudy從第9名升至第5名!(鼓掌ing)

NearJMP進入前十。

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

六月驕陽似火,也抵不過選手們的熱情。

大家繼續加油!

接下來我們來回顧一下第四題

看看看雪評委和出題者是怎麼說的ヾ(๑╹◡╹)ノ"



看雪評委 netwind 點評


作者設計了一個存在 double free 和 uaf 漏洞的程式,攻擊者需要利用 fastbin 的 malloc_consolidate 函式來造成 unlink,最後再佈置棧構造 ropchain 即可完成攻擊。作為一道漏洞挖掘和利用的題目,引起了大家廣泛關注,成功破解該題人數達14人,並且漏洞利用各有千秋,甚至有人透過作者疏忽利用棧溢位破解了此題,攻防雙方表現都非常精彩!


作者簡介:


Ree,大二在讀,CTF比賽 Pwn 選手,興趣廣泛,熱愛漏洞挖掘與利用。目前主要研究方向為二進位制自動化分析。


看雪 CTF2017 第四題設計思路


考點

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功能無效

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

3. create 函式可以申請一個小於 4096 位元組的 chunk,並往裡面寫入資料,然後置flag位為1,同時用一個全域性變數 number 來記錄已申請的 chunk 個數,number不得大於4。

4. delete 函式可以 free 一個指標並置 flag 位為 0,但是不檢查是否已經 free 這個指標。

5. edit 檢查 flag 位,只能修改已經 flag 為 1 的 chunk。

6. 資料結構如下:

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

漏洞點

1. uaf,在dele一個指標後沒有清零,可以再次 free 這個 freed 的指標。

2. 漏洞什麼的。


漏洞利用

1. 主要利用 fastbin 的 malloc_consolidate 這個函式來造成 unlink,後面再佈置棧構造 ropchain 即可。

2. 在申請 large bin 的時候,會將 freed fastbin 的 inuse 位清零,同時進行合併,將合併後的堆塊放入 unsortbins 中。然後遍歷 unsortbins,按照大小分別放入 smallbins 和 largebins 中。

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

3. 這時利用 uaf,free 一個 fastbin,也就是我們剛才申請的 0x30 大小的塊,將它鏈入 fastbins 的單向連結串列中。因為當我們從fastbins中分配不會置後一個 chunk 的 inuse位為1,但是由於之前的 malloc_consolidate 已經使得該 fastbin 的後一個 chunk 的 inuse 位為 0,所以造成一個矛盾,是的我們能夠 unlink。

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

4. 分配一個 0x20 大小的 chunk,置後一個 chunk 的 presize 位為我們剛才分配的fastbin 的大小,為 unlink 做準備,0x20 會從之前合併的 smallbins 中切割,然後該 smallbins 移到 unsortbins 中,併成為 last_remainder。

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

5. 修改 0x30 的 fastbin,並填充 unlink 的 payload,再在之後分配一個 smallbin 大小的 chunk,使得 unsortbin 中的 chunk 移到smallbins(因為 unsortbins 有一個 check,會檢查第一個 chunk 的 bk 是否指向 unsortbin 的頭),最後 delete 觸發 unlink。

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

6. 接下來的事情就簡單了,修改 fflush 的 got 表為 add rsp 8; ret 的 gadget,然後用rop 洩露 libc 基址,最後修改 free_got 為 system 即可。

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

7. free 一個事先寫好 /bin/sh\0 的 chunk 拿 shell 即可。

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

PS:

因為可以 malloc 任意大小,還有 uaf,漏洞略大,但已經盡力避免未預料解法了。

PPS:

好像國內的 CTF 還沒見過考 malloc_consolidate的,也可能我比賽打的少了XD...

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路


看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路


下面選取攻擊者 BPG 的破解分析


一、ALL

這題也是一般堆溢位的流程,主要有下面幾個操作:

1. 建立

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

這一段程式碼比較多,但可以看到問題還是存在的,size和cun都是可以透過輸入負數,接著透過強型別轉換`unsigned int`來轉換成很大的整數來整形溢位。

2. 刪除

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

可以看到這裡也是存在問題的,刪除之前沒有判斷塊是否被刪除了,所以應該可以構造`double-free`

3. 編輯

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

這裡就是正常的編輯,不過驗證了塊是否存在。

二、DOUBLE-FREE

一年前做過一道`double-free`之後就再也沒碰過了,這裡正好把相關知識點再溫習一下。

堆結構如下,其中0,1,2,3表示一個單位長度。

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

正常`unlink`的函式主要程式碼如下:

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

如果能覆蓋一個塊的頭部來達到控制其`bk`和`fd`的話,就能夠成功修改任意地址的值了,但由於存在判斷`FD->bk != P || BK->fd != P`,所以沒法隨便修改,這時就需要利用`double-free`了。

首先判斷是需要透過的,所以可以有下面兩個等

FD->bk = P   <=> FD+3 = P
BK->fd = P   <=> BK+2 =

接著就是構造一個堆頭滿足這兩個等式了

pre_size     0
size         chunk_size + 1 //這兩個條件表示堆仍在使用中
fd           p_addr - 3
bk           p_addr - 2

那麼就能得到繞過判斷後能實現的效果

FD->bk = BK => P = BK = P - 2
BK->fd = FD => P = FD = P - 3

所以最後實現的效果是`P=P-3`。

接著就是實現`double-free`的流程了,稍微盜一下圖...

1. 新建兩個 chunk 分別為 chunk0 和 chunk1

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

2. free 掉這兩個塊,第一塊作為稍後 unlink 的塊,另一塊作為 free 的塊

3. 新建一個塊,這個塊要能覆蓋到 chunk1 的頭部,從而偽造兩個 chunk 的頭,chunk0 的頭部之前已經說過了,而 chunk1 需要欺騙作業系統 chunk0 是已經被free 了的,所以其頭部應該如下

pre_size     chunk0_size
size         chunk1_size

然後整體實現如下:

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

4. 那麼新建這個塊就相當於是兩個塊了,然後我們 free chunk1,就能實現 unlink chunk0 從而使得 chunk0 的地址存放的值變成了 P-0x18

5. 接下來修改 chunk0 的值,修改的值為 0x18 個 padding,然後就能修改 chunk0 的地址的值了,這時修改成 free 的 GOT 表地址

6. 接下來再修改一次chunk0, 這次的值修改成 system 那麼就會使得 free 的 GOT 表指向 system,接下來 free 的時候傳入 /bin/sh 就能獲取 shell 了

三、 EXP

在除錯 EXP 過程中出現了這樣倆個問題,需要注意一下。

第一個是這裡的 P 指的是指向堆地址的指標,也就是`0x6020e0`,不要誤以為是堆的地址哦。

第二個在這裡我是把`/bin/sh`寫在第0個堆,而用2,3來進行`double-free`,主要原因是由於在除錯的過程中發現把`/bin/sh`寫後面會被系統發現`double-free`。

具體EXP:

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路

看雪.WiFi萬能鑰匙 CTF 2017第四題 點評及解題思路


最後感謝 WiFi 萬能鑰匙安全應急響應中心的贊助支援,

接下來的比賽大家一定要使出洪荒之力哦!↖(^ω^)↗

比心


贊助商

上海連尚網路科技有限公司成立於 2013 年,是一家專注於提供免費上網和內容服務的移動網際網路企業。連尚網路自主研發的核心產品 WiFi 萬能鑰匙,以分享經濟的模式,透過雲端計算和大資料技術,利用熱點主人分享的閒置WiFi資源,為使用者提供免費、穩定、安全的上網服務,以幫助更多的人上網,找到屬於他們的機會,改變自己的命運。


相關文章