英语原文共 16 页,剩余内容已隐藏,支付完成后下载完整资料
二进制可执行文件的跨CPU结构漏洞查找
Jannik Pewnylowast;, Behrad Garmanylowast;, Robert Gawliklowast;, Christian Rossowlowast;dagger;, Thorsten Holzlowast;
摘要:随着各种CPU体系结构下的闭源软件的广泛使用,需要识别二进制级别的关键安全漏洞以执行漏洞评估。遗憾的是,现有的漏洞查找方法存在以下缺陷:1.检测过程需要源代码;2.只针对单一架构有效(通常是x86架构);3.依赖于动态分析,而动态分析对嵌入式设备来说本质上是比较困难的。
在本文中,我们提出了这样一个系统:首先,导出已知漏洞的签名;然后,我们使用这些签名来查找已部署在不同CPU架构(如x86架构或MIPS架构)上的二进制文件中的漏洞。不同的CPU体系结构带来了一系列的挑战,例如不同的CPU模型之间指令集的不兼容性。为了解决这个问题,我们首先将二进制代码翻译为中间代码从而产生具有输入变量和输出变量的赋值公式;然后我们抽取具体的输入来观察基本块的I/O行为,从而掌握它们的语义。最后,我们使用I/O行为来查找与漏洞签名行为相似的代码部分,从而有效地检测出存在漏洞的代码部分。
我们设计并实现了一个跨CPU体系结构的可执行文件漏洞查找工具。目前我们的原型程序支持三种指令集的CPU体系结构(x86、ARM、MIPS),并且可以找到基于这些体系结构下的二进制代码中的漏洞。研究表明,无论底层的指令集是什么,我们都可以找到心脏出血(Heartbleed)漏洞。同样地,我们使用我们的方法在基于MIPS和ARM的路由器闭源固件映像中找到了后门。
一.介绍
软件漏洞仍然是当今最大的安全威胁之一。内存错误等严重的软件漏洞在开源和闭源的软件中都很普遍。国家漏洞库在2013年列出了5186个关键安全漏洞,这表明近年来的软件漏洞数量趋于稳定。然而,尽管漏洞已知,想要获知特定软件中漏洞是否存在,尤其是当程序库被更大的软件项目重用时,这仍然是一项挑战。更糟糕的是,最先进的工具在处理程序库时存在缺陷,这些库已经被部署在各种架构上。许多研究人员已经解决了在源代码级别发现漏洞的问题。专业的代码验证工具可以确保源代码的质量,并且有许多自动化的漏洞查找方法可以发现严重的安全漏洞。然而,在查找软件漏洞时,访问源代码是一个相当僵化的假设。很多知名的软件作为商业软件(如MS Office)或免费的闭源软件(如Adobe Reader或Flash)都只能以二进制的形式提供。嵌入式设备上的软件通常被称为固件,且通常是闭源的,通过不安全的语言实现,并重用第三方项目(潜在易受攻击)的代码。更重要的是,闭源软件可能被剥离符号信息,即二进制文件不包含函数名称或数据类型等符号信息。因此,我们寻求一个不需要符号信息来查找二进制级别漏洞的解决方案。仅凭这一点,在二进制级别上查找漏洞的过程比源代码级的方法更具有挑战性。
在二进制级别上查找漏洞的另一个挑战是越来越多的的软件被跨平台编译用于各种CPU体系结构。也就是说,即使某个漏洞在某一种特定的体系结构(如Intel x86架构)中是已知的,在基于相同源代码编译但应用于另一种体系结构的代码中查找漏洞也存在各种各样的困难:来自不同体系结构的二进制文件在指令集、函数偏移、函数调用约定等方面有所不同。这对于多种跨平台编译的软件来说是有问题的,例如,硬件供应商使用相同的代码库来编译适用于不同CPU体系结构的不同设备(如家庭路由器,摄像头,VoIP电话)的固件。同样,随着最近基于ARM的Windows RT部署的增加,MS Office,Adobe Reader或Flash等知名软件已经可用于多种平台和体系结构。如果跨平台编译的软件包含众所周知的脆弱的、易受攻击的库,则问题更加复杂。例如,在OpenSSL中发现心脏出血(Heartbleed)漏洞之后,在各种体系结构(x86,MIPS,ARM,PowerPC等)上运行的受影响的闭源软件列表越来越多。目前,没有一种可行的方法可以在属于不同体系结构的二进制代码中自动找到这些已知的漏洞。用户必须人工检查或者依靠供应商来检查闭源代码中的漏洞。但是,心脏出血漏洞案例再一次说明,供应商并不是特别快速地评估其产品的安全风险。通常,这将形成一个重要的时间差,这此期间可以利用关键的安全漏洞。更糟糕的是,虽然这些系统仍然被消费者和业界广泛使用,但并不能保证那些随着时间流逝而消失的供应商的硬件或固件的漏洞最终会被检查出来。
在本文中,我们解决了这个问题,并开始寻找二进制软件和多种体系结构中的漏洞。由于跨体系结构特性使漏洞搜索复杂化很多,所以我们将重点放在以下用例上:一旦知道一个漏洞,我们的目标就是识别其他二进制文件中同样脆弱的、易受攻击的部分(包括基于其他CPU体系结构编译的)。也就是说,我们使用易受攻击的函数(或其一部分)的漏洞签名来查找类似的漏洞实例。虽然这把我们的工作限制在重新查找类似的、有文档记录的漏洞实例,但是在跨体系结构编译的代码时代,这个问题已经成为了日常。例如,Heartbleed在所有CPU体系结构中都影响了来自多个供应商的大量闭源软件产品。受影响的软件列表仍在增长,并且没有自动识别易受攻击的软件版本的方法。同样,有人发现,有几个Linksys和Netgear设备在他们的固件中包含了一个后门,但是用户却不得不信任供应商指出的所有受影响的产品。我们的目标是提供一个机制来帮助这样的场景下的分析人员,分析人员定义一个漏洞签名,然后查找其他(任何体系结构的)软件二进制文件中的部分是否包含类似的漏洞。
为此,我们提出了一种使用二进制的统一表示的机制,以便我们可以比较基于不同指令集(即跨体系结构)的二进制文件。也就是说,我们首先提取二进制代码,转换为中间表示(IR)。即使在这个IR中,我们也必然会遇到缺乏符号和数据类型的二进制信息。基于这个IR代码,我们的目标是在基本块级别上掌握二进制语义。具体来说,我们为每个基本块建立赋值公式,用输入和输出变量来捕获基本块的行为。输入变量是影响输出变量的任何输入,比如CPU寄存器或内存的内容。然后我们采样随机输入变量来监视它们对输出变量的影响。这个分析得到每个赋值公式的输入/输出(I/O)对的列表,用它捕获一个基本块的实际语义。尽管类似代码的语法对于各种CPU架构(即使在中间表示中)是完全不同的,但我们可以使用这种语义来比较跨ISA的基本块。我们目前支持英特尔x86,ARM和MIPS,因为它们具有很高的流行度。
我们使用语义表示来发现其他任意软件中的漏洞签名,这些软件可能容易受到签名中定义的漏洞的影响。漏洞签名可以从已知的易受攻击的二进制程序或源代码中自动导出,也可以简单地代表整个易受攻击的功能。为了保持性能,我们使用MinHash来显着减少I/O对之间的比较次数,以找到合适的基本块匹配。最后,一旦找到基本的块匹配,我们提出一个算法,利用控制流图(CFG)扩大我们的搜索到整个漏洞签名。作为输出,我们的系统列出按照与漏洞签名类似的顺序排列的函数。这使得分析人员可以对分析的二进制文件中潜在的易受攻击的功能有一个基本的概览。
为了评估我们的方法,我们首先系统地测试我们的系统在匹配不同体系结构,不同编译器和不同优化级别的二进制文件的等效函数时的性能。评估显示,我们的系统在精确匹配功能时只有少数误报。例如,我们展示了我们的方法在基于MIPS的OpenSSL二进制中10个最接近的函数匹配中排列了OpenSSL ARM函数的61%。其次,我们评估我们的系统在各种现实世界中的使用情况,为此我们从固件中提取供应商编译的软件二进制文件,以便搜索真实世界中的漏洞。我们的系统在三个支持的体系结构中的24个测试软件程序组合中找到了21个Heartbleed漏洞。此外,我们发现了易受攻击的RouterOS固件,并在Netgear设备中确认了后门。请注意,为了强调我们的设计甚至可以容忍构建环境中的偏差,在所有这些仿真的测试中,我们都无法访问源代码,只使用了相应固件中包含的实际软件的二进制文件。
我们在某些假设下获得了这些结果,例如,二进制文件没有被混淆。然而,我们还表明,我们的系统在某种程度上可以容忍(更常见的)二进制干扰,比如编译器优化或构建环境的差异 - 除了解决大多数先前未解决的差异,比较不同架构的ISA之间的代码差异。
此外,我们的方法可以使用子函数粒度,这是漏洞搜索的关键。虽然功能匹配技术(如BLEX,BinDiff或Expose)可以找到已被克隆的函数中的漏洞,但在其他函数中找到易受攻击函数的重用部分,而不是单纯的克隆。
我们提出的系统的用途是多方面的;在这项工作中,我们专注于识别未修复的漏洞副本。然而,我们不限于在同一个程序中(即相同的二进制)这样做,甚至不要求必须是基于相同的体系结构编译的目标二进制文件。例如,那些运行不支持特定软件/设备的供应商(例如,产品超出生命周期或者供应商破产了)的公司可以独立验证,是否存在常见的漏洞。同样,如果广泛使用的库中的漏洞(如最近的Heartbleed)被人们所知,安全响应中心可以在很短的时间内找到受影响的产品。我们的概念也可以应用于在闭源程序中搜索已知的后门程序。而且我们的系统还可以有更多的用途,例如查找二进制差异、在二进制文件中搜索软件版权、或展示二进制代码中的共享代码。
综上所述,我们的四个主要贡献如下:
- 我们将ARM、x86和MIPS代码转换为统一的类似RISC的表达式,以捕获每个基本块的I/O语法。
- 我们引入一个抽样和MinHashing引擎来创建基本块及与之对应的语义摘要(这是我们进行漏洞搜索的基础)。
- 我们定义了一个度量标准来比较像子控制流图(Sub-CFG)和函数这样的代码结构,这使我们能够在任意的软件二进制文件中搜索漏洞签名。
- 我们经验性地证明了我们的方法在查找跨越体系结构的软件中多个现实存在的漏洞的可行性。
二.方法
我们现在概述一下在二进制可执行文件中进行跨体系结构漏洞查找的一般方法。我们的目标是利用代码相似性度量来找出与已知存在漏洞的代码类似的代码的位置。这里的假设是,类似的代码通常来自稍微修改过的共享代码,这通常也导致相同的漏洞被共享。我们感兴趣的是发现对安全至关重要的漏洞。但是,我们的方法支持发现许多类型的漏洞,因此我们可以互换地使用漏洞。
- 工作流程
我们使用一个漏洞签名,即一个类似某个漏洞特定实例的二进制代码,来发现另一个二进制程序(目标程序)中可能存在的漏洞。为此,我们首先得到一个漏洞签名(第II-B节)。然后,我们将漏洞签名和目标程序都转换成中间表示(第II-C节),并构建紧凑的基本块式语义散列(第II-D节)。所有这些转换对于漏洞签名和目标程序都是一次性的过程。
图1说明了指令ldrb(ARM),lbu(MIPS)和lodsb(x86)的这一过程。首先,我们将这些汇编指令转换为中间表示,从而生成一个赋值公式列表,我们将其表示为易于解析的S表达式(符号表达式)。分配公式详细说明了输出变量如何受其输入影响。例如,x86情况下的第一行表示ESI指向的地址的前8位存储在寄存器AL中。对于每个公式,输入的数量是不同的(例如,没有终端的输入,AL,v0和R3变量,或ESI变量的两个输入)。接下来,使用随机的具体输入值(虚线框),我们对这些公式的输入/输出行为进行抽样(我们只说明了对第一个公式的抽样)。例如,在ESI的x86公式中,具体输入(5,1)产生6的输出。最后一步,我们在I/O对上构建语义哈希,这使得我们可以有效地比较I/O基本块的行为。
在漏洞查找阶段,我们使用转换后的漏洞签名(即其表示形式为分配公式图)来识别类似转换的二进制文件中的漏洞。也就是说,我们在目标程序中寻找可能的匹配候选项目(第II-E部分)。对于每个这样的候选对,我们应用CFG驱动的、贪婪的、但局部最优的扩展算法。该算法扩展了与漏洞签名以及目标程序中的附加基本块的初始匹配(第II-F部分)。该算法然后计算漏洞签名和目标程序之间的相似性,返回按照与签名的相似性排序的代码位置的列表。下面,我们将更详细地解释这些步骤。
- 漏洞签名
漏洞签名就像正常的二进制代码一样:它由基本块和这些基本块之间可能的控制流转换组成。因此,原则上任何基本块都可以选作漏洞签名。例如,漏洞签名可能代表整个存在漏洞的功能,限制了人工更详细定义漏洞签名的工作。但是,我们系统的用户应该将漏洞签名更改为较小的代码部分,这些代码部分仅涵盖漏洞及其相关的上下文。请注意,我们的方法只需要一个有区别的代码段,通常情况下,发生漏洞的上下文非常独特,我们的方法完全独立于漏洞类型。目前我们已经成功地评估了缓冲区溢出、逻辑错误和软件后门。
然而,很难估计签名大小如何影响总体的结果。一个对脆弱性影响大且对于其上下文的区分必不可少的非特征基本块可能会改善结果,而对脆弱性影响小的特征基本块可能会导致误报。
虽然我们的目标是在无需访问源代码的情况下查找二进制文件中的漏洞,但是我们并不一定要限制自己仅在得到漏洞签名时才使用二进制信息。例如,考虑一个典型的开源软件中的漏洞被公开的情况。这通常意味着我们可以利用漏洞的代码块来定义漏洞签名。因此,我们可以使用调试信息来自动查找到与存在漏洞的功能部件相对应的基本块,从而几乎不需要手动操作即可有效地导出漏洞签名。
请注意,即使可用的源代码可用,如果存在漏洞的代码成为闭源程序的一部分,这时仍然无法使用基于源代码的漏洞查找技术。在实践中,有问题的开源代码被重新用于闭源程序,这是只有二进制表示的文件可用。例如,开源软件项目BusyBox和OpenSSL中的漏洞成为许多闭源固件镜像的一部分。
- 统一的跨体系结构指令集
显然,x86,ARM和MIPS等体系结构的指令集有很大差异。除了指令集以外,调用约定,通用和专用CPU寄存器集以及内存访问策略(例如R
全文共25699字,剩余内容已隐藏,支付完成后下载完整资料
资料编号:[13782],资料为PDF文档或Word文档,PDF文档可免费转换为Word
以上是毕业论文外文翻译,课题毕业论文、任务书、文献综述、开题报告、程序设计、图纸设计等资料可联系客服协助查找。