软件安全与脆弱性分析-对于freenote小程序的Poc分析
最近上軟件安全與脆弱性分析課程,對freenote小程序(貌似是某一年的CTF題)進行了依次Poc分析。感覺很有意思,在這里對分析過程進行一個總結。
1.程序功能介紹
給定的程序運行界面如上圖所示,大體上分為五個模塊他們分別為:(1)列出已經存儲的記錄、(2)添加新的記錄、(3)編輯指定的記錄、(4)刪除已經存儲的記錄、(5)退出程序。
將note程序加載到ida中,可以得到程序的匯編代碼部分,動態調試后可以得到程序初始化后的開始位置:
在ida中進入到不同的功能函數中,利用反匯編可以得到功能函數的偽代碼部分分別如下:
(1)列出已經存儲的記錄功能函數的偽代碼:
(2)新建記錄功能函數的偽代碼:
(3)編輯已經存儲記錄功能函數的偽代碼:
(4)刪除已有記錄功能函數的偽代碼:
(5)退出程序功能函數僅調用庫函數puts()實現字符串“bye”的輸出;
同時,根據note初始化函數,分析note存儲結構我們可以推斷其大致如下:
??????? 所有note都存儲在堆中,塊大小四舍五入到0x80字節的下一個倍數
??????? 有一個表存儲指向note的指針,以及它們的大小和一個表示它們當前是否正在使用的標志
??????? 該表最多可以存儲256個note,并且在程序初始化期間也被分配到堆上
??????? 在刪除一個note時,相應的塊被釋放,并且在表中清除了in_use標志
其中n表示表格中可用槽的數量(256)(8字節),m表示已使用槽的數量(在上例中為兩個)(8字節)。Note entry包括(8字節)標識(是否被使用),(8字節)長度,(8字節)指針。
2.Poc分析
通過上一部分的分析,我們對note程序的框架有了一個基本的了解,接下來利用動態分析,對程序的崩潰點進行分析;
我們按照Poc提示的輸入內容,對程序進行實驗,在輸入第二次刪除已有記錄操作的時候,可以發現程序發生了崩潰,實驗分析截圖如下:
輸入:
2
6
aaaaaaaaaaaaaaaaa
分析:
qword_6020A8地址如下:
?
查看該地址:
note該結構共有256(0000 00000000 0100)個可使用空間,已使用1(0000 0000 0000 0001)個空間,第一個note在使用中,標志符為1(0000 0000 0000 0001),長度為6(0000 0000 0000 0006),地址為(0000 0000 0154 2830)。查看如下:
?
輸入:
2
8
bbbbbbbbbbbbbbbbbbb
分析同上:
?
?
輸入:
2
10
cccccccccccccccc
分析同上:
?
輸入:
4
1
分析:
?
輸入:
4
1
分析:
程序crash,刪除時沒有檢查該note是否被使用。
根據Poc的輸入我們發現在對同一個記錄進行兩次刪除操作,而導致了程序崩潰,所以我們判斷對記錄進行刪除的功能函數里面出現了錯誤從而導致程序崩潰,在刪除記錄函數部分設置斷點,進行動態調試的過程中可以發現,程序在第二次刪除與第一次擁有相同記錄號的記錄時,發生了錯誤,錯誤的位置為調用庫函數free();
找到程序錯誤位置后,我們再利用ida反匯編功能,進入到刪除記錄函數的偽代碼中去仔細觀察,發現程序在刪除記錄的時候并沒有檢查記錄號對應的記錄的狀態,即并沒有檢查所要刪除的記錄是否已經被刪除過,所以當再次刪除已經刪除的記錄時,庫函數free()將對已經釋放的空間再次釋放,從而產生double free的錯誤,導致程序崩潰,至此我們對note程序的崩潰有了一個完整認識。
3.漏洞利用
???????? 通過對漏洞位置的確定,我們可以針對漏洞產生的函數free()來構造漏洞的利用手段,大體上分為兩個部分,一是對程序存放堆中note起始的位置的確定,二是通過構造虛假的chunk塊達到更改GOT表項free()函數對應的地址位置,來實現攻擊。
3.1Linux下的堆內存管理基礎
想要根據free函數進行漏洞利用,我們需要了解Linux對堆塊管理的基本知識,Linux中對堆塊使用malloc_chunk的數據結構進行管理,數據結構的定義如下圖所示:
其中prev_size指連續虛擬地址中當前塊即chunk相鄰的前一塊,它占據的存儲空間大小;size指當前塊占據的存儲空間大小;fd和bk指針只有在數據塊沒有被使用時才有效,他們分別指向前一塊沒有被使用的數據塊和后一塊沒有被使用的數據塊,這里涉及到了Linux下對空閑chunk的管理,利用bins鏈表將空閑的存儲塊按照存儲空間的大小進行分類管理。當程序釋放一個chunk塊的時候,操作系統將會在在釋放快的前后連續的虛擬地址空間進行判斷,看是否其前后的塊已經是被釋放的塊,如果是則會將該塊從空閑鏈表隊列即bins隊列中刪除(unlink),與當前釋放塊進行合并后再次放入對應的bins鏈表中,在進行unlink操作的過程中,若對P進行刪除,則會進行P->bk->fd=P->fd與P->fd->bk=P->bk這兩個操作,具體的unlink函數定義如下。
在了解了Linux下的堆內存存儲管理后,我們還需要了解GOT表項,簡單來說在Linux下,如果一個程序執行的過程中需要調用外部庫函數,則會去GOT表項中尋找對應的外部庫函數的地址,例如本程序在執行free操作的時候,就會去GOT表項中尋free函數對應的地址,拿到對應的地址之后便可以執行free操作。
3.2note堆首地址確認
這一部分,主要實現對存儲note的堆的基址的確認,只有確認了基址我們才能在后面的步驟中進行chunk的偽造。確認地址的步驟如下:
(1)新建四個note,分別記為note0、note1、note2、note3存儲“a”或任意其他字符,得到的note表已經具體的chunk布局如下:
(2)依次將note0與note2進行free操作,此時可以在bins鏈表中找到note0與note2對應的地址,表示他們已經作為未被使用的chunk被系統所回收,且note0的bk指針將會指向note2;
(3)再次創建一個新的note,使其滿足8字節的內容大小如“12345678”,系統根據FIFO原則會將首次釋放的note0空間分配給新的note,且note0中fd指針的位置會被新note的數據內容所覆蓋,而bk指針因為新存note的長短則不會被覆蓋,又因為新存入的字符串沒有結束符,則在讀取字符串的過程中會將其后面的bk內容也讀出,根據bk所指向的地址空間位置,進行簡單地計算后我們便能夠得出存儲note0的位置;
3.3構造偽chunk替換GOT中的free函數地址
在上一小節中,我們得到了存儲note的首地址,根據首地址我們重新建立三個note,第一個note包含我們偽造的chunk,其中這個偽造的chunk我們使其狀態為已經釋放,且fd指向chunk的bk與bk指向chunk的fd相同(滿足后面所述的unlink條件),第二個note為真chunk,將其內容存為“/bin/sh”,第三個note存儲若干偽chunk,內容可以用字符串“a”代替,在進行了上述操作后,我們得到了兩個chunk組,一個為真一個為假,他們布局分別如下圖所示:
接下來我們要進行的操作就是修改GOT表項中free函數的地址使其被我們想要執行函數的地址所替代。
由上圖可知,一開始創建的四個note中note3地址為0X6049d0,所以首先對note3進行釋放操作,此時操作系統會檢測當前地址前一個chunk所處的狀態,而其前一個chunk,根據size與pre_size計算得出剛好就是我們新建的note0中的偽造的那部分chunk,由于當前釋放的chunk中0x90字段的最低位表示了前一個chunk為釋放狀態,且它的fd與bk在構造時滿足unlink條件(fd->bk=bk->fd=p)則會對其進行unlink后與當前請求釋放chunk進行合并操作。
??
合并前note表部分布局如下圖所示,其中note0的地址是正常的存儲note0內容的地址。
?
在進行unlink的過程中,設unlink的對象為P,P結構如下所示。
則會進行P->bk->fd=P->fd與P->fd->bk=P->bk的操作,那么P->bk指向的地址為0X603020,它所表示的chunk的fd指針的地址為0X603030,其內容0X604830將會被改寫為P->fd即0X603018。同理p->fd所指向的地址為0X603018,它表示的chunk的bk指向的地址也為0X603030,其中內容將會被改寫為P->bk即0X603018,得到note表如下圖:
此時如果我們對note0記錄進行編輯操作,系統會按照note0對應的地址對note0進行修改(實際上已經在修改note表項),那么我們可以將note0對應的地址改為GOT表項的地址,當我們查看note0時,系統將會根據note0在note表中的地址(此時已經是GOT表項)打印給我們,這時,我們可以根據free字段去修改free函數對應的函數地址,將其改為我們想要程序執行的函數如system,這是如果我們再次釋放note1,則程序會利用GOT表項中的free字段對應的函數地址(此時已經為system函數地址)來調用system(“/bin/sh“)了。
至此,我們通過利用Linux堆內存管理體制中unlink操作下的漏洞成功攻擊了程序,實現了note程序的漏洞利用。
參考資料:
http://rk700.github.io/2015/04/21/0ctf-freenote/
https://kitctf.de/writeups/0ctf2015/freenote
https://www.cnblogs.com/alisecurity/p/5520847.html
總結
以上是生活随笔為你收集整理的软件安全与脆弱性分析-对于freenote小程序的Poc分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IO的简介
- 下一篇: 任卫红:关键信息基础设施的等级保护