C语言内存安全性运行时验证技术综述

2021-05-07 02:24张琦刘一辰
现代信息科技 2021年23期
关键词:缓冲区指针C语言

张琦 刘一辰

摘  要:C语言广泛应用于嵌入式软件和系统软件的开发,它提供了更直接的底层内存控制,但却缺少对内存访问安全性的检测,导致C程序运行時可能产生内存安全性错误。当前,开发人员力求通过多种验证技术解决内存安全性错误,最常用的是运行时验证技术。文章首先对C程序常见的内存安全性错误进行分析,然后介绍几种相关的内存分析技术,最后分别对几种常用的C程序内存安全性检测工具进行介绍和比较,为接下来的研究工作提供了方向性参考。

关键词:C程序;内存错误;运行时验证;AddressSanitizer;Movec

中图分类号:TP311     文献标识码:A文章编号: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  引  言

随着社会的不断发展,信息化为人们的生产生活带来极大的便利。生活中的方方面面都离不开计算机软件的应用,如在线教育、智能交通服务、远程医疗、5G通信以及各种社交、办公等领域。计算机软件在给人们带来便利的同时,也潜藏着一些安全问题。OpenSSL本身是一个用于安全通信,可以保证数据机密性和可靠性的应用程序。然而,在2014年,OpenSSL被爆出“心脏滴血”重大漏洞,攻击者通过这一漏洞,可以获取应用程序源码、用户的网络访问请求和用户的cookie信息,甚至可以获取到用户的电子邮件、银行卡账号密码等信息,给用户带来不可估量的损失。RPC远程过程调用是一个进程通信机制,允许一台计算机远程执行另一台计算机上的代码。2003年,利用RPC一个漏洞的蠕虫“冲击波”在互联网上传播,感染了上百万台计算机。该病毒会建立一个“后门”,允许攻击者远程控制被感染的计算机,使其系统崩溃。根据保守估算,“冲击波”造成至少5亿美元的经济损失,而起因却是源于代码中存在一个缓冲区溢出漏洞。为了保证软件使用的可靠性和信息的安全性,越来越多的技术注重于检测软件系统的内存安全性。当前,主流的软件验证技术包括软件测试、程序静态分析、模型检测和运行时验证等。

C语言编写的程序具有运行速度快、执行效率高等特点,因此C语言广泛应用于嵌入式系统软件的开发。同时它提供了更直接的底层内存控制,但却缺少对内存访问安全性的检测,导致C程序运行时可能产生内存安全性错误,比如内存泄漏、缓冲区溢出、多次释放等。因此,对C语言的内存安全性进行验证是十分重要的。

1  C程序内存错误

借鉴Safe-C的分类方法,可以将C程序的内存错误分为空间内存错误和时间内存错误。空间内存错误是指对内存上下界范围外的空间进行非法的访问或修改,比如,对空指针进行解引用、缓冲区溢出,访问非法指针等。时间内存错误是指访问已经释放的内存,比如,释放后使用(UAF)、解引用悬挂指针、多次释放、非法释放等。

如图1所示为几种常见的空间内存错误。

图1列出了几种C程序常见空间内存错误,如图2所示为几种常见的时间内存错误。

2  运行时验证技术

动态分析技术在运行程序的基础上,通过监测程序的执行情况来收集程序的运行时行为,并对其进行分析,检查程序是否存在内存安全性问题。下面介绍几种常见的运行时验证技术:

(1)值验证技术。由Crispan Cowan等人提出,主要用于检测缓冲区溢出问题。值验证技术的原理是在局部变量缓存区和函数返回地址之间插入一个安全变量。局部变量缓冲区一旦溢出,如果攻击者试图修改函数的返回地址,则该安全变量也会随之被更改。可以通过检测安全变量是否被修改来检测程序是否被恶意攻击。由于值验证技术是通过在栈上插入安全变量的方式来检测缓冲区溢出问题,因此该方法无法检测堆内存和全局的缓冲区溢出问题,同时也无法检测时间内存错误,有很大的局限性。

(2)基于对象技术。由Jones和Kelly提出,主要用于检测内存越界等问题。它的主要思想是存储程序中所有对象的上下边界,而非存储各个指针,这样做的好处是多个指针指向同一个对象时只需记录一次,从而节省存储空间。对指针进行解引用访问时,在指针元数据表中查询指针的地址值,检查指针值是否在上下界之间,如果指针值在上下界之间,则访问合法。采用这种方式保证了对象内存布局的完整性,同时也会记录堆内存的空间分配边界信息。但是该技术最大的缺点是无法解决子对象问题。

(3)宽指针(fat-pointer)技术。顾名思义,指针不再只存有内存地址信息,还存有该指针所指向内存块的基地址和大小等信息。Safe-C就是在宽指针的基础之上,额外增加了指针变量的存储类型和引用计数,不仅可以检测内存越界等问题,还能处理部分时间内存错误。由于宽指针技术更改了原有的指针结构,会导致插桩后的代码与未插桩代码(比如库函数)不兼容,并且插桩后的指针结构变得复杂,致使程序执行效率低下。

(4)基于指针的技术。其思想与宽指针类似,不同的是,该方法将指针的内存地址和大小等信息记录到一个独立的数据结构中,从而不改变原有的指针结构。基于指针技术的方法为每一个新创建的指针变量建立一个指针元数据pmd,pmd中存储指针所指对象的边界等信息。在为指针赋值时,会进行指针元数据的更新,新指针的指针元数据继承自原指针的指针元数据。在对指针进行解引用访问内存时,首先需要对该指针的pmd进行查询,判断访问地址是否在对象的上下界范围之内以及是否满足相应的类型。

(5)影子内存技术。是指将一个程序内存状态以某种特定的方式偏移映射到一个特定的空间内,其中内存状态中包含了程序中变量存放的地址、内存是否被初始化以及其他一些变量的信息等。在对程序中的变量进行访问时,通过查询其影子空间存储的该变量的内存状态来判断访问是否合法。

3  运行时验证工具

目前,针对C语言比较成熟的动态分析工具有AddressSantizer、SoftBoundCets、Valgrind、Movec等:

(1)AddressSanitizer是谷歌公司开发的基于影子内存的技术,采用中间代码插桩实現的动态检测工具。该算法的思路是:如果想避免缓冲区溢出,只需在每块内存区域的右端(或两端)加一块红色区域,将内存的状态信息记录到影子内存中,在对内存进行操作时可以通过影子内存来判断该内存的状态。AddressSantizer可以有效检测缓冲区溢出、UAF、Double-Free、内存泄漏等问题,但却无法处理子对象越界等问题。

(2)SoftBoundCets由SoftBound和Cets构成,同样采用基于指针的技术。其中,SoftBound可以检测空间内存错误,它记录每一个指针所指对象的边界信息。而Cets可以检测部分时间内存错误,它为每个对象维护一个唯一ID,在访问该对象内存空间时进行检测。但SoftBoundCets却难以检测子对象越界、非法访问库函数以及函数的指针参数等问题。

(3)Valgrind是一款用于内存安全检测以及性能分析的框架。Memcheck是最广泛使用的重量级内存安全检测工具,能够检测大多数的内存错误,比如对未初始化内存的访问、内存访问越界等。它采用二进制代码插桩技术并结合影子内存技术,记录程序中内存字节是否具有有效的、已初始化的值,并记录地址空间是否能够被读写。在操作内存空间时,可以通过记录表来分析检测程序中的空指针访问、Double-Free等问题,但无法处理全局变量缓冲区溢出、子对象越界等问题。

(4)Movec是南京航空航天大学计算机科学与技术学院SVLAB实验室自主开发的用于C程序运行时监控、验证的自动化工具。Movec采用源代码插桩技术,利用LLVM和Clang编译器可以将用Movec语言编写的有关安全属性和监控规范的运行时检查器插入到C程序中,插桩后的程序可以兼容任何C语言编译器(例如GCC和其他特定于平台的编译器)。Movec采用扩展的基于指针的技术,每个指针变量创建并维护一个指针元数据pmd(pointer metadata),图3(a)定义了pmd的数据结构。pmd中存储了所指向对象的上下界base和bound信息,同时还存储了为每个内存对象创建并维护的状态节点snd,图3(b)定义了snd的数据结构。snd中存储了内存对象的状态stat和引用计数count。对象的状态包括heap、stack、global、static、function和invalid,而引用计数记录指向该对象的指针数。

4  实验对比分析

为了验证上述工具对C程序内存安全性错误的检测能力,本文选用Mibench标准测试集中的部分软件作为该实验的实验数据。Mibench中包含了35个用于基准测试的嵌入式应用测试集,它主要是对通用领域的计算能力进行评价,Mibench测试集在指令分布、内存行为、并行化等方面独具优势。

本文实验运行环境为:处理器选用Intel® Core™ i5-7300U CPU、四核、CPU主频2.60 GHz,内存为8 GB,操作系统为64位Ubuntu 16.04.12,编译器为gcc 5.4.0。实验结果如表1所示。

其中,Y表示可以找出程序的内存安全性错误,N表示无法找出错误,/表示程序无法正常运行。从实验结果可知,Movec可以找出程序中的大部分错误,并准确地给出了错误信息;SoftBoundCets无法检测出错误,并且对部分程序无法正常插桩运行;Valgrind仅发现了部分错误。AddressSantizer的检测能力与Movec最接近,它发现了测试集中存在的大多数错误,但是漏报了blowfish中的错误。

5  结  论

随着信息化技术的快速发展,人们的生活越来越离不开计算机软件的使用,计算机软件在给人们生活带来便利的同时也存在着安全隐患,保证软件的使用安全变得尤为重要。运行时验证技术作为轻量化的验证方法,能够有效地检测系统内存安全性方面的漏洞,得到了越来越多的应该。本文总结了几种常用的运行时验证技术,对比了几种流行的运行时验证工具并进行了实验比较。希望未来能够推出更多高精尖技术,并且可以将运行时验证技术与静态分析、模糊测试等技术相结合,进一步为软件的内存安全性检测做出贡献。

参考文献:

[1] John,Matt,Pravir. Network security with openSSL: cryptography for secure communications [M].O’Reilly Media,2002.

[2] 曹志波.OpenSSL的心脏出血漏洞 [J].电子技术与软件工程,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] 严俊琦,陈哲,黄志球.C程序内存安全的运行时检测方法研究和实现 [J].小型微型计算机系统,2017,38(10):2358-2362.

[5] 李文明,陈哲,李绪蓉,等.C程序数组越界的运行时验证技术研究与实现 [J].计算机工程与应用,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—),男,汉族,江苏连云港人,硕士研究生在读,主要研究方向:软件验证;刘一辰(1999—),男,汉族,河北邢台人,硕士研究生在读,主要研究方向:软件验证。

猜你喜欢
缓冲区指针C语言
“C语言程序设计”课程混合教学探索
郊游
基于C语言的计算机软件编程技术探究
中职C语言单片机课堂教学中的趣味性探讨
为什么表的指针都按照顺时针方向转动
计算机原理中C语言的应用价值
缓冲区溢出漏洞攻击及其对策探析
初涉缓冲区
浅析C语言指针
本期导读