張雨昕, 芮志清, 李威威, 張 畫,4, 羅天悅, 吳敬征
1(中國科學(xué)院 軟件研究所 智能軟件研究中心, 北京 100190)
2(伊利諾伊大學(xué)香檳分校 The Grainger College of Engineering, Urbana-Champaign 61820)
3(中國科學(xué)院 軟件研究所 PLCT實(shí)驗(yàn)室, 北京 100190)
4(北京航空航天大學(xué) 高等理工學(xué)院, 北京 100191)
緩沖區(qū)溢出攻擊是計(jì)算機(jī)系統(tǒng)安全領(lǐng)域的重要攻擊手段之一.攻擊者通過對未做邊界檢查的緩沖區(qū)寫入惡意數(shù)據(jù), 達(dá)到控制程序甚至獲取整個(gè)系統(tǒng)操作特權(quán)的目的.然而因?yàn)橐訡語言為代表的被廣泛使用的編程語言并不具有強(qiáng)制進(jìn)行緩沖區(qū)邊界檢查的功能,所以眾多使用此類語言的系統(tǒng)中存在著諸多溢出漏洞易被攻擊者利用.如今, 每年此類漏洞被檢測到的數(shù)量在各類關(guān)于計(jì)算機(jī)安全的漏洞依舊中占據(jù)前列[1].雖然隨著技術(shù)的進(jìn)步與發(fā)展, 操作系統(tǒng)、應(yīng)用軟件和硬件層面都發(fā)展出許多預(yù)防此類攻擊的安全機(jī)制, 例如內(nèi)存地址空間隨機(jī)化(ASLR)[2], StackGuard[3], 數(shù)據(jù)不可執(zhí)行(DEP)[4]等.與此同時(shí), 攻擊的方式也隨之復(fù)雜, 發(fā)展出各類變種, 例如Return-to-libc Attack (Ret2libc)和Sigreturn Oriented Programming (SOP)等[5,6], 以此繞過各類安全機(jī)制.
指針加密是一種通過保護(hù)指令地址的溢出攻擊預(yù)防機(jī)制.溢出攻擊的主要原理是注入惡意數(shù)據(jù), 修改指令寄存器指向的地址使控制流跳轉(zhuǎn)到攻擊者構(gòu)造的代碼中, 最終劫持程序或者獲取更高的系統(tǒng)權(quán)限.而指針加密的主要機(jī)制是將程序返回地址和函數(shù)指針等重要數(shù)據(jù)加密后再存儲在內(nèi)存中, 而在需要將此類數(shù)據(jù)加載到指令寄存器中時(shí)再解密使指令寄存器指向正確的目的地址.通過此種方法, 指令的地址被加密隱藏, 即使攻擊者通過各種方式改變了指令寄存器中的值, 也無法預(yù)測指令指針實(shí)際指向的位置, 更無法使指針指向惡意構(gòu)造的代碼處.因此這一安全預(yù)防機(jī)制可以有效阻止各類溢出攻擊.
PointGuard是一種通過軟件手段實(shí)現(xiàn)指針加密機(jī)制的技術(shù)[7], 此機(jī)制將密鑰存儲在內(nèi)存中某一區(qū)域, 在加解密時(shí)取出密鑰值將其與指針的值做異或運(yùn)算.但是, 此方式在加解密時(shí)均需要訪問內(nèi)存, 會(huì)增加時(shí)間開銷以及內(nèi)存占用的空間開銷.而且對于能夠讀取數(shù)據(jù)的攻擊, 易泄露加密鍵值從而導(dǎo)致預(yù)防機(jī)制失效.針對這些問題, 本文提出基于RISC-V自定義指令設(shè)計(jì)的指針加密協(xié)處理器PEC-V (Pointer Enryption Coprocessor on RISC-V), 通過硬件手段實(shí)現(xiàn)這一機(jī)制.
RISC-V作為一個(gè)新型開源指令集架構(gòu), 同樣易受到緩沖區(qū)溢出攻擊.Jaloyan等在論文中闡明了此類攻擊在RISC-V架構(gòu)上的可行性, 并利用內(nèi)核中的代碼片段成功實(shí)現(xiàn)了ROP (Return Oriented Programming)攻擊并繞過多種安全防御機(jī)制[5].因此, 針對RISC-V的安全性研究十分必要.
RISC-V具有的顯著特性之一便是開放的可擴(kuò)展性, RocketChip是一款基于RISC-V的SoC (Systemon-a-Chip)生成器, 它基于RISC-V預(yù)留的自定義指令設(shè)計(jì)的RoCC (Rocket Custom Coprocessor)接口可以方便的擴(kuò)展協(xié)處理器.而協(xié)處理器PEC-V的內(nèi)部設(shè)計(jì)主要通過使用PUF (Physical Unclonable Function)[8]加解密數(shù)據(jù).PUF對不同激勵(lì)輸入做出唯一且隨機(jī)的響應(yīng), 但對于同樣的輸入總是輸出固定值.因此本文將被加密數(shù)據(jù)地址作為激勵(lì)輸入, 將PUF響應(yīng)作為密鑰加密數(shù)據(jù)以此減少訪問內(nèi)存的時(shí)間開銷, 減少內(nèi)存占用, 同時(shí)保障了安全性.
此節(jié)主要介紹針對溢出攻擊的其他安全預(yù)防機(jī)制和這些機(jī)制存在的問題, 以及介紹RISC-V自定義指令和RoCC接口的細(xì)節(jié)和選擇這一架構(gòu)的原因.
目前, 針對緩沖區(qū)溢出攻擊的研究十分廣泛, 研究者們提出了許多預(yù)防機(jī)制.首先, ASLR[2]和DEP[4]便是兩種已經(jīng)被廣泛使用的預(yù)防機(jī)制.其中, ASLR機(jī)制在加載程序地址空間時(shí), 通過在棧、堆、代碼區(qū)和動(dòng)態(tài)鏈接庫等內(nèi)存段的起始地址前加入一段隨機(jī)偏移量達(dá)到地址隨機(jī)化的目的.此種方法可以加大攻擊者定位漏洞跳轉(zhuǎn)到目的地址的難度.而DEP機(jī)制是在內(nèi)存頁添加額外標(biāo)識字節(jié)表示此頁是否可執(zhí)行, 通過操作系統(tǒng)的控制區(qū)分內(nèi)存為可執(zhí)行段和不可執(zhí)行段, 因此寫在緩沖區(qū)中被攻擊者惡意注入的代碼將不再可以被執(zhí)行, 從而阻止攻擊.然而面對更加具有針對性和復(fù)雜的攻擊手段, 這兩種預(yù)防機(jī)制變得十分有限.對于ASLR機(jī)制, 攻擊者通過在注入代碼中添加nop指令的方式使程序控制流最終仍能被攻擊者掌握.并且在32位的系統(tǒng)架構(gòu)上, ASLR存在內(nèi)存地址空間小的時(shí)候隨機(jī)化不足的問題[9].而對于DEP機(jī)制, 攻擊者可以利用動(dòng)態(tài)鏈接庫或者程序中已經(jīng)存在的代碼片段構(gòu)造棧中的返回地址和數(shù)據(jù)實(shí)現(xiàn)Ret2libc攻擊[10].
而后Stack Canary[3]作為一種更加有效的預(yù)防機(jī)制被提出, 并被實(shí)際應(yīng)用.Stack Canary可以通過將NULL值插在緩沖區(qū)的末尾, 以此識別緩沖區(qū)中數(shù)據(jù)是否越界, 當(dāng)發(fā)現(xiàn)NULL值被覆蓋時(shí)說明緩沖區(qū)溢出,則立刻終止程序.然而如果使用NULL值插在緩沖區(qū)末尾, 會(huì)有一些系統(tǒng)函數(shù)允許寫入NULL值導(dǎo)致溢出攻擊依舊可行.此問題的一個(gè)解決方式是使用隨機(jī)數(shù)代替NULL值.然而如果使用隨機(jī)數(shù), 那么此數(shù)值需要對攻擊者保密, 如果使用軟件實(shí)現(xiàn)此機(jī)制, 隨機(jī)數(shù)的種子值需要存儲在TCB中, 而這將成為一個(gè)易受攻擊的薄弱環(huán)節(jié).De等[11]在論文中使用PUF在RISC-V架構(gòu)上設(shè)計(jì)了一個(gè)Canary Engine.然而此種硬件實(shí)現(xiàn)方式依舊不能避免一些攻擊.Stack Canary機(jī)制只能檢測到改變了緩沖區(qū)和返回地址之間所有數(shù)據(jù)的攻擊, 對于通過指針直接覆蓋返回值的攻擊, Stack Canary無法避免, 例如printf格式化字符串溢出等.此外, 對于堆上的溢出攻擊, Stack Canary同樣無法阻止[12].
近年來另一種防御機(jī)制控制流完整性(CFI)[13]逐漸成為研究的主流, 針對此方面的研究主要分為粗粒度控制流完整性[14]和細(xì)粒度控制流完整性[15].這些機(jī)制在編譯階段構(gòu)建程序的控制流圖并通過某種方案在程序執(zhí)行時(shí)使其只能按照流圖中的邊跳轉(zhuǎn).然而這些方案大部分并未投入實(shí)際使用, 它們依舊各自存在一定的問題.由于靜態(tài)分析并不能完全確定程序的控制流圖, 例如函數(shù)指針指向的函數(shù)無法在編譯階段確定, 因此粗粒度的控制流完整性方案無法精準(zhǔn)定位程序跳轉(zhuǎn)的位置, 這導(dǎo)致此機(jī)制依舊存在漏洞可被攻擊者利用,而細(xì)粒度方案則會(huì)增添大量空間和時(shí)間的開銷[16,17].
類似于CFI機(jī)制, 指針加密也通過保護(hù)程序控制流達(dá)到阻止攻擊的目的.Cowan等[7]提出的PointGuard技術(shù)便是通過加解密指針的方式阻止溢出攻擊.此技術(shù)為了保障加密密鑰的隨機(jī)性, 每當(dāng)開啟一個(gè)新進(jìn)程時(shí)都需要重置此密鑰(REF), 而此值將被存在進(jìn)程的TCB中.因此TCB可能會(huì)成為整個(gè)系統(tǒng)中易受攻擊的環(huán)節(jié), 對于有可能存在數(shù)據(jù)泄露或者存在可以修改TCB值的漏洞的程序, 攻擊者可以破解或繞過此機(jī)制.此外由于每一次加解密返回地址或者其他可改變指令寄存器值的數(shù)據(jù)時(shí), PointGuard都需要從內(nèi)存中取出密鑰的值, 將其與返回地址或者函數(shù)指針執(zhí)行異或運(yùn)算[18].從以上描述中可以看出在存儲和使用此類數(shù)據(jù)時(shí), Point-Guard都需要額外增添1條訪存指令, 這將影響到程序的運(yùn)行效率.綜上, 本文受Canary Engine[11]的啟發(fā), 提出基于RISC-V自定義指令設(shè)計(jì)的指針加密協(xié)處理器PEC-V, 通過硬件手段實(shí)現(xiàn)這一機(jī)制, 可在增強(qiáng)安全性的同時(shí)有效解決運(yùn)行效率低的問題.
RISC-V預(yù)留了眾多未被定義的編碼空間[19], 其中,為了便于非標(biāo)準(zhǔn)化的擴(kuò)展, RISC-V預(yù)留了4種自定義指令custom0/1/2/3, 使用者可以將這4種指令擴(kuò)展成為協(xié)處理器的控制指令.RocketChip是一個(gè)開源的RISC-V的SoC生成器.RocketChip的代碼實(shí)現(xiàn)了RoCC接口, 此接口支持custom0/1/2/3指令, 可用于連接用戶自定義的協(xié)處理器[20].
ROCC接口支持的custom指令的格式和字段如圖1所示, 其中rd字段為目的寄存器, rs1和rs2為源寄存器, xs1和xs2表示協(xié)處理器是否讀取源寄存器中的值, xd表示是否寫回目的寄存器, opcode為custom指令的操作碼, funct7的值可由用戶自行擴(kuò)展以控制協(xié)處理器完成不同操作.本文使用custom0指令, 編碼funct7字段使custom0擴(kuò)展成為4條不同的協(xié)處理器控制指令.
圖1 自定義指令格式
RoCC接口的架構(gòu)[21]如圖2所示, 其中cmd是散開的接口, 包括兩個(gè)源寄存器的值和輸入指令, 主處理器通過cmd將命令和數(shù)據(jù)傳入?yún)f(xié)處理器中; resp將協(xié)處理器中的值傳遞回cmd中rd字段指明的目的寄存器中; mem.req和mem.resp分別用于協(xié)處理器發(fā)送內(nèi)存讀寫請求和主處理器返回請求結(jié)果; busy表示協(xié)處理器是否能繼續(xù)接收指令, busy值為真時(shí)表明協(xié)處理器處于堵塞狀態(tài).
圖2 RoCC接口架構(gòu)細(xì)節(jié)
從上文介紹中可以看出, RISC-V指令集可擴(kuò)展的特性以及RocketChip已經(jīng)實(shí)現(xiàn)的RoCC接口可以允許本研究方便地接入自定義的協(xié)處理器, 實(shí)現(xiàn)指針加密的機(jī)制.因此本文選擇使用此指令架構(gòu)和接口設(shè)計(jì)和運(yùn)行試驗(yàn).
本文設(shè)計(jì)的用于指針加密的協(xié)處理器內(nèi)部構(gòu)造如圖3所示.其中, PUF是一種硬件結(jié)構(gòu), 其利用硬件某些方面不可預(yù)測的隨機(jī)性, 對某一輸入可產(chǎn)生固定的隨機(jī)響應(yīng).一個(gè)輸入和對應(yīng)的響應(yīng)被定義為一個(gè)Challenge-Response-Pair (CRP), PUF依據(jù)CRPs數(shù)量的多少被分為強(qiáng)PUF和弱PUF, 其中, 強(qiáng)PUF的CRPs數(shù)量可以達(dá)到指數(shù)級[8], 足以滿足指針加密的需要.同時(shí)PUF成本低, 面積小, 耗能低, 且能一定程度上預(yù)防常見的對loT的側(cè)信道攻擊[22].本文中使用的PUF為SRAM-PUF.圖中, 每當(dāng)rs1傳入輸入時(shí), PUF產(chǎn)生唯一對應(yīng)的隨機(jī)響應(yīng)并傳到異或門中.
圖3 PEC-V的電路邏輯圖
TRNG是真隨機(jī)數(shù)發(fā)生器, 它利用機(jī)器產(chǎn)生的噪聲例如熱力學(xué)噪聲、光電效應(yīng)和量子現(xiàn)象等產(chǎn)生真正的隨機(jī)數(shù).圖中的TRNG在產(chǎn)生隨機(jī)數(shù)后將其傳入secret register中保存.
本文對RISC-V自定義指令custom0的funct7字段進(jìn)行編碼, 在custom0的基礎(chǔ)上擴(kuò)展了4條協(xié)處理器控制指令.協(xié)處理器中的譯碼器通過funct7字段的不同識別不同的指令.4條指令如表1所示.
表1 增添的自定義指令
指令1無輸入和輸出, 它的作用是命令協(xié)處理器中的TRNG產(chǎn)生1個(gè)真隨機(jī)數(shù)并將值保存到secret register中.每當(dāng)建立1個(gè)新進(jìn)程的時(shí)候, 操作系統(tǒng)都會(huì)發(fā)送指令1到協(xié)處理器, 這樣每一個(gè)進(jìn)程初始化后都會(huì)獲得一個(gè)真隨機(jī)數(shù)值.
指令2的作用是將協(xié)處理器secret register中存儲的值取出存入rd字段指定的寄存器中.每當(dāng)CPU進(jìn)行上下文切換將正在運(yùn)行的進(jìn)程切換出去的時(shí)候, 操作系統(tǒng)負(fù)責(zé)發(fā)送指令2到協(xié)處理器中取出此進(jìn)程的隨機(jī)數(shù)值并存入其PCB中.
指令3的作用是將rs1字段中指定的寄存器中的值傳入?yún)f(xié)處理器的secret register中, 當(dāng)CPU將某一進(jìn)程切換進(jìn)入的時(shí)候, 操作系統(tǒng)負(fù)責(zé)將PCB中存儲的隨機(jī)數(shù)值裝載到常寄存器中并且發(fā)送指令3到協(xié)處理器,協(xié)處理器再將隨機(jī)值存入secret register中.
指令4是唯一由用戶進(jìn)程使用的指令, 其作用是將rs1中的值作為輸入傳入PUF中, PUF產(chǎn)生的響應(yīng)與secret register中的值進(jìn)行異或后再與rs2中的值進(jìn)行異或, 最后傳入rd中.對于進(jìn)程中的返回地址, 函數(shù)指針等需要加密的數(shù)據(jù), 進(jìn)程負(fù)責(zé)將需要加密的數(shù)據(jù)以及數(shù)據(jù)的存儲地址分別傳入rs1和rs2中并且發(fā)送指令4給協(xié)處理器, 等到協(xié)處理器返回值存入rd, 進(jìn)程再將加密后的數(shù)據(jù)存入內(nèi)存.而當(dāng)進(jìn)程需要使用此加密數(shù)據(jù)時(shí), 同樣將數(shù)據(jù)和地址存入rs1和rs2中, 發(fā)送指令4到協(xié)處理器, 余下過程與加密相同, 最后rd寄存器中即為解密后的數(shù)據(jù).
通過上述的機(jī)制, 對于每一個(gè)進(jìn)程都有唯一的真隨機(jī)值, 這樣不同的進(jìn)程中即使是相同地址的數(shù)據(jù), 加密后的密文將不會(huì)相同, 而對于同一進(jìn)程, 在同一虛擬地址空間的數(shù)據(jù), 由于地址不同, 地址作為PUF的輸入得到的固定的隨機(jī)響應(yīng)也不相同, 所以PUF起到了在同一虛擬內(nèi)存地址空間中隨機(jī)化的目的.綜上, 此設(shè)計(jì)指針加密的鍵值的隨機(jī)性更高, 所以此機(jī)制的安全性具有足夠的保障.
在RISC-V指令集增加自定義指令后, 為達(dá)到指針加密的目標(biāo), 還需在程序中插入自定義匯編指令.本文首先將程序編譯為匯編程序, 接著使用程序掃描編譯后的匯編指令, 識別以下4處需要對指令做出修改的地方, 分別為: 函數(shù)指針賦值前, 函數(shù)指針解引用前, 被調(diào)用過程保存返回地址前和被調(diào)用過程返回之前.之后自動(dòng)在此些位置插入計(jì)算地址的指令和指令4進(jìn)行加解密, 修改后的匯編指令再轉(zhuǎn)換為二進(jìn)制文件執(zhí)行.除了此插入方法之外, 還可通過使用Clang/LLVM編譯器實(shí)現(xiàn)插入指令方式的方案.首先將程序編譯為LLVM的中間代碼, 增加pass插入加解密的指令, 最后轉(zhuǎn)換為可執(zhí)行文件.相對于本文的方法, 修改編譯器的方案更為完善, 但為快速驗(yàn)證PEC-V的安全性, 本文未采取復(fù)雜的修改編譯器的方案.
對于程序需要做的具體的改變本文通過圖4中簡單的示例程序進(jìn)行說明.
圖4(a)中的程序是使用函數(shù)指針的一個(gè)簡單示例, 圖4(b)中是針對返回地址加密的簡單示例.首先將程序編譯成中間指令, 掃描定位到程序賦值和使用函數(shù)指針的位置以及調(diào)用過程時(shí)返回地址壓棧以及出棧的位置, 接下來在這些位置插入需要的匯編指令進(jìn)行加密和解密操作.圖中黑色方框中的匯編指令即為后期添加的加密和解密操作, custom_rd_rs1_r2即為新增的指令4.
圖4 對函數(shù)指針和返回地址的處理
對于函數(shù)指針, 在地址存入指針之前, 先將指針的地址通過指令addi a4,s0, -24放入常用寄存器a4中,a5中本身存著函數(shù)指針的值, 接著a4、a5作為指令4中的rs1、rs2傳入?yún)f(xié)處理器中, 協(xié)處理器進(jìn)行加密后的返回值返回到a5, 接著a5中加密后的值被存入指針中.而當(dāng)程序需要使用函數(shù)指針時(shí), 同樣將指針的值和指針的地址傳入?yún)f(xié)處理器進(jìn)行解密.
而針對返回地址,ra寄存器中存儲的是返回地址,圖中jalra, offset指令執(zhí)行的過程是:
ra = pc + 2, pc = pc + offset;
所以, 被調(diào)用函數(shù)保存返回地址之前, 通過add a4,s0, -56獲得返回地址存在棧上的位置, 將ra和a4中的值都傳入?yún)f(xié)處理器獲得加密的地址.當(dāng)被調(diào)用函數(shù)返回時(shí), 在返回地址出棧后, 插入同樣指令進(jìn)行解密.
從以上的例子中可以看出此機(jī)制的設(shè)計(jì)不會(huì)增加額外的內(nèi)存訪問, 因此減少了對程序運(yùn)行效率的影響.而從安全方面來看, 對于一個(gè)程序p1中一個(gè)需要加密的數(shù)據(jù)d1, 它的密文是同時(shí)和TRNG產(chǎn)生的真隨機(jī)數(shù)rp1和PUF對其地址a1產(chǎn)生的響應(yīng)sa1異或的結(jié)果, 即密文m1=d1⊕rp1⊕sa1.所以一個(gè)程序中的某個(gè)需要加密的數(shù)據(jù)的鍵值將由rp1和sa1共同決定, 這在PointGuard的基礎(chǔ)上更增添了安全性.而當(dāng)攻擊者試圖修改地址執(zhí)行惡意代碼時(shí), 如果通過窮舉的方式, 對于64位系統(tǒng)將有264種可能的加密鍵值.當(dāng)遭受溢出攻擊, 程序指令寄存器的值被修改后, 雖然程序不會(huì)識別到值已經(jīng)被改變, 但是解密后的地址會(huì)跳轉(zhuǎn)到任意位置并造成程序崩潰, 阻止了攻擊者試圖控制程序的意圖.
根據(jù)以上的原理介紹可以看出, 此機(jī)制主要防御的攻擊模式是, 利用緩沖區(qū)溢出改變指令寄存器指向的代碼, 跳轉(zhuǎn)注入代碼或者庫中以ret指令結(jié)尾的gadgets, 最終實(shí)現(xiàn)攻擊者想要的操作.此機(jī)制實(shí)現(xiàn)安全性的前提是攻擊者無法訪問只有特權(quán)級進(jìn)程才能控制的PCB區(qū)域, 無法獲取PCB中存儲的進(jìn)程唯一的真隨機(jī)鍵值.在此前提下即使攻擊者可在同一機(jī)器上運(yùn)行自己的程序, 讀取加密鍵值, 也無法從此數(shù)據(jù)中獲取任何其他進(jìn)程加密鍵值的信息, 而對于攻擊者試圖攻擊的進(jìn)程, 即使有幾處內(nèi)存位置的加密鍵值被讀溢出漏洞所暴露, 其他位置的加密鍵值仍然無法被攻擊者獲取.由于一般攻擊都需要多處的代碼段鏈接在一起執(zhí)行, 因此, 攻擊者能成功的概率將大大降低.而如果通過暴力破解的方式, 需要的次數(shù)取決于PUF產(chǎn)生響應(yīng)的字節(jié)數(shù), 對于可產(chǎn)生32位響應(yīng)的PUF, 破解需要的時(shí)間將是指數(shù)級的.
本研究使用Chisel電路語言[23]實(shí)現(xiàn)了PEC-V的邏輯電路, 接入RocketChip的RoCC接口, 接著使用RocketChip已實(shí)現(xiàn)的Cycle-accurate C++ Emulator進(jìn)行實(shí)驗(yàn).實(shí)驗(yàn)的主要目的有二:
(1) 驗(yàn)證此機(jī)制的安全性.
(2) 測試此機(jī)制對程序運(yùn)行效率的影響.
測試程序.首先, 本文設(shè)計(jì)了緩沖區(qū)溢出攻擊的測試程序, 簡單的程序示例如圖5所示.程序中strcpy函數(shù)將str中的值復(fù)制到buff中的時(shí)候, 由于沒有邊界檢查, 棧中的返回值將被覆蓋, 當(dāng)函數(shù)執(zhí)行完后指令指針指向到了if代碼塊之中, 然而if中指令在程序正常執(zhí)行的情況下并不會(huì)被執(zhí)行.
圖5 簡單的攻擊代碼
實(shí)驗(yàn)結(jié)果與分析.當(dāng)示例程序在仿真器上模擬運(yùn)行的時(shí)候攻擊者成功使得if中本不應(yīng)被執(zhí)行的代碼執(zhí)行, 而當(dāng)PEC-V被使用時(shí), 程序跳轉(zhuǎn)到未知位置造成程序崩潰, 阻止了攻擊者的目的.
除了自行設(shè)計(jì)的溢出攻擊程序之外, 對于此機(jī)制的安全性, 進(jìn)一步根據(jù)Wilander等設(shè)計(jì)的緩沖區(qū)溢出的測試集進(jìn)行分析.Wilander等羅列出了20余種針對緩沖區(qū)溢出的攻擊[24], 主要分為4類, 分別為針對return address, function point, old base point和longjmp buffer的攻擊.因?yàn)楸疚牡臋C(jī)制針對的是return address和function point的加解密, 所以在此處只討論關(guān)于前兩者的攻擊.攻擊的方式又可分為棧溢出和堆溢出攻擊,攻擊方式如表2所示.
表2 Wilander等[24]研究中的攻擊種類
因?yàn)榇诵┕暨^程中都需要通過覆蓋返回地址或函數(shù)指針指向目的地址, 然而由于此類數(shù)據(jù)已被加密,在攻擊者無法獲得加密密鑰的情況下, 覆蓋后的值解密后將指向隨機(jī)地址造成程序崩潰, 因此攻擊者的目的將無法實(shí)現(xiàn).
(1) 測試程序.本實(shí)驗(yàn)首先使用Juliet Test Suite[25]這一常見漏洞測試集進(jìn)行效率測試.測試集中存在著幾種針對緩沖區(qū)溢出漏洞的分類(cwe121_stack_based_buffer_overflow, cwe122_heap_based_buffer_overflow和cwe124_buffer_underwrite, cwe680_integer_overflow_to_buffer_overflow), 選取這4種分類中的測試程序t1,t2,t3和t4, 進(jìn)行針對返回地址的防御實(shí)驗(yàn).其中,t1為向棧上緩沖區(qū)復(fù)制數(shù)據(jù)越界,t2為向堆上緩沖區(qū)復(fù)制數(shù)越界,t3為數(shù)組下標(biāo)越界,t4為整數(shù)溢出導(dǎo)致數(shù)組越界.由于Juliet測試集中缺少針對函數(shù)指針的攻擊示例, 對于函數(shù)指針的效率測試使用Wilander testbed中的測試集, 包括棧上溢出修改函數(shù)指針w1和堆上溢出修改函數(shù)指針w2和w3.測試過程首先將t1-t4和w1-w3編譯成原始的沒有加密機(jī)制保護(hù)的版本, 在此基礎(chǔ)上按照前文介紹的方式修改匯編代碼, 增加使用PEC-V的防護(hù)機(jī)制.接著在C++仿真器上本研究使用RISC-V的ProxyKernel運(yùn)行測試程序, 通過在測試程序開始前和結(jié)束后讀取時(shí)鐘寄存器的值來獲得精確的運(yùn)行周期.
除了使用已存在的測試集之外, 為了進(jìn)一步探究此防御機(jī)制的效率問題, 本文對于棧上溢出修改函數(shù)指針和返回地址的測試程序進(jìn)行修改, 增加對程序中嵌套調(diào)用函數(shù)和多次使用函數(shù)指針的情況的測試.test1測試針對返回地址的加解密的效率, test1中子函數(shù)迭代調(diào)用的次數(shù)從1到6增加.test2測試針對函數(shù)指針保護(hù)的效率, test2中使用的函數(shù)指針從1到6不斷增多.
(2) 實(shí)驗(yàn)結(jié)果與分析.對Juliet Test Suite和Wilander Testbed中的程序進(jìn)行實(shí)驗(yàn)后結(jié)果如圖6所示, 從中可以看出使用此機(jī)制對于常見的可利用漏洞進(jìn)行防御, 程序效率的下降未超過4%, 未造成嚴(yán)重影響.而在對test1和test2加密前后兩個(gè)版本測試后, 實(shí)驗(yàn)的運(yùn)行結(jié)果分別如圖7(a)和圖7(b)所示.從圖中可以看出test1和test2在受到協(xié)處理器的加密機(jī)制保護(hù)后, 運(yùn)行效率的下降在1%-3%之間.
圖6 測試集運(yùn)行效率
圖7 性能比較
從數(shù)據(jù)中可以看出, 對于一般測試程序而言, 硬件實(shí)施指針加密的方式并不會(huì)對程序的運(yùn)行效率產(chǎn)生顯著影響.
本文旨在介紹一種通過硬件方式實(shí)現(xiàn)的緩沖區(qū)溢出攻擊保護(hù)機(jī)制.通過RoCC接口接入指針加密協(xié)處理器, 加密返回地址和函數(shù)指針使得攻擊者定位目標(biāo)代碼的難度大大增加, 同時(shí)使得對程序的運(yùn)行效率的影響降到最小, 而PUF和TRNG在協(xié)處理器中的使用使得加密鍵值的隨機(jī)性得到保障, 并且PUF的特性可以加大物理手段獲取隨機(jī)鍵值的難度.實(shí)驗(yàn)結(jié)果表明,未使用PEC-V機(jī)制時(shí)針對對RISC-V的溢出攻擊能夠成功, 然而增加這一防護(hù)機(jī)制后, 攻擊的難度增加, 并且未對程序運(yùn)行效率造成顯著影響, 優(yōu)于以往的實(shí)現(xiàn)方案.
此外本文主要針對返回地址和函數(shù)指針進(jìn)行討論,而常見的溢出攻擊針對的目標(biāo)還有幀指針等, 此機(jī)制略作修改便可同樣運(yùn)用于幀指針值的保護(hù).而此預(yù)防機(jī)制存在一定的不足之處, 對于不需要返回到特定地址, 直接通過溢出改寫重要變量或者泄露重要信息的攻擊, 此機(jī)制暫時(shí)無法防御, 這方面的防御手段還需進(jìn)一步研究.