余云飛, 張躍軍,3, 汪鵬君, 李 剛
1. 寧波大學(xué) 信息科學(xué)與工程學(xué)院, 寧波315211
2. 溫州大學(xué) 電氣與電子工程學(xué)院, 溫州325035
3. 密碼科學(xué)技術(shù)國家重點實驗室, 北京100878
隨著物聯(lián)網(wǎng)、云計算和移動支付等技術(shù)的快速發(fā)展, 嵌入式系統(tǒng)在軍事、汽車、醫(yī)療、通訊等領(lǐng)域得到廣泛應(yīng)用, 尤其是眾多嵌入式系統(tǒng)之間網(wǎng)絡(luò)通訊、協(xié)同處理能力也得到進一步加強. 這同時也給攻擊者找到可趁之機. 攻擊者可以利用軟件漏洞實施控制流攻擊進而對整個系統(tǒng)進行控制. 控制流攻擊是指利用程序漏洞, 通過篡改程序控制流的存儲地址或控制流數(shù)據(jù)等方式, 將程序?qū)虿?zhí)行預(yù)先設(shè)定的惡意代碼, 達到破壞系統(tǒng)或盜取關(guān)鍵信息的目的. 根據(jù)惡意代碼注入與否, 控制流攻擊可分為代碼注入攻擊和代碼復(fù)用攻擊. 代碼注入攻擊指攻擊者利用軟件的某些漏洞將惡意代碼注入到應(yīng)用程序. 堆棧溢出攻擊是代碼注入攻擊的一種典型方式, 堆棧中寫入的數(shù)據(jù)量超過堆棧本身的容量, 溢出的數(shù)據(jù)可以覆蓋合法的數(shù)據(jù), 但由于原始程序并沒有做邊界檢查, 這就為攻擊者實施溢出攻擊埋下隱患. 攻擊者可以利用溢出攻擊覆蓋原始返回地址, 將返回地址篡改為指向預(yù)先注入惡意代碼的地址, 進行控制流劫持. 堆棧溢出攻擊如圖1 所示, 攻擊者用起始地址A 覆蓋堆棧中的返回地址, 進行控制流的劫持. 隨著數(shù)據(jù)執(zhí)行保護(Data Execution Prevention, DEP) 技術(shù)[1]的提出, 代碼注入攻擊被有效地阻止.
圖1 堆棧溢出攻擊Figure 1 Stack overflow attack
代碼復(fù)用攻擊則利用程序本身的代碼片段去組成想要實施的惡意代碼, 研究表明這種方法能夠成功繞過DEP 機制, 進而實施控制流攻擊——面向返回的編程攻擊(Return Oriented Programming, ROP)[2].攻擊者實施ROP 攻擊, 不需要向內(nèi)存中注入惡意代碼, 僅利用程序中大量以ret 結(jié)尾的指令作為配件gadget 即可組成圖靈完備的惡意代碼實施攻擊. 針對控制流攻擊, 許多防御方法被相繼提出, 本文主要考慮與硬件特性相關(guān)的方法. 文獻[3,4] 提出利用控制流完整性(Control Flow Integrity, CFI) 檢測異常控制流, 該方案通過線下靜態(tài)分析獲取目標地址白名單, 每次控制流轉(zhuǎn)移時, 立即詢問該地址是否在白名單中, 一旦出現(xiàn)目標地址不在白名單的間接跳轉(zhuǎn),就會報錯并終止程序, 由此檢測控制流跳轉(zhuǎn)異常, 但要獲取完備的目標地址白名單是很難實現(xiàn)的; 文獻[5]通過研究ROP 對地址信息的依賴性, 在探究隨機化效率的基礎(chǔ)上, 提出一種短序列隨機化的抗攻擊技術(shù), 并對隨機化覆蓋率的特性進行剖析, 解決了如何提高隨機化覆蓋率問題, 但是攻擊者可以利用內(nèi)存泄露方式獲得隨機化后的數(shù)據(jù)進行攻擊; 文獻[6] 提出基于異??刂屏髯R別的漏洞攻擊檢測方法, 能夠準確檢測到漏洞進行攻擊, 并可作為漏洞利用攻擊的實時檢測方案,而由于此方案需要擴展指令集, 可能造成指令集不兼容問題; 文獻[7]針對ROP 攻擊提出采用指令集隨機化的防御策略, 在指令末端數(shù)據(jù)中設(shè)定多寄存器并在數(shù)據(jù)范圍內(nèi)隨機分配寄存器數(shù)據(jù), 達到防御ROP 攻擊的目的, 但由于間接跳轉(zhuǎn)指令的識別, 如無法正確識別目標指令就不能保證隨機化后的正確性; 文獻[8]提出上下文控制流完整性檢查, 利用intel CPU 中的LBR(Last Branch Record, LBR)機制, 每當程序要執(zhí)行重要的系統(tǒng)調(diào)用時對LBR 中保存的先前的跳轉(zhuǎn)指令進行CFI 判斷, 若全部符合, 則繼續(xù)執(zhí)行, 若不符合控制流圖, 跳轉(zhuǎn)則停止執(zhí)行并報錯, 有效地檢測出控制流的非法轉(zhuǎn)移, 但由于檢測粒度不夠細, 攻擊者可通過構(gòu)造棧和選擇函數(shù)實施攻擊; 文獻[9] 提出利用Intel 處理器跟蹤的硬件機制, 結(jié)合虛擬技術(shù)對內(nèi)核模塊進行控制流完整性檢查, 對防御ROP 攻擊具有極強的保護精確性, 兼容性和效率, 但是生成完備的內(nèi)核模塊控制流圖非常困難, 并且由于細粒度的控制流完整性檢查, 將會引入很大的性能開銷; 文獻[10] 提出一種基于異常控制流識別的攻擊檢測方法, 該方法通過構(gòu)建完整的安全執(zhí)行輪廓, 并限定控制流轉(zhuǎn)移的合法目標, 來識別異??刂屏鬓D(zhuǎn)移, 而構(gòu)建完整的安全執(zhí)行輪廓十分困難, 若不能構(gòu)建完整的安全輪廓, 將會導(dǎo)致攻擊誤報問題; 文獻[11] 在分析增強內(nèi)容敏感和字段敏感指針的基礎(chǔ)上, 提出細粒度的控制流完整性檢測方法, 保證操作系統(tǒng)內(nèi)核完整性, 細粒度檢查要求嚴格控制每一個間接轉(zhuǎn)移指令的轉(zhuǎn)移目標, 將會引入過大的性能開銷; 文獻[12] 提出控制流完整性監(jiān)視保護, 它是一種粗粒度控制流完整性檢查方法, 關(guān)鍵思想是以可變大小的塊指令動態(tài)地限制間接分支僅定位程序塊的第一條指令, 而粗粒度CFI 則是將一組類似或相近類型的目標歸到一起進行檢查, 由于檢查粒度不夠細, 攻擊者依然可以利用精心設(shè)計的指令配件繞過防御機制實施攻擊; 文獻[13] 提出一種新的硬件輔助CFI 框架, 該框架使用功能標簽方法和有效標簽的狀態(tài)模型來實施細粒度CFI 策略, 然而細粒度的檢查將會引入過大的開銷; 文獻[14] 提出一種基于加密消息認證碼, 保護控制流元素并通過動態(tài)檢查阻止所有已知的攻擊, 實質(zhì)上此方案也屬于粗粒度CFI 檢查, 攻擊者依然可以利用配件繞過此防御機制; 文獻[15] 提出利用影子棧和片內(nèi)安全存儲區(qū)等硬件實現(xiàn)功能齊全的CFI 指令集架構(gòu), 進而防御控制流攻擊, 而由于此方案需要對指令集修改, 將會導(dǎo)致指令集不兼容等問題.
綜上, 針對以上硬件防御手段或存在開銷大或安全性低, 亦或指令集不兼容等問題[16,17], 本文采用硬件開銷較小的XOR 門加密電路和內(nèi)置安全寄存器組對返回地址加密及存儲. 如此, 既不會帶來過大的開銷, 也不會引入新的指令集.
鑒于現(xiàn)有抗控制流技術(shù)存在的問題, 提出一種基于XOR 門加密的抗控制流攻擊方法, 電路結(jié)構(gòu)框圖如圖2 所示. 攻擊者實施控制流攻擊必須篡改堆棧中的返回地址, 為了防止攻擊者修改堆棧中的返回地址且不帶來過大的硬件開銷, 引入XOR 加密電路對返回地址進行加密處理, 當指令譯碼結(jié)果為程序調(diào)用指令call 時, 返回地址不會被直接壓入到堆棧中, 而是經(jīng)過XOR 加密電路加密. 為了檢測加密后的返回地址是否被攻擊者修改, 需要對加密后的返回地址進行存儲, 因此引入內(nèi)置安全寄存器組(Build-in Security Register Bank, BSRB) 存儲加密后的返回地址. 加密的返回地址被同時壓入堆棧和內(nèi)置安全寄存器組中,當指令譯碼結(jié)果為程序返回指令ret 時, 堆棧和內(nèi)置安全寄存器組中的加密返回地址則要經(jīng)過XOR 解密電路后送入地址比較器, 通過返回地址比較結(jié)果檢測系統(tǒng)是否受到控制流攻擊, 若受到攻擊, 立即觸發(fā)reset 信號翻轉(zhuǎn)為有效電平使系統(tǒng)重新初始化, 停止程序繼續(xù)執(zhí)行.
圖2 抗控制流攻擊結(jié)構(gòu)框圖Figure 2 Diagram of defending control flow attack
為保護返回地址不被篡改, 引入XOR 門加/解密電路對返回地址進行加/解密. 正常情況下, 當系統(tǒng)執(zhí)行程序調(diào)用指令call 時, 下一條指令的地址會被壓入到堆棧中, 當執(zhí)行程序返回指令ret 時, 系統(tǒng)會從堆棧中取出返回地址, 繼續(xù)執(zhí)行下一條指令. 為防止攻擊者利用軟件漏洞去篡改堆棧中的返回地址, 進而實施控制流劫持, 引入XOR 門加密電路. 當執(zhí)行調(diào)用指令call 時, 返回地址A 不會被直接壓入到堆棧中, 而是經(jīng)過XOR 加密電路與密鑰K 異或加密. 密鑰K 則是由偽隨機數(shù)發(fā)生器生成的16 位隨機數(shù)并存儲在專門的密鑰寄存器中, 并經(jīng)過DesignCompiler 綜合, 在TSMC 65 nm CMOS 工藝下平均功耗為0.187 mW, 關(guān)鍵路徑延時為2.0 ns, 產(chǎn)生的隨機數(shù)可以通過NIST 測試. 如圖3(a) 所示, 堆棧中壓入的是經(jīng)過XOR 加密電路加密的返回地址(K ⊕A); 當執(zhí)行程序返回指令ret 時, 堆棧中的返回地址則要經(jīng)過XOR 解密單元, 如圖3(b) 所示, 出棧的返回地址為K ⊕A ⊕K). 攻擊者如果篡改堆棧中加密過的返回地址, 當其從堆棧中取出時, 須經(jīng)過XOR 解密單元, 由于攻擊者篡改的返回地址沒有經(jīng)過XOR 加密單元,攻擊者想要執(zhí)行指令的地址A 將被解密電路導(dǎo)向地址(K ⊕a) 由于K 未知繼而攻擊失敗.
圖3 XOR 門加/解密電路Figure 3 XOR gate encrypt/decrypt circuit
圖4 為提出的內(nèi)置安全寄存器組, 用于存儲加密后的返回地址. 攻擊者實施控制流攻擊的基礎(chǔ)就是在系統(tǒng)執(zhí)行調(diào)用指令call, 返回地址被壓入到堆棧后, 對堆棧中的返回地址通過緩沖區(qū)溢出的方法進行篡改.為了檢測堆棧中加密后的返回地址是否被篡改, 引入內(nèi)置安全寄存器組備份加密返回地址. 內(nèi)置安全寄存器組實質(zhì)上是一個特殊的堆棧, 用于專門存儲加密的返回地址和保護其不被攻擊者覆蓋. 該寄存器組中的加密返回地址只能通過調(diào)用指令call 和程序返回指令ret 寫入和讀取, 而其他指令禁止訪問.
為驗證所提方案的有效性, 使用硬件編程語言verilog 分別在oc_8051 處理器與ARM6 處理器的取指、譯指及執(zhí)行階段加入XOR 加解密電路和內(nèi)置安全寄存器組及地址比較器, 實現(xiàn)具有防御控制流攻擊功能的處理器.
圖5 為本方案在處理器取指、譯指、執(zhí)行階段加入XOR 地址加解密單元和內(nèi)置安全寄存器組及地址比較器架構(gòu)框圖, 檢測處理器是否受到控制流攻擊步驟如下.
步驟1: 指令譯碼結(jié)果為程序調(diào)用指令call 時, 觸發(fā)偽隨機數(shù)發(fā)生器產(chǎn)生密鑰K 存儲到密鑰寄存器中;
步驟2: 將返回地址送入XOR 加密單元進行加密處理;
步驟3: 將加密后的返回地址同時送入壓入堆棧和內(nèi)置安全寄存器組;
步驟4: 指令譯碼結(jié)果為程序返回指令ret 時, 同時彈出堆棧和內(nèi)置安全寄存器組中的加密返回地址,并送入到XOR 解密單元, 將加密的返回地址進行解密處理;
步驟5: 在執(zhí)行階段, 將從堆棧和內(nèi)置安全寄存器組中彈出的解密后返回地址送入到地址比較器;
步驟6: 若地址比較器結(jié)果相同, 則繼續(xù)執(zhí)行程序, 反之則停止執(zhí)行程序.
圖5 抗控制流攻擊處理器的架構(gòu)Figure 5 Architecture of defending control flow attack processor
抗控制流攻擊處理器具體工作流程如圖6 所示. 處理器工作過程分為五個階段: 取指、譯指、執(zhí)行、訪存、寫回. 當處理器處于譯指階段時, 指令譯碼結(jié)果為call 指令時, 即子程序開始調(diào)用. 處理器將觸發(fā)隨機數(shù)發(fā)生器產(chǎn)生密鑰K 存儲到密鑰寄存器并將返回地址送入XOR 加密單元進行加密, 加密過后的返回地址被送入到堆棧和BSRB; 指令譯碼結(jié)果為ret 指令時, 即子程序調(diào)用結(jié)束. 處理器將同時彈出BSRB和堆棧中的加密返回地址并送入到解密單元, 并將解密的返回地址送入地址比較器進行比較. 若比較結(jié)果相同則程序繼續(xù)正常執(zhí)行, 反之則停止執(zhí)行. 若攻擊者篡改堆棧中加密后的返回地址進行劫持控制流, 則篡改后的返回地址出棧后必須強制經(jīng)過解密電路, 由于篡改后的地址未經(jīng)過加密, 最終出棧的返回地址并非攻擊者想要執(zhí)行指令的地址, 控制流攻擊則失敗. 在攻擊者無法獲取密鑰K 時此方案是安全的, 但若攻擊者同時覆蓋堆棧和BSRB 中的返回地址, 由于XOR 解密單元的存在, 攻擊者想要執(zhí)行的指令地址依然會被強制解密, 攻擊依舊失敗, 只是系統(tǒng)不會做出異常處理, 而是繼續(xù)執(zhí)行其它地址處的指令.
圖6 抗控制流攻擊的流程圖Figure 6 Process of defending control flow
為驗證方案的有效性, 進行g(shù)adget 消除與邏輯綜合以及波形仿真等實驗, 實驗環(huán)境包括: Intel Xeon(R) Dual-Core CPU 2.0 GHz、6 G RAM 服務(wù)器, 涉及的工具軟件包括: ROPGadget-master5.4、Pin2.14、NClaunch 以及DesignCompiler.
攻擊者若要實施控制流劫持進行ROP 攻擊, 必須有大量可用的以ret 為結(jié)尾的指令片段作為配件gadget 組成惡意代碼, 因此減少可被利用的gadget 數(shù)目就能降低攻擊者劫持控制流的可能性. 通過加解密電路, 使堆棧中的攻擊者篡改后的地址經(jīng)過解密指向不是以ret 為結(jié)尾的指令片段處, 進而減少可被攻擊者使用的gadget. 但是由于提出的防御機制是在調(diào)用指令call 和程序返回指令ret 控制下加解密返回地址, 若加密后的gadget 地址恰好是間接跳轉(zhuǎn)指令jmp 或間接調(diào)用指令call 的目標地址, 則此gadget依然可被攻擊者使用, 進而實施攻擊. 為了得到gadget 消除率, 首先使用ROPGadget-master5.4 工具掃描測試程序, 獲得測試程序中的gadget 的總數(shù), 然后用Pin 提取測試程序的間接跳轉(zhuǎn)指令jmp 及間接調(diào)用指令call 的目的地址, 最后在二進制代碼翻譯工具Pin 框架下實現(xiàn)此方法, 并提取此方案加密后的gadget 地址. 若一個gadget 地址加密后恰好是間接跳轉(zhuǎn)指令jmp 或間接調(diào)用指令call 的目的地址, 則此gadget 可以被攻擊者利用, 統(tǒng)計此gadget 數(shù)目, 得到gadget 消除率. 基準測試程序在本方案中的gadget消除率, 如表1 所示. 其中5 個程序?qū)儆赗IPE 測試程序, RIPE 里面包含了850 個緩沖區(qū)溢出攻擊程序.實驗結(jié)果顯示gadget 平均消除率為99.52%, 結(jié)果表明此方法可以有效防御控制流攻擊.
表1 Gadget 消除率Table 1 Gadget elimination rate
表2 與表3 是通過修改oc_8051 處理器和ARM6 處理器的源代碼加入XOR 加解密電路與內(nèi)置安全寄存器組以及地址比較器后的硬件開銷, 使用DesignCompiler 綜合獲得面積、功耗和延時. 結(jié)果顯示在TSMC 65nm CMOS 工藝下oc_8051 處理器面積和功耗分別增加5.10% 和6.06%, ARM6 處理器面積和功耗分別增加5.25% 和6.3%, 與文獻[18] 相比, 此方案硬件開銷減小了22.95%, 大大減小了硬件開銷.
表2 oc_8051 處理器硬件開銷情況Table 2 Overhead of oc_8051 processor
表3 ARM6 處理器硬件開銷情況Table 3 Overhead of ARM6 processor
圖7 為當堆棧中的返回地址與內(nèi)置安全寄存器組中的返回地址不同時, 使用NClaunch 獲得的波形圖.
圖7 仿真波形Figure 7 Simulation waveform
CLK 為時鐘信號, INT 和INT_V 分別為中斷信號和中斷向量, RES 和RETI 分別為比較地址信號和中斷返回信號, ROM 為指令存儲地址. 當ret 指令執(zhí)行時RES 為0, 返回地址比較結(jié)果不相同, 證明堆棧中返回地址遭到篡改.
本文首先利用XOR 門加密電路對返回地址進行加密, 然后將加密后的返回地址同時壓入內(nèi)置安全寄存器和堆棧, 最后將解密后的返回地址送入地址比較器, 根據(jù)返回地址比較結(jié)果實現(xiàn)檢測和防御控制流攻擊的目的. 實驗結(jié)果表明本方案在TSMC 65 nm CMOS 工藝下gadget 平均消除率高達99.52%, 面積和功耗最大分別僅增加了5.25% 和6.3%. 應(yīng)該說明的是該方法僅局限于防御ROP 型與代碼注入型控制流攻擊, 無法防御面向跳轉(zhuǎn)的編程攻擊型(Jump Oriented Programming, JOP) 控制流攻擊和拒絕服務(wù)攻擊.