前身——return-to-libc
目的:
繞過DEP
主要思想:
代碼重用攻擊蕉扮。利用進程空間中已經(jīng)存在的代碼阎姥,通過注入的異常數(shù)據(jù)控制其為攻擊者服務(wù)。
新的利用點——復雜指令集CISC
CISC的問題:
代碼中的一個字節(jié)的含義取決于上下文养涮,原則上吩案,任何一個字節(jié)都可能是一條指令的起始。
思想:
通過劫持控制流媒惕,攻擊者可以令CPU按照其意愿重新解讀已經(jīng)存在的代碼系吩。
需求:
使用非常規(guī)的方式將短小指令片段串聯(lián)成完整的代碼流。
Galileo算法可為返回導向編程搜索可用的指令資源妒蔚。
升級版——精簡指令集RISC
對SPARC構(gòu)造返回導向編程面臨的問題:
無法利用意外的指令序列穿挨;X86下返回導向編程gadget的所有構(gòu)造特點在RISC中都不存在月弛。
新思路:
將函數(shù)的后綴作為gadget使用(利用結(jié)尾的ret-restore指令序列);利用結(jié)構(gòu)化數(shù)據(jù)流使得gadget與SPARC的函數(shù)調(diào)用慣例相吻合科盛;構(gòu)造內(nèi)存-內(nèi)存gadget(寄存器僅在gadget內(nèi)部使用)帽衙。
新防御——Smashing the gadgets:
核心思路:
阻止x86代碼中出現(xiàn)以外的gadget。
手段一:抹掉0xC3字節(jié)(ret)
手段二:指令重新排序
手段三:寄存器壓棧順序隨機化
手段四:寄存器重新分配
顛覆版——ROP without return
核心:
update-load-branch指令序列“pop x; jmp *x”
蹦床trampoline
函數(shù)調(diào)用步驟:
在esi中載入call-jmp序列的地址
在ebp中載入leave-jmp序列的地址
在eax中載入n+偏移量
將call-jmp序列的地址存儲至地址n
改寫esi贞绵,使其存儲“返回地址”
esi值寫入result位置后厉萝,再讀出至edi
交換使返回值存入ebp,leave指令換入edi
在esi中載入pop-jmp序列的地址
在ecx中載入函數(shù)入口地址
在eax中載入地址n
交換esp和eax榨崩,棧指針指向n(函數(shù)地址)
edi處的leave指令將使函數(shù)“返回”
防御新思路——從結(jié)構(gòu)上阻止程序控制流被劫持:
- 程序控制流完整性保護(CFI)
- 實用粗粒度CFI
Springboard段--使得間接控制轉(zhuǎn)移可以通過位校驗進行檢查谴垫,Springboard段內(nèi)地址的第27位總是為0,且僅有Springboard段滿足該條件母蛛。間接控制轉(zhuǎn)移只能以Springboard段內(nèi)的適當存根作為目標翩剪。
缺陷:
需要改寫程序的二進制代碼。很難識別出程序中所有合法控制轉(zhuǎn)移目標彩郊,對二進制代碼的修改困難且易錯前弯,兼容性問題在一定程度上依然存在。 - 基于動態(tài)優(yōu)化的CFI
在程序執(zhí)行過程中加以監(jiān)視和約束秫逝。
缺陷:
效率太低恕出。 - 利用硬件特性和虛擬化技術(shù)的CFI
利用虛擬化技術(shù)。
內(nèi)核模式下作為操作系統(tǒng)的一部分违帆,性能開銷低浙巫;提供了動態(tài)優(yōu)化工具可能提供的CFI優(yōu)勢。
監(jiān)視目標:執(zhí)行流由足夠長的gadget序列組成前方。
完整性檢查的觸發(fā):
設(shè)置滑動窗口,所有窗口外內(nèi)存均設(shè)為不可執(zhí)行廉油』菹眨控制轉(zhuǎn)移指向窗口外時,將觸發(fā)異常并陷入內(nèi)核抒线,引起完整性檢查班巩;敏感系統(tǒng)調(diào)用也會引起完整性檢查。
返回導向編程的基本流程:
始于對程序控制流的篡改(控制流異常)
各gadget由ret指令或pop-jump組合代替eip加以鏈接(大量控制流異常)
原始棧結(jié)構(gòu)遭到破壞嘶炭,ROP過程中棧指針單項移動(棧的行為異常)
有時抱慌,棧指針可能被篡改并指向不屬于棧區(qū)的內(nèi)存(棧的行為異常)
CFI基本思想:
通過預設(shè)的運行時校驗,確保程序執(zhí)行與預先定義的控制流圖嚴格吻合眨猎;
通過對二進制碼的靜態(tài)分析來獲取CFI所需保證的控制流圖抑进;
借由靜態(tài)的二進制代碼改寫為程序添加運行時的自我校驗。
CFI的基本安全性假設(shè):
控制轉(zhuǎn)移目標的標示符(ID)具有唯一性睡陪;
程序代碼不可寫寺渗;
程序數(shù)據(jù)不可執(zhí)行匿情。
CFI的搭建:
內(nèi)存訪問控制 SMAC
通過與運算,確毙攀猓控制轉(zhuǎn)移目標的最高位字節(jié)內(nèi)容位40h炬称;
使得間接控制轉(zhuǎn)移總是指向合法的代碼區(qū)段;
由此在一定程度上實現(xiàn)軟件故障隔離(SFI)涡拘。受保護的影子棧
專門劃定內(nèi)存區(qū)域用于檢查ret指令是否響應(yīng)了正確的call指令玲躯;
為影子棧預設(shè)地址前綴,結(jié)合SMAC鳄乏,可確保只有CFI的校驗指令可以修改該區(qū)域跷车。
CFI的弱點:
即使在靜態(tài)分析中,間接控制轉(zhuǎn)移的合法跳轉(zhuǎn)目標也不唯一汞窗,不是排他的姓赤;
受到性能的制約,粗粒度化的CFI對控制流的約束更加松散仲吏。
改進型ROP——針對CFI
- 利用以函數(shù)入口和函數(shù)調(diào)用點為起始的gadget
- 圖靈完全的改進型gadget集對抗現(xiàn)存最嚴格的CFI
改進型gadget的類型(主要來自kernel32.dll):
具有call指令前綴的gadget(主要)不铆;
call-ret配對的gadget組合;
“長nop"gadget裹唆。
繞過CFI不會導致返回導向編程的功能性有所缺損誓斥。
ROP變種“數(shù)據(jù)導向編程”——一切為了繞過CFI
特點:
通過污染數(shù)據(jù)(特別是指針)改變被重用代碼的實際語義。借助循環(huán)不斷注入新的攻擊載荷许帐,使得被重用代碼的實際執(zhí)行效果隨之改變劳坑。
數(shù)據(jù)導向編程所重用的代碼資源主要來自串操作。
交互式攻擊 - 允許攻擊者在每輪循環(huán)中輸入不同的載荷以激活不同的gadget成畦。
非交互式攻擊 - 攻擊者必須一次性輸入整個攻擊載荷距芬,需要額外的指令元素以支持虛擬的跳轉(zhuǎn)操作。
新防御——地址空間隨機化ASLR
思想:
使gadget的位置變得無法確定循帐。
粗粒度ASLR:
mmap offset框仔、stack offset、brk offset隨機化拄养。
粗粒度ASLR的改進:偏移量+內(nèi)存區(qū)段的位置置換离斩。
細粒度ASLR:
區(qū)段間----->區(qū)段內(nèi)
改變代碼文本的具體內(nèi)容
實施
程序在加載時自我隨機化;
通過虛擬機進行動態(tài)隨機化瘪匿;
操作系統(tǒng)的隨機化跛梗。
ASLR的無效化:
場景1:攻擊者無法披露目標程序的內(nèi)存空間;
場景2:攻擊者可以實施內(nèi)存空間披露棋弥,但只能獲得一個代碼指針核偿。
限制:對于任何ASLR,程序在執(zhí)行時不在改變其內(nèi)存空間結(jié)構(gòu)顽染。
“頁面收割”最終暴露進程中的全部代碼宪祥、API接口等可利用資源聂薪。
Just-In-Time代碼重用