- 知識背景
- 棧溢出及防護
- 堆溢出及防護
一顶别、知識背景
關(guān)于棧溢出的知識背景
1. 典型操作系統(tǒng)的內(nèi)存布局:
分段的意義:
緩存命中率高、訪問控制
2. 進程的內(nèi)存布局:
3. 堆棧的區(qū)別:
地址增長方向
heap - 堆 地址從小到大
stack - 棧 地址從大到小
支持及作用
棧時具有硬件直接支持的拒啰,棧存儲數(shù)據(jù)和控制流信息。
堆是由操作系統(tǒng)的庫函數(shù)予以支持的完慧,堆存儲數(shù)據(jù)谋旦。
4. ESP與EIP:
esp - 棧指針寄存器
esp指向棧頂(存儲棧頂?shù)牡刂罚?br>
push則esp減
pop則esp增
eip - 指令指針寄存器
eip指向.test中存放的代碼指令,指向的指令為即將被執(zhí)行的指令屈尼。
5. 棧的工作原理:
棧的作用:為函數(shù)的調(diào)用和執(zhí)行維護存儲結(jié)構(gòu)册着。
函數(shù)調(diào)用時:存儲數(shù)據(jù)
函數(shù)返回時:恢復(fù)數(shù)據(jù)
棧幀:調(diào)用函數(shù)將在棧上創(chuàng)建一個結(jié)構(gòu)化空間,稱為棧幀脾歧。
錨點:函數(shù)被調(diào)用時的棧指針位置甲捏。可用于對函數(shù)的局部數(shù)據(jù)尋址鞭执、返回到調(diào)用者司顿。
call - return的實現(xiàn):
1)存儲參數(shù)
push arg2
push arg1
2)存儲函數(shù)f返回后需要執(zhí)行的指令地址RA(push RA)
call f
3)存儲返回位置
把ebp原來存儲的值壓棧,將esp此時的位置X存入ebp兄纺。
push %ebp
mov %esp %ebp
4)執(zhí)行函數(shù)f的指令
X可幫助函數(shù)f的局部變量尋址大溜。
5)返回
將ebp存儲的值(即返回位置)告訴esp,并回復(fù)ebp原來的數(shù)據(jù)估脆。此外钦奋,通過此時棧頂?shù)臄?shù)據(jù)RA,定位到下一條需要執(zhí)行的指令。
mov %ebp %esp
pop %ebp
retn
6. 緩沖區(qū):
copy-on-write:
資源的復(fù)制只有在需要寫入的時候才進行付材,在此之前朦拖,只是以只讀方式共享。
很多時候厌衔,函數(shù)執(zhí)行中需要局部分配較大的線性內(nèi)存空間璧帝。
增長方向
棧增值方向為從高到低,緩沖區(qū)的增長從低到高葵诈。
要求
緩沖區(qū)應(yīng)該足夠大裸弦,寫入數(shù)據(jù)之前應(yīng)該先檢查是否仍有剩余空間可用。
關(guān)于堆溢出的知識背景
1. 堆的創(chuàng)建和維護:
通過malloc實現(xiàn)
2. 堆的工作原理:
malloc創(chuàng)建的區(qū)域首先是堆的場地(Arena)作喘,進程申請堆空間時理疙,malloc從場地中劃分對應(yīng)大小的區(qū)域供其使用。同一場地內(nèi)可能存在多個堆段泞坦。
注意:
Main Arena沒有heap_info
有多個heap的Thread Arena只有一個malloc_state
場地的數(shù)量限制 - 與cpu內(nèi)核數(shù)量有關(guān):
32位系統(tǒng):#_of_Arena = 2 * #_of_cores + 1
64位系統(tǒng):#_of_Arena = 8 * #_of_cores + 1
堆塊的形態(tài):
N表示此塊是否屬于main arean; M表示此塊是否是mmap()創(chuàng)建的; P表示前塊是否正在使用窖贤。
顯式鏈表結(jié)構(gòu)bin:
bin是記錄free chunk的鏈表數(shù)據(jù)結(jié)構(gòu),在glibc中可分為fastbinsY和bins贰锁。
fastbin主要用于高效的分配和回收比較小的內(nèi)存塊赃梧,采用LIFO形式的單鏈表結(jié)構(gòu)。
頂塊top chunk:
不屬于任何bin豌熄。
當前所有空閑塊(無論哪種bin)全都尺寸不合時授嘀,由頂塊應(yīng)急。
頂塊比請求尺寸大——分割供給使用锣险,剩余部分為新頂塊蹄皱。
頂塊比請求尺寸小——全堆無適合塊,擴展堆/分配新堆芯肤。
二巷折、棧溢出及防護
1. 主要原因:忽略了邊界檢查
-> 開發(fā)者認為被操作對象合法
-> 二進制代碼底層細節(jié)復(fù)雜,容易使人忽略問題的存在
-> 一些重要的遺產(chǎn)代碼在最初的設(shè)計中存在此類缺陷
2. 現(xiàn)有的棧溢出防護技術(shù)
數(shù)據(jù)執(zhí)行保護(W⊕X崖咨,NX-bit):
機制:
對內(nèi)存頁面增加一個標識比特锻拘,使它要么可改寫,要么可執(zhí)行击蹲。
缺陷:
只要不試圖執(zhí)行數(shù)據(jù)區(qū)內(nèi)容署拟,則既不能阻止溢出,又不能發(fā)現(xiàn)溢出际邻。
棧幀上的“金絲雀”:
機制:
棧上設(shè)置檢查點芯丧,檢查點數(shù)值異常,則代表棧溢出發(fā)生世曾。
缺陷:
開銷大缨恒,對遺產(chǎn)代碼不起作用谴咸。
影子棧:
機制:
構(gòu)造一個額外的動態(tài)數(shù)據(jù)區(qū)域,稱為影子站骗露。當call發(fā)生時岭佳,在返回地址入棧的同時,也將其寫入影子堆棧萧锉。每當return發(fā)生時珊随,在彈出并轉(zhuǎn)向返回地址前,將其與影子堆棧的棧頂比較柿隙。
缺陷:
開銷大叶洞,無法保護遺產(chǎn)代碼。
分離的控制/數(shù)據(jù)棧:
機制:
修改操作系統(tǒng)的內(nèi)存布局禀崖,分配兩個楍帽伲空間,分別用于控制參數(shù)和數(shù)據(jù)的存儲波附。
缺陷:
無法保護遺產(chǎn)代碼艺晴,不適用于完全由匯編語言構(gòu)成的函數(shù)。
三掸屡、堆溢出及防護
1. 與棧溢出的區(qū)別
溢出方向等于堆增長方向封寞。首先破壞(虛擬地址意義上的)下一個堆塊的構(gòu)造。
2. linux上的典型堆溢出利用方式
- 攻擊fastbin
- 攻擊unlink
攻擊fastbin:
基于fastbin塊LIFO的特點仅财,我們可以先申請狈究,然后釋放,再申請就可以得到原來地址的塊盏求。
但是這不能滿足我們的需求谦炒,我們需要將堆分配在可控地址。
我們可以通過堆溢出更改已經(jīng)申請塊的fd风喇,使其指向我們可控的地址,并且在可控地址上偽造假的fastbin結(jié)構(gòu)缕探。
釋放魂莫,再申請兩次,第2次就可以得到分配在可控地址上的塊爹耗。(覆蓋fd)
攻擊unlink:
unlink攻擊技術(shù)就是利用”glibc malloc”的內(nèi)存回收機制耙考,將second chunk給unlink掉,并且潭兽,在unlink的過程中使用shellcode地址覆蓋掉free函數(shù)(或其他函數(shù)也行)的GOT表項倦始。這樣當程序后續(xù)調(diào)用free函數(shù)的時候(如上面代碼[5]),就轉(zhuǎn)而執(zhí)行shellcode了山卦。顯然鞋邑,核心就是理解glibc malloc的free機制。
一旦涉及到free內(nèi)存,那么就意味著有新的chunk由allocated狀態(tài)變成了free狀態(tài)枚碗,此時glibc malloc就需要進行合并操作——向前以及(或)向后合并逾一。這里所謂向前向后的概念如下:將previous free chunk合并到當前free chunk,叫做向后合并肮雨;將后面的free chunk合并到當前free chunk遵堵,叫做向前合并。
3. windows堆溢出攻擊的主要形式
- 利用向量化異常處理(VEH)
- 利用系統(tǒng)默認異常處理函數(shù)(UEF)
- Heap spray
- Bitmap Flipping攻擊
- Bitmap XOR攻擊
- Heap Cache攻擊
4. 堆溢出防御
堆依靠系統(tǒng)庫實現(xiàn)其維護怨规,因此陌宿,堆保護 = 系統(tǒng)庫升級。
針對unlink的保護:
Double Free檢測
next size非法檢測
雙鏈表沖突檢測