一種程序運(yùn)行時(shí)處理器指令校驗(yàn)方法
【專利摘要】本發(fā)明涉及一種程序運(yùn)行時(shí)處理器指令校驗(yàn)方法,該方法包括以下內(nèi)容:在程序運(yùn)行之前,計(jì)算出程序所有代碼段中每條正確指令的地址,然后將正確指令的地址轉(zhuǎn)換成地址校驗(yàn)數(shù)據(jù),最后在程序運(yùn)行過(guò)程中,當(dāng)處理器計(jì)算出一條分支轉(zhuǎn)移指令的分支目標(biāo)地址,未提交結(jié)果時(shí),對(duì)計(jì)算出的分支目標(biāo)地址進(jìn)行校驗(yàn),本發(fā)明可用于阻止利用程序非正常指令序列構(gòu)造出的惡意代碼在處理器上執(zhí)行。
【專利說(shuō)明】-種程序運(yùn)行時(shí)處理器指令校驗(yàn)方法
【技術(shù)領(lǐng)域】
[0001] 本發(fā)明設(shè)及一種程序運(yùn)行時(shí)處理器指令校驗(yàn)方法,屬于計(jì)算機(jī)安全領(lǐng)域,用于阻 止利用程序非正常指令序列構(gòu)造出的惡意代碼在處理器上執(zhí)行。
【背景技術(shù)】
[0002] 利用軟件漏洞進(jìn)行代碼注入攻擊是長(zhǎng)期W來(lái)最流行的一種惡意代碼攻擊手段。但 是近年來(lái)的計(jì)算機(jī)系統(tǒng)均引入了一種軟硬件結(jié)合的存儲(chǔ)保護(hù)機(jī)制W貸X。該保護(hù)機(jī)制使得 代碼注入攻擊變得非常困難。w?x機(jī)制規(guī)定了操作系統(tǒng)一個(gè)存儲(chǔ)頁(yè)的寫(xiě)入和執(zhí)行是互斥 的,即存放可執(zhí)行代碼的內(nèi)存頁(yè)不能被寫(xiě)入,可寫(xiě)入內(nèi)存頁(yè)中的內(nèi)容不能被執(zhí)行。該意味著 即使惡意代碼被植入一個(gè)內(nèi)存頁(yè),由于該個(gè)內(nèi)存頁(yè)不能被執(zhí)行,所W惡意代碼也不能發(fā)揮 作用。
[0003] 但是,近年來(lái)出現(xiàn)的代碼重用攻擊技術(shù)成為了新的利用軟件漏洞進(jìn)行惡意代碼攻 擊的手段。代碼重用攻擊不用進(jìn)行代碼注入,而是通過(guò)一系列分支轉(zhuǎn)移指令(包括跳轉(zhuǎn)指 令、函數(shù)調(diào)用指令、函數(shù)返回指令等)將程序已有的代碼(包括系統(tǒng)運(yùn)行庫(kù)中的代碼)重新 組織,構(gòu)成惡意代碼序列進(jìn)行攻擊。由于代碼重用攻擊不用向內(nèi)存頁(yè)中寫(xiě)入代碼數(shù)據(jù),而是 利用程序已有的代碼,所WW?X機(jī)制對(duì)代碼重用攻擊是完全無(wú)效的。
[0004] 代碼重用攻擊對(duì)于CISC指令集處理器(如目前廣泛使用的x86系列處理器)的威 脅要遠(yuǎn)大于RISC指令集處理器。該是因?yàn)樵赗ISC處理器中,所有指令長(zhǎng)度均是一致的,每 條指令的起始地址都是指令長(zhǎng)度的整倍數(shù)。RISC處理器在執(zhí)行指令時(shí),不接受起始于非指 令長(zhǎng)度整倍數(shù)地址的指令。但是CISC處理器的指令長(zhǎng)度是不固定的。Wx86處理器為例, 指令長(zhǎng)度可W是1個(gè)字節(jié)至16個(gè)字節(jié)。該意味著代碼段中的任何一個(gè)地址都可能是一條 新指令的起始地址。因此,在CISC處理器上構(gòu)造惡意代碼要比在RISC處理器上容易。目 前已公布的研究顯示,面向x86處理器的代碼重用攻擊所使用的90% W上的惡意代碼都是 由程序的非正常指令序列構(gòu)成。由此可見(jiàn),如果能夠阻止該些非正常指令序列的執(zhí)行,將會(huì) 極大地降低計(jì)算機(jī)系統(tǒng)被進(jìn)行代碼重用攻擊的風(fēng)險(xiǎn)。
[0005] 目前,采用CISC指令集的計(jì)算機(jī)系統(tǒng)(如使用x86系列處理器的計(jì)算機(jī))沒(méi)有 任何保護(hù)機(jī)制來(lái)阻止上述非正常指令序列的執(zhí)行。一些學(xué)術(shù)研究雖然提出了防止非正常 x86指令執(zhí)行的方法,但均采用軟件手段實(shí)現(xiàn),該些方法均要求應(yīng)用程序必須在一個(gè)軟件虛 擬機(jī)環(huán)境中運(yùn)行,從而導(dǎo)致應(yīng)用程序的運(yùn)行性能大大降低。本發(fā)明提出了一種軟硬件相結(jié) 合的保護(hù)機(jī)制來(lái)阻止處理器執(zhí)行非正常指令序列,該機(jī)制不依賴于虛擬機(jī)環(huán)境,應(yīng)用程序 不用進(jìn)行任何修改,且程序運(yùn)行性能損失非常小。本發(fā)明的方法可W應(yīng)用于X86 W及其他 CISC處理器系列。到目前為止,采用類(lèi)似方法來(lái)實(shí)現(xiàn)阻止非正常指令執(zhí)行的方法尚未見(jiàn)報(bào) 道。
【發(fā)明內(nèi)容】
[0006] 本發(fā)明目的在于降低計(jì)算機(jī)系統(tǒng)被進(jìn)行代碼重用W及其他利用非正常指令進(jìn)行 惡意代碼攻擊的風(fēng)險(xiǎn)。
[0007] 本發(fā)明一種程序運(yùn)行時(shí)處理器指令校驗(yàn)方法,其特征是該校驗(yàn)方法步驟如下:
[000引 (1)在程序運(yùn)行之前,計(jì)算出程序所有代碼段中每條正確指令的地址,其方法是:
[0009] 對(duì)于每個(gè)代碼段,通過(guò)代碼段信息獲取該代碼段起始處第一條指令的地址,然后 從第一條指令起對(duì)該代碼段進(jìn)行反匯編,并通過(guò)反匯編依次獲得該代碼段中所有指令的長(zhǎng) 度,此后每條指令的地址即為前一條指令的地址加上前一條指令的長(zhǎng)度;
[0010] (2)將正確指令的地址轉(zhuǎn)換成地址校驗(yàn)數(shù)據(jù),其方法是:
[0011] 將地址上連續(xù)的代碼段合并為一個(gè)代碼段進(jìn)行處理,設(shè)合并后代碼段的起始加載 地址是a。,結(jié)束地址為ai,對(duì)于a。至a 1范圍內(nèi)的每一個(gè)地址,當(dāng)該地址是一條正確指令的起 始地址,則用一位"1"來(lái)表示,否則用一位"0"來(lái)表示,或用一位"0"表示一條正確指令的 起始地址,一位"1"表示否,在程序運(yùn)行過(guò)程中,地址校驗(yàn)數(shù)據(jù)放在內(nèi)存中,供處理器校驗(yàn)指 令時(shí)進(jìn)行查詢,將所有合并后代碼段的起始加載地址、代碼段的大小和地址校驗(yàn)數(shù)據(jù)的地 址記錄到一個(gè)表中,供程序運(yùn)行時(shí)查詢使用;
[0012] (3)在程序運(yùn)行過(guò)程中,當(dāng)處理器計(jì)算出一條分支轉(zhuǎn)移指令的分支目標(biāo)地址,未提 交結(jié)果時(shí),對(duì)計(jì)算出的分支目標(biāo)地址進(jìn)行校驗(yàn),設(shè)待校驗(yàn)的分支目標(biāo)地址為at,其校驗(yàn)方法 是:
[0013] 1)通過(guò)一個(gè)分支目標(biāo)校驗(yàn)緩存對(duì)該地址at進(jìn)行校驗(yàn),該分支目標(biāo)緩存中存放了剛 成功執(zhí)行過(guò)的分支指令的分支目標(biāo)地址,當(dāng)待校驗(yàn)的分支地址at與分支目標(biāo)緩存中的一個(gè) 地址一致,則校驗(yàn)成功,處理器則繼續(xù)正常執(zhí)行,否則需執(zhí)行2),
[0014] 2)首先找到地址at所對(duì)應(yīng)的代碼段,即要知道地址at是在哪個(gè)代碼段的地址范圍 內(nèi),當(dāng)沒(méi)有找到對(duì)應(yīng)的代碼段,則地址at為非法地址,此時(shí)引發(fā)處理器異常,終止校驗(yàn)過(guò)程; 當(dāng)找到地址at對(duì)應(yīng)的代碼段后,設(shè)該代碼段的第一個(gè)指令的起始地址為a。,則根據(jù)地址at 相對(duì)于a。的偏移量找出相應(yīng)的地址校驗(yàn)數(shù)據(jù),其方法是;設(shè)該代碼段的地址校驗(yàn)數(shù)據(jù)存放 于地址a。處,取出地址化+「知-口。)/8]處的一個(gè)字節(jié),其中運(yùn)算「口]表示不超過(guò)n的最大整 數(shù),n為0?2^之間的實(shí)數(shù),該字節(jié)的第(a i-a。)% 8+1位即為地址at的校驗(yàn)數(shù)據(jù),其中% 表示取模運(yùn)算;當(dāng)校驗(yàn)數(shù)據(jù)表明地址at為一條正確指令的起始地址,則校驗(yàn)成功,處理器繼 續(xù)正常執(zhí)行,并用地址at更新分支目標(biāo)校驗(yàn)緩存,否則校驗(yàn)失敗,引發(fā)處理器異常。
[0015] 本發(fā)明的有益效果;該方法阻止應(yīng)用程序非正常指令的執(zhí)行達(dá)99% W上,并阻止 代碼重用攻擊達(dá)90% W上,且硬件與軟件開(kāi)銷(xiāo)均小于已報(bào)道的其他同類(lèi)方法。
【具體實(shí)施方式】
[0016] 下面W采用X86系列處理器,操作系統(tǒng)為L(zhǎng)inux的計(jì)算機(jī)系統(tǒng)為例,說(shuō)明本發(fā)明的
【具體實(shí)施方式】,下面敘述中所提到的內(nèi)存地址均是指虛地址。
[0017] 1、操作系統(tǒng)加載完應(yīng)用程序或動(dòng)態(tài)共享庫(kù)后,計(jì)算出各個(gè)代碼段中每條正確指令 的地址:
[001引 ELF格式是目前Linux操作系統(tǒng)所采用的可執(zhí)行文件格式,當(dāng)ELF格式的可執(zhí)行 程序或共享庫(kù)加載到內(nèi)存后,操作系統(tǒng)即獲知每個(gè)代碼段的第一條指令在內(nèi)存中的起始地 址。根據(jù)x86指令集的編碼規(guī)則,從第一條指令處開(kāi)始,依次將整個(gè)代碼段的二進(jìn)制數(shù)據(jù)反 匯編成合法的X86指令序列,并且根據(jù)第一條指令地址和反匯編出的每條指令長(zhǎng)度,依次 計(jì)算出每條指令在內(nèi)存中的地址。
[0019] 2、將步驟1中計(jì)算出的正確指令地址轉(zhuǎn)換成地址校驗(yàn)數(shù)據(jù):
[0020] 將地址上連續(xù)的多個(gè)代碼段合并為一個(gè)代碼段進(jìn)行處理,合并后代碼段的起始加 載地址是A,結(jié)束地址為B,對(duì)于A至B范圍內(nèi)的每一個(gè)地址,當(dāng)該地址是一條正確指令的起 始地址,則用一位"1"來(lái)表示,否則用一位"0"來(lái)表示。因?yàn)榈刂沸r?yàn)數(shù)據(jù)是只讀的,所W 該數(shù)據(jù)放在程序的代碼段空間中,處理器訪問(wèn)時(shí)通過(guò)指令cache或單獨(dú)的指令校驗(yàn)cache 訪問(wèn)。此外,將所有合并后代碼段的起始加載地址、代碼段的大小和地址校驗(yàn)數(shù)據(jù)的地址記 錄到一個(gè)表中,記作代碼段校驗(yàn)查詢表,作為操作系統(tǒng)進(jìn)程數(shù)據(jù)結(jié)構(gòu)的一部分,供程序運(yùn)行 時(shí)查詢使用。
[0021] 3、在程序運(yùn)行過(guò)程中,當(dāng)處理器計(jì)算出一條分支轉(zhuǎn)移指令的分支目標(biāo)地址但還未 提交結(jié)果時(shí),對(duì)計(jì)算出的分支目標(biāo)地址進(jìn)行校驗(yàn):
[0022] 當(dāng)流水線的提交單元要提交一條非直接分支指令的結(jié)果時(shí),對(duì)分支指令的分支目 標(biāo)地址進(jìn)行校驗(yàn),當(dāng)該分支目標(biāo)地址合法時(shí),處理器繼續(xù)正常執(zhí)行,否則將引發(fā)一個(gè)處理器 異常。該校驗(yàn)過(guò)程如下:
[0023] (1)首先,通過(guò)分支目標(biāo)校驗(yàn)緩存對(duì)分支目標(biāo)地址進(jìn)行校驗(yàn),該分支目標(biāo)校驗(yàn)緩存 中存放了最近成功執(zhí)行過(guò)的分支指令的分支目標(biāo)地址。硬件實(shí)現(xiàn)上,該分支目標(biāo)校驗(yàn)緩存 設(shè)置在處理器的提交單元附近。當(dāng)待校驗(yàn)的分支目標(biāo)地址命中該緩存時(shí),表明該分支目標(biāo) 合法,此時(shí)處理器繼續(xù)正常執(zhí)行。沒(méi)有命中,則需進(jìn)行步驟(2);
[0024] (2)x86處理器含有一個(gè)分支預(yù)測(cè)器,分支預(yù)測(cè)器位于處理器的取指單元附近,所 W訪問(wèn)分支預(yù)測(cè)器的延遲要大于直接訪問(wèn)提交單元附近的分支目標(biāo)校驗(yàn)緩存,但分支目標(biāo) 校驗(yàn)緩存通過(guò)設(shè)置較少的校驗(yàn)項(xiàng)W節(jié)省硬件開(kāi)銷(xiāo)。分支預(yù)測(cè)器中存在一個(gè)BTB(分支目標(biāo) 緩存)部件,當(dāng)待校驗(yàn)分支目標(biāo)地址沒(méi)有命中提交單元附近的分支目標(biāo)校驗(yàn)緩存時(shí),查詢 分支預(yù)測(cè)器中的BTB,命中則表明該分支目標(biāo)合法,此時(shí)處理器繼續(xù)正常執(zhí)行,否則需進(jìn)行 步驟(3);
[0025] (3)通過(guò)代碼段校驗(yàn)查詢表緩存來(lái)查找該分支目標(biāo)地址所處的代碼段。代碼段校 驗(yàn)查詢表緩存是存放在內(nèi)存中的代碼段校驗(yàn)查詢表在處理器里的一個(gè)部分緩存映像。當(dāng)待 校驗(yàn)的分支目標(biāo)地址在代碼段校驗(yàn)查詢表緩存中找到相應(yīng)的代碼段信息時(shí)執(zhí)行步驟(4), 否則引發(fā)一個(gè)中斷,在中斷過(guò)程中操作系統(tǒng)在完整的代碼段校驗(yàn)查詢表中查找待校驗(yàn)的分 支目標(biāo)地址所對(duì)應(yīng)的代碼段,查找失敗則表明該分支目標(biāo)地址非法,引發(fā)處理器異常,當(dāng)找 到相應(yīng)的代碼段,則用該代碼段信息更新代碼段校驗(yàn)查詢表緩存,中斷返回,繼續(xù)執(zhí)行步驟 (4);
[0026] (4)設(shè)待校驗(yàn)的分支目標(biāo)地址為a。在步驟做中查詢到的代碼段的第一條指令 地址為a。,代碼段的地址校驗(yàn)數(shù)據(jù)存放于內(nèi)存地址a。處,則在內(nèi)存地址化+「(口飢)/8' 處的字節(jié)的第(at-a。)% 8+1位為地址at的校驗(yàn)數(shù)據(jù)。為了正確訪問(wèn)該地址,需經(jīng)將地址 化+「(化-口o)/8l通過(guò)指令翻譯后備緩沖器轉(zhuǎn)換成物理地址,然后通過(guò)1級(jí)指令cache和二 級(jí)cache等訪問(wèn)該地址處的校驗(yàn)數(shù)據(jù)。獲得校驗(yàn)數(shù)據(jù)后,校驗(yàn)數(shù)據(jù)為"1"則表明地址at為 一條正確指令的起始地址,處理器繼續(xù)正常執(zhí)行,并用地址at更新分支目標(biāo)校驗(yàn)緩存,否則 校驗(yàn)失敗,引發(fā)處理器異常。
[0027] 將該實(shí)例應(yīng)用在裝有Intel Corei7處理器和Linux操作系統(tǒng)的計(jì)算機(jī)上進(jìn)行測(cè) 試,測(cè)試結(jié)果表明本方法阻止應(yīng)用程序非正常指令的執(zhí)行達(dá)100%,并阻止了 94%的代碼 重用攻擊,計(jì)算機(jī)系統(tǒng)增加的開(kāi)銷(xiāo)為0. 03%,而已報(bào)道同類(lèi)方法的開(kāi)銷(xiāo)均在20% W上。
【權(quán)利要求】
1. 一種程序運(yùn)行時(shí)處理器指令校驗(yàn)方法,其特征是該校驗(yàn)方法步驟如下: (1) 在程序運(yùn)行之前,計(jì)算出程序所有代碼段中每條正確指令的地址,其方法是: 對(duì)于每個(gè)代碼段,通過(guò)代碼段信息獲取該代碼段起始處第一條指令的地址,然后從第 一條指令起對(duì)該代碼段進(jìn)行反匯編,并通過(guò)反匯編依次獲得該代碼段中所有指令的長(zhǎng)度, 此后每條指令的地址即為前一條指令的地址加上前一條指令的長(zhǎng)度; (2) 將正確指令的地址轉(zhuǎn)換成地址校驗(yàn)數(shù)據(jù),其方法是: 將地址上連續(xù)的代碼段合并為一個(gè)代碼段進(jìn)行處理,設(shè)合并后代碼段的起始加載地址 是a。,結(jié)束地址為S1,對(duì)于8(|至ai范圍內(nèi)的每一個(gè)地址,當(dāng)該地址是一條正確指令的起始地 址,則用一位"1"來(lái)表示,否則用一位"〇"來(lái)表示,或用一位"〇"表示一條正確指令的起始 地址,一位" 1"表示否,在程序運(yùn)行過(guò)程中,地址校驗(yàn)數(shù)掘放在內(nèi)存中,供處理器校驗(yàn)指令時(shí) 進(jìn)行查詢,將所有合并后代碼段的起始加載地址、代碼段的大小和地址校驗(yàn)數(shù)據(jù)的地址記 錄到一個(gè)表中,供程序運(yùn)行時(shí)查詢使用; (3) 在程序運(yùn)行過(guò)程中,當(dāng)處理器計(jì)算出一條分支轉(zhuǎn)移指令的分支目標(biāo)地址,未提交結(jié) 果時(shí),對(duì)計(jì)算出的分支目標(biāo)地址進(jìn)行校驗(yàn),設(shè)待校驗(yàn)的分支目標(biāo)地址為at,其校驗(yàn)方法是: 1) 通過(guò)一個(gè)分支目標(biāo)校驗(yàn)緩存對(duì)該地址at進(jìn)行校驗(yàn),該分支目標(biāo)緩存中存放了剛成功 執(zhí)行過(guò)的分支指令的分支目標(biāo)地址,當(dāng)待校驗(yàn)的分支地址at與分支目標(biāo)緩存中的一個(gè)地址 一致,則校驗(yàn)成功,處理器則繼續(xù)正常執(zhí)行,否則需執(zhí)行2), 2) 首先找到地址at所對(duì)應(yīng)的代碼段,即要知道地址at是在哪個(gè)代碼段的地址范圍內(nèi), 當(dāng)沒(méi)有找到對(duì)應(yīng)的代碼段,則地址at為非法地址,此時(shí)引發(fā)處理器異常,終止校驗(yàn)過(guò)程;當(dāng) 找到地址at對(duì)應(yīng)的代碼段后,設(shè)該代碼段的第一個(gè)指令的起始地址為a^,則根據(jù)地址\相 對(duì)于%的偏移量找出相應(yīng)的地址校驗(yàn)數(shù)掘,其方法是:設(shè)該代碼段的地址校驗(yàn)數(shù)據(jù)存放于 地址a。處,取出地址也+「(必-伽)/81處的一個(gè)字節(jié),其中運(yùn)算表示不超過(guò)n的最大整數(shù), n為0?264之間的實(shí)數(shù),該字節(jié)的第(a,-?) % 8+1位即為地址at的校驗(yàn)數(shù)據(jù),其中%表示 取模運(yùn)算;當(dāng)校驗(yàn)數(shù)據(jù)表明地址at為一條正確指令的起始地址,則校驗(yàn)成功,處理器繼續(xù)正 常執(zhí)行,并用地址at更新分支目標(biāo)校驗(yàn)緩存,否則校驗(yàn)失敗,引發(fā)處理器異常。
【文檔編號(hào)】G06F21/56GK104504329SQ201410835359
【公開(kāi)日】2015年4月8日 申請(qǐng)日期:2014年12月30日 優(yōu)先權(quán)日:2014年12月30日
【發(fā)明者】呂雅帥, 趙忠文, 吳玲達(dá) 申請(qǐng)人:中國(guó)人民解放軍裝備學(xué)院