張琦 劉一辰
摘? 要:C語言廣泛應(yīng)用于嵌入式軟件和系統(tǒng)軟件的開發(fā),它提供了更直接的底層內(nèi)存控制,但卻缺少對(duì)內(nèi)存訪問安全性的檢測(cè),導(dǎo)致C程序運(yùn)行時(shí)可能產(chǎn)生內(nèi)存安全性錯(cuò)誤。當(dāng)前,開發(fā)人員力求通過多種驗(yàn)證技術(shù)解決內(nèi)存安全性錯(cuò)誤,最常用的是運(yùn)行時(shí)驗(yàn)證技術(shù)。文章首先對(duì)C程序常見的內(nèi)存安全性錯(cuò)誤進(jìn)行分析,然后介紹幾種相關(guān)的內(nèi)存分析技術(shù),最后分別對(duì)幾種常用的C程序內(nèi)存安全性檢測(cè)工具進(jìn)行介紹和比較,為接下來的研究工作提供了方向性參考。
關(guān)鍵詞:C程序;內(nèi)存錯(cuò)誤;運(yùn)行時(shí)驗(yàn)證;AddressSanitizer;Movec
中圖分類號(hào):TP311? ? ?文獻(xiàn)標(biāo)識(shí)碼:A文章編號(hào):2096-4706(2021)23-0084-04
Overview of C Language Memory Safety Runtime Verification Technology
ZHANG Qi, LIU Yichen
(College of Computer Science and Technology, Nanjing University of Aeronautics and Astronautics, Nanjing? 211106, China)
Abstract: C language is widely used in the development of embedded software and system software. It provides more direct underlying memory control but lacks the detection of memory access security, which causes memory security errors when C programs are running. At present, developers strive to solve memory security errors through a variety of verification technologies, the most commonly used is runtime verification technology. This paper first analyzes common memory security errors in C programs, then introduces several related memory analysis techniques, and finally introduces and compares several commonly used C program memory security detection tools. It provides direction reference for the following research work.
Keywords: C program; memory error; runtime verification; Address Sanitizer; Movec
0? 引? 言
隨著社會(huì)的不斷發(fā)展,信息化為人們的生產(chǎn)生活帶來極大的便利。生活中的方方面面都離不開計(jì)算機(jī)軟件的應(yīng)用,如在線教育、智能交通服務(wù)、遠(yuǎn)程醫(yī)療、5G通信以及各種社交、辦公等領(lǐng)域。計(jì)算機(jī)軟件在給人們帶來便利的同時(shí),也潛藏著一些安全問題。OpenSSL本身是一個(gè)用于安全通信,可以保證數(shù)據(jù)機(jī)密性和可靠性的應(yīng)用程序。然而,在2014年,OpenSSL被爆出“心臟滴血”重大漏洞,攻擊者通過這一漏洞,可以獲取應(yīng)用程序源碼、用戶的網(wǎng)絡(luò)訪問請(qǐng)求和用戶的cookie信息,甚至可以獲取到用戶的電子郵件、銀行卡賬號(hào)密碼等信息,給用戶帶來不可估量的損失。RPC遠(yuǎn)程過程調(diào)用是一個(gè)進(jìn)程通信機(jī)制,允許一臺(tái)計(jì)算機(jī)遠(yuǎn)程執(zhí)行另一臺(tái)計(jì)算機(jī)上的代碼。2003年,利用RPC一個(gè)漏洞的蠕蟲“沖擊波”在互聯(lián)網(wǎng)上傳播,感染了上百萬臺(tái)計(jì)算機(jī)。該病毒會(huì)建立一個(gè)“后門”,允許攻擊者遠(yuǎn)程控制被感染的計(jì)算機(jī),使其系統(tǒng)崩潰。根據(jù)保守估算,“沖擊波”造成至少5億美元的經(jīng)濟(jì)損失,而起因卻是源于代碼中存在一個(gè)緩沖區(qū)溢出漏洞。為了保證軟件使用的可靠性和信息的安全性,越來越多的技術(shù)注重于檢測(cè)軟件系統(tǒng)的內(nèi)存安全性。當(dāng)前,主流的軟件驗(yàn)證技術(shù)包括軟件測(cè)試、程序靜態(tài)分析、模型檢測(cè)和運(yùn)行時(shí)驗(yàn)證等。
C語言編寫的程序具有運(yùn)行速度快、執(zhí)行效率高等特點(diǎn),因此C語言廣泛應(yīng)用于嵌入式系統(tǒng)軟件的開發(fā)。同時(shí)它提供了更直接的底層內(nèi)存控制,但卻缺少對(duì)內(nèi)存訪問安全性的檢測(cè),導(dǎo)致C程序運(yùn)行時(shí)可能產(chǎn)生內(nèi)存安全性錯(cuò)誤,比如內(nèi)存泄漏、緩沖區(qū)溢出、多次釋放等。因此,對(duì)C語言的內(nèi)存安全性進(jìn)行驗(yàn)證是十分重要的。
1? C程序內(nèi)存錯(cuò)誤
借鑒Safe-C的分類方法,可以將C程序的內(nèi)存錯(cuò)誤分為空間內(nèi)存錯(cuò)誤和時(shí)間內(nèi)存錯(cuò)誤??臻g內(nèi)存錯(cuò)誤是指對(duì)內(nèi)存上下界范圍外的空間進(jìn)行非法的訪問或修改,比如,對(duì)空指針進(jìn)行解引用、緩沖區(qū)溢出,訪問非法指針等。時(shí)間內(nèi)存錯(cuò)誤是指訪問已經(jīng)釋放的內(nèi)存,比如,釋放后使用(UAF)、解引用懸掛指針、多次釋放、非法釋放等。
如圖1所示為幾種常見的空間內(nèi)存錯(cuò)誤。
圖1列出了幾種C程序常見空間內(nèi)存錯(cuò)誤,如圖2所示為幾種常見的時(shí)間內(nèi)存錯(cuò)誤。
2? 運(yùn)行時(shí)驗(yàn)證技術(shù)
動(dòng)態(tài)分析技術(shù)在運(yùn)行程序的基礎(chǔ)上,通過監(jiān)測(cè)程序的執(zhí)行情況來收集程序的運(yùn)行時(shí)行為,并對(duì)其進(jìn)行分析,檢查程序是否存在內(nèi)存安全性問題。下面介紹幾種常見的運(yùn)行時(shí)驗(yàn)證技術(shù):
(1)值驗(yàn)證技術(shù)。由Crispan Cowan等人提出,主要用于檢測(cè)緩沖區(qū)溢出問題。值驗(yàn)證技術(shù)的原理是在局部變量緩存區(qū)和函數(shù)返回地址之間插入一個(gè)安全變量。局部變量緩沖區(qū)一旦溢出,如果攻擊者試圖修改函數(shù)的返回地址,則該安全變量也會(huì)隨之被更改??梢酝ㄟ^檢測(cè)安全變量是否被修改來檢測(cè)程序是否被惡意攻擊。由于值驗(yàn)證技術(shù)是通過在棧上插入安全變量的方式來檢測(cè)緩沖區(qū)溢出問題,因此該方法無法檢測(cè)堆內(nèi)存和全局的緩沖區(qū)溢出問題,同時(shí)也無法檢測(cè)時(shí)間內(nèi)存錯(cuò)誤,有很大的局限性。
(2)基于對(duì)象技術(shù)。由Jones和Kelly提出,主要用于檢測(cè)內(nèi)存越界等問題。它的主要思想是存儲(chǔ)程序中所有對(duì)象的上下邊界,而非存儲(chǔ)各個(gè)指針,這樣做的好處是多個(gè)指針指向同一個(gè)對(duì)象時(shí)只需記錄一次,從而節(jié)省存儲(chǔ)空間。對(duì)指針進(jìn)行解引用訪問時(shí),在指針元數(shù)據(jù)表中查詢指針的地址值,檢查指針值是否在上下界之間,如果指針值在上下界之間,則訪問合法。采用這種方式保證了對(duì)象內(nèi)存布局的完整性,同時(shí)也會(huì)記錄堆內(nèi)存的空間分配邊界信息。但是該技術(shù)最大的缺點(diǎn)是無法解決子對(duì)象問題。
(3)寬指針(fat-pointer)技術(shù)。顧名思義,指針不再只存有內(nèi)存地址信息,還存有該指針?biāo)赶騼?nèi)存塊的基地址和大小等信息。Safe-C就是在寬指針的基礎(chǔ)之上,額外增加了指針變量的存儲(chǔ)類型和引用計(jì)數(shù),不僅可以檢測(cè)內(nèi)存越界等問題,還能處理部分時(shí)間內(nèi)存錯(cuò)誤。由于寬指針技術(shù)更改了原有的指針結(jié)構(gòu),會(huì)導(dǎo)致插樁后的代碼與未插樁代碼(比如庫函數(shù))不兼容,并且插樁后的指針結(jié)構(gòu)變得復(fù)雜,致使程序執(zhí)行效率低下。
(4)基于指針的技術(shù)。其思想與寬指針類似,不同的是,該方法將指針的內(nèi)存地址和大小等信息記錄到一個(gè)獨(dú)立的數(shù)據(jù)結(jié)構(gòu)中,從而不改變?cè)械闹羔樈Y(jié)構(gòu)。基于指針技術(shù)的方法為每一個(gè)新創(chuàng)建的指針變量建立一個(gè)指針元數(shù)據(jù)pmd,pmd中存儲(chǔ)指針?biāo)笇?duì)象的邊界等信息。在為指針賦值時(shí),會(huì)進(jìn)行指針元數(shù)據(jù)的更新,新指針的指針元數(shù)據(jù)繼承自原指針的指針元數(shù)據(jù)。在對(duì)指針進(jìn)行解引用訪問內(nèi)存時(shí),首先需要對(duì)該指針的pmd進(jìn)行查詢,判斷訪問地址是否在對(duì)象的上下界范圍之內(nèi)以及是否滿足相應(yīng)的類型。
(5)影子內(nèi)存技術(shù)。是指將一個(gè)程序內(nèi)存狀態(tài)以某種特定的方式偏移映射到一個(gè)特定的空間內(nèi),其中內(nèi)存狀態(tài)中包含了程序中變量存放的地址、內(nèi)存是否被初始化以及其他一些變量的信息等。在對(duì)程序中的變量進(jìn)行訪問時(shí),通過查詢其影子空間存儲(chǔ)的該變量的內(nèi)存狀態(tài)來判斷訪問是否合法。
3? 運(yùn)行時(shí)驗(yàn)證工具
目前,針對(duì)C語言比較成熟的動(dòng)態(tài)分析工具有AddressSantizer、SoftBoundCets、Valgrind、Movec等:
(1)AddressSanitizer是谷歌公司開發(fā)的基于影子內(nèi)存的技術(shù),采用中間代碼插樁實(shí)現(xiàn)的動(dòng)態(tài)檢測(cè)工具。該算法的思路是:如果想避免緩沖區(qū)溢出,只需在每塊內(nèi)存區(qū)域的右端(或兩端)加一塊紅色區(qū)域,將內(nèi)存的狀態(tài)信息記錄到影子內(nèi)存中,在對(duì)內(nèi)存進(jìn)行操作時(shí)可以通過影子內(nèi)存來判斷該內(nèi)存的狀態(tài)。AddressSantizer可以有效檢測(cè)緩沖區(qū)溢出、UAF、Double-Free、內(nèi)存泄漏等問題,但卻無法處理子對(duì)象越界等問題。
(2)SoftBoundCets由SoftBound和Cets構(gòu)成,同樣采用基于指針的技術(shù)。其中,SoftBound可以檢測(cè)空間內(nèi)存錯(cuò)誤,它記錄每一個(gè)指針?biāo)笇?duì)象的邊界信息。而Cets可以檢測(cè)部分時(shí)間內(nèi)存錯(cuò)誤,它為每個(gè)對(duì)象維護(hù)一個(gè)唯一ID,在訪問該對(duì)象內(nèi)存空間時(shí)進(jìn)行檢測(cè)。但SoftBoundCets卻難以檢測(cè)子對(duì)象越界、非法訪問庫函數(shù)以及函數(shù)的指針參數(shù)等問題。
(3)Valgrind是一款用于內(nèi)存安全檢測(cè)以及性能分析的框架。Memcheck是最廣泛使用的重量級(jí)內(nèi)存安全檢測(cè)工具,能夠檢測(cè)大多數(shù)的內(nèi)存錯(cuò)誤,比如對(duì)未初始化內(nèi)存的訪問、內(nèi)存訪問越界等。它采用二進(jìn)制代碼插樁技術(shù)并結(jié)合影子內(nèi)存技術(shù),記錄程序中內(nèi)存字節(jié)是否具有有效的、已初始化的值,并記錄地址空間是否能夠被讀寫。在操作內(nèi)存空間時(shí),可以通過記錄表來分析檢測(cè)程序中的空指針訪問、Double-Free等問題,但無法處理全局變量緩沖區(qū)溢出、子對(duì)象越界等問題。
(4)Movec是南京航空航天大學(xué)計(jì)算機(jī)科學(xué)與技術(shù)學(xué)院SVLAB實(shí)驗(yàn)室自主開發(fā)的用于C程序運(yùn)行時(shí)監(jiān)控、驗(yàn)證的自動(dòng)化工具。Movec采用源代碼插樁技術(shù),利用LLVM和Clang編譯器可以將用Movec語言編寫的有關(guān)安全屬性和監(jiān)控規(guī)范的運(yùn)行時(shí)檢查器插入到C程序中,插樁后的程序可以兼容任何C語言編譯器(例如GCC和其他特定于平臺(tái)的編譯器)。Movec采用擴(kuò)展的基于指針的技術(shù),每個(gè)指針變量創(chuàng)建并維護(hù)一個(gè)指針元數(shù)據(jù)pmd(pointer metadata),圖3(a)定義了pmd的數(shù)據(jù)結(jié)構(gòu)。pmd中存儲(chǔ)了所指向?qū)ο蟮纳舷陆鏱ase和bound信息,同時(shí)還存儲(chǔ)了為每個(gè)內(nèi)存對(duì)象創(chuàng)建并維護(hù)的狀態(tài)節(jié)點(diǎn)snd,圖3(b)定義了snd的數(shù)據(jù)結(jié)構(gòu)。snd中存儲(chǔ)了內(nèi)存對(duì)象的狀態(tài)stat和引用計(jì)數(shù)count。對(duì)象的狀態(tài)包括heap、stack、global、static、function和invalid,而引用計(jì)數(shù)記錄指向該對(duì)象的指針數(shù)。
4? 實(shí)驗(yàn)對(duì)比分析
為了驗(yàn)證上述工具對(duì)C程序內(nèi)存安全性錯(cuò)誤的檢測(cè)能力,本文選用Mibench標(biāo)準(zhǔn)測(cè)試集中的部分軟件作為該實(shí)驗(yàn)的實(shí)驗(yàn)數(shù)據(jù)。Mibench中包含了35個(gè)用于基準(zhǔn)測(cè)試的嵌入式應(yīng)用測(cè)試集,它主要是對(duì)通用領(lǐng)域的計(jì)算能力進(jìn)行評(píng)價(jià),Mibench測(cè)試集在指令分布、內(nèi)存行為、并行化等方面獨(dú)具優(yōu)勢(shì)。
本文實(shí)驗(yàn)運(yùn)行環(huán)境為:處理器選用Intel? Core? i5-7300U CPU、四核、CPU主頻2.60 GHz,內(nèi)存為8 GB,操作系統(tǒng)為64位Ubuntu 16.04.12,編譯器為gcc 5.4.0。實(shí)驗(yàn)結(jié)果如表1所示。
其中,Y表示可以找出程序的內(nèi)存安全性錯(cuò)誤,N表示無法找出錯(cuò)誤,/表示程序無法正常運(yùn)行。從實(shí)驗(yàn)結(jié)果可知,Movec可以找出程序中的大部分錯(cuò)誤,并準(zhǔn)確地給出了錯(cuò)誤信息;SoftBoundCets無法檢測(cè)出錯(cuò)誤,并且對(duì)部分程序無法正常插樁運(yùn)行;Valgrind僅發(fā)現(xiàn)了部分錯(cuò)誤。AddressSantizer的檢測(cè)能力與Movec最接近,它發(fā)現(xiàn)了測(cè)試集中存在的大多數(shù)錯(cuò)誤,但是漏報(bào)了blowfish中的錯(cuò)誤。
5? 結(jié)? 論
隨著信息化技術(shù)的快速發(fā)展,人們的生活越來越離不開計(jì)算機(jī)軟件的使用,計(jì)算機(jī)軟件在給人們生活帶來便利的同時(shí)也存在著安全隱患,保證軟件的使用安全變得尤為重要。運(yùn)行時(shí)驗(yàn)證技術(shù)作為輕量化的驗(yàn)證方法,能夠有效地檢測(cè)系統(tǒng)內(nèi)存安全性方面的漏洞,得到了越來越多的應(yīng)該。本文總結(jié)了幾種常用的運(yùn)行時(shí)驗(yàn)證技術(shù),對(duì)比了幾種流行的運(yùn)行時(shí)驗(yàn)證工具并進(jìn)行了實(shí)驗(yàn)比較。希望未來能夠推出更多高精尖技術(shù),并且可以將運(yùn)行時(shí)驗(yàn)證技術(shù)與靜態(tài)分析、模糊測(cè)試等技術(shù)相結(jié)合,進(jìn)一步為軟件的內(nèi)存安全性檢測(cè)做出貢獻(xiàn)。
參考文獻(xiàn):
[1] John,Matt,Pravir. Network security with openSSL: cryptography for secure communications [M].O’Reilly Media,2002.
[2] 曹志波.OpenSSL的心臟出血漏洞 [J].電子技術(shù)與軟件工程,2017(13):263.
[3] AUSTIN T M,BREACH S E,SOHI G S. Efficient detection of all pointer and array access errors [J].ACM SIGPLAN Notices,1994,29(6):290-301.
[4] 嚴(yán)俊琦,陳哲,黃志球.C程序內(nèi)存安全的運(yùn)行時(shí)檢測(cè)方法研究和實(shí)現(xiàn) [J].小型微型計(jì)算機(jī)系統(tǒng),2017,38(10):2358-2362.
[5] 李文明,陳哲,李緒蓉,等.C程序數(shù)組越界的運(yùn)行時(shí)驗(yàn)證技術(shù)研究與實(shí)現(xiàn) [J].計(jì)算機(jī)工程與應(yīng)用,2015,51(11):190-195+211.
[6] MA R,Chen L K,Hu C Z,et al. A dynamic detection method to C/C++ programs memory vulnerabilities based on pointer analysis [C]//2013 IEEE 11th International Conference on Dependable, Autonomic and Secure Computing. Chengdu:IEEE,2013:52-57.
[7] XU W,DUVARNEY D C,SEKAR R. An efficient and backwards-compatible transformation to ensure memory safety of C programs [C]//ACM SIGSOFT twelfth international symposium on Foundations of software engineering. Newport Beach:Stony Brook University,2004:117-126.
[8] STEPANOV E,SEREBRYANY K. MemorySanitizer: Fast detector of uninitialized memory use in C++ [C]//2015 IEEE/ACM International Symposium on Code Generation and Optimization (CGO). San Francisco:IEEE,2015:46-55.
[9] SEREBRYANY K,BRUENING D,POTAPENKO A,et al. Addresssanitizer: A fast address sanity checker [C]//Usenix Conference on Technical Conference. USENIX Association,2012:309-318.
[10] NAGARAKATTE S,ZHAO J,MARTIN M M K,et al. SoftBound: Highly compatible and complete spatial memory safety for C [C]//Proceedings of the 2009 ACM SIGPLAN Conference on Programming Language Design and Implementation. Dublin:ACM,2009:245-258.
[11] Frascaroli J,Brivio S,Covi E,et al. Evidence of soft bound behaviour in analogue memristive devices for neuromorphic computing [J].Scientific reports,2018,8(1):1-12.
[12] Nethercote N,Seward J. Valgrind: a framework for heavyweight dynamic binary instrumentation [J].ACM Sigplan notices,2007,42(6):89-100.
[13] Nethercote N,Seward J. Valgrind: A program supervision framework [J].Electronic notes in theoretical computer science,2003,89(2):44-66.
作者簡介:張琦(1992—),男,漢族,江蘇連云港人,碩士研究生在讀,主要研究方向:軟件驗(yàn)證;劉一辰(1999—),男,漢族,河北邢臺(tái)人,碩士研究生在讀,主要研究方向:軟件驗(yàn)證。