热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

从UEFI模块的动态仿真到覆盖率导向的UEFI固件模糊测试(二)

 在本文中,我们将为读者详细介绍覆盖率导向的UEFI固件模糊测试技术。在本文上一部分中,我们对UEFI的攻击面进行了全面的分析,接下来,我们将为读者介绍内存池Sanitizer。 内存池Sanitiz

 

在本文中,我们将为读者详细介绍覆盖率导向的UEFI固件模糊测试技术。

在本文上一部分中,我们对UEFI的攻击面进行了全面的分析,接下来,我们将为读者介绍内存池Sanitizer。

 

内存池Sanitizer

基于突变的模糊测试技术,主要是由下面一组观察结果驱动的:


  1. 有效输入发生突变后可能会变成无效输入;

  2. 如果目标没有对这些无效输入进行正确处理,可能会触发内存破坏问题;

  3. 内存破坏问题通常表现为崩溃。

图6 基于突变的模糊测试技术示意图

就其本身而言,这些假设是相当简单化的,而且并不总是成立的。作为一个例子,让我们考虑一个简单的,基于堆栈的缓冲区溢出漏洞。如果溢出不够“深”,很可能它不会覆盖保存的返回地址,因此不会表现为崩溃。即便如此,也有两个原因使侦测这些情况变得极其重要:


  1. 首先,如果运气好的话,fuzzer可能会发现其他一些突变,从而帮助将“deep”“浅”溢出转换为“深”溢出漏洞。

  2. 其次,如果构建得当,即使是“浅”溢出漏洞也可能对攻击者非常有用。例如,在堆栈溢出的情况下,我们可以覆盖其他局部变量的值,从而影响程序的执行。

为了帮助fuzzer将这些情况与实际崩溃一样对待,我们需要sanitizer助一臂之力。简单地说,sanitizer是一个非常笼统的术语,用来表示任何对执行中的代码实施更严格检查的检测策略。如果这些检查中有一项在运行时失败了,sanitizer就会故意使进程崩溃,从而通知fuzzer刚刚发现了一个潜在易受攻击的路径。

sanitizer的应用并不只限于模糊测试技术。事实上,大多数sanitizer都被开发人员用到。通过将这些工具融入到他们的工作流程中,开发人员可以快速暴露各种编程错误,否则这些编程错误可能会在很长一段时间内无法被发现。这些sanitizer的著名例子包括Google的sanitizer套件(AddressSanitizer、MemorySanitizer、LeakSanitizer等)、微软的ApplicationVerifier以及老牌的、深受欢迎的Valgrind。

对于我们的UEFI NVRAM fuzzer来说,我们主要是对AllocatePool()和FreePool()等内存池服务进行“消毒处理(sanitization)”。和其他动态内存分配器一样,UEFI内存池也容易受到一些滥用模式的影响,例如:


  1. 内存池上溢/下溢(Pool overflow/underflow):一段行为不当的代码将数据写到了给定内存池缓冲区的边界之外,从而破坏相邻的内存。

  2. 越界访问(Out-of-bounds access):试图读取超出给定内存池缓冲区边界的数据。

  3. 双重释放(Double-frees):在这种情况下,同一个内存池块被释放两次。

  4. 无效释放(Invalid frees):试图释放一些本来就不属于内存池的内存。根据特定的内存池的实现方式,这种模式也可能导致内存破坏。

  5. 释放后使用(Use after free):在内存池块被释放后,一段代码又访问了它。

在开发sanitizer的过程中,我们从包含类似功能的BaseSAFE项目中获得了一些灵感,并借鉴了一些巧妙的想法。我们恳请您查看他们的项目,并阅读附带的论文(尤其是4.7节–Drop-In Heap Sanitizer)。本质上将,内存池sanitizerhook了许多重要的内存池服务,如allocate()和free(),并对它们进行如下处理:


  1. allocate(size):对于每一个内存分配请求,sanitizer首先会增加8个字节的辅助数据。也就是说,如果用户请求了X个字节,那么实际的内存块的大小将是X+8。接下来,要返回给调用者的指针将被移位4个字节。这样就给我们留下了两个“填充”区域,每个区域长4个字节。借助于Qiling框架提供的内存API,我们可以使这些“填充”区域变成既不可读也不可写的内存区域。因此,任何访问这些“填充”区域的尝试都会被捕获并导致异常。通过这个方案,我们可以检测到大多数的内存池上溢和下溢的情况,甚至包括是那些off-by-one漏洞所致、通常很难发现的内存池上溢和下溢情况。

图7 一个精心构造的内存池块,用于检测内存池上溢/下溢。


  1. free(ptr):当一个内存块被释放时,我们首先将用户可访问的部分(从P+4开始,到P+4+size结束)标记为不可访问。因此,任何试图在释放内存块后访问它的行为都会被检测到。此外,与现实世界中的堆不同(它应该考虑到性能和内存需求问题),我们必须确保不会再次分配这个内存块。这样我们就省去了维护空闲列表和管理不同内存块状态之间转换的麻烦。

图8 一个内存池中的内存块被释放后的情况。通过让用户可见的部分也无法访问,我们就能“捕获”所有针对该内存块的UAF问题

我们要解决的另一个重大挑战是源于库函数的溢出漏洞和其他漏洞。根据设计,Unicorn引擎支持的所有hook类型只能由模拟的CPU指令触发,而不是由框架本身触发。反过来,这也会带来一些有趣而又有悖常理的东西。

作为一个具体的例子,让我们考虑一个简单的UEFI应用程序,它调用一个引导服务,如CopyMem(),其中一个缓冲区是一个标记为不可访问的内存区域。现在,假设CopyMem()的实现是由应用程序自己给出的,就像编译器选择内联这个函数一样。这种情况显然会在运行时引发异常,所以没有什么特殊的地方。

现在,考虑一下CopyMem()的实现从来没有在二进制层面明确给出的情况。取而代之的是,对CopyMem()函数的调用被拦截,并在Qiling之上模拟其效果。这样的实现可能会利用框架特有的API来直接写入内存,从而绕过为目标内存缓冲区安装的任何hook。

图9 CopyMem()服务的可能实现。通过直接写入内存,这样的实现不会触发安插在目标缓冲区上的任何hook。

为了纠正这种情况,我们扩展了sanitizer,以利用金丝雀值(canary values)。总的来说,在内存池缓冲区的一部分被标记为不可访问之前,它会被一些已知的魔术值(默认情况下为0xCD)所填充。然后,在执行结束时,sanitizer会遍历所有这些块,并验证它们没有以任何方式被破坏。使用这种技术时,我们只能在事后检查缓冲区溢出漏洞(即我们不会立即得到通知),但这比让这些漏洞逃之夭夭要好得多。

图10 一个释放的内存池块,其中填充了金丝雀值。金丝雀值可以帮助我们检测源自被仿真的库函数的漏洞。

然而,另一种缓解这个问题的方法源于这样一个事实,即CopyMem()和SetMem()都可以通过手工编写汇编代码的方式来轻松实现。虽然memcpy()和memset()的顶级实现确实不简单,但只需少量的x86指令就可以构造出一个简陋的、非性能导向的版本。正因为如此,一个可能的解决方案是为这些服务引入汇编版本,将它们编译并注入到仿真环境中,然后强制所有CopyMem()和SetMem()的调用方都使用它们。这样一来,所有的字节传输都变成了Unicorn引擎支持的实际CPU指令,因此,它们就很容易被各种类型的hook所拦截。

图11 SetMem()的手写汇编实现。虽然它很简陋,性能也不高,但它完全实现了应有的功能——这才是最重要的。

 

小结

在本文中,我们为读者介绍了内存池Sanitizer,接下来,我们将为读者演示如何检测未初始化的内存泄露。

(未完待续)


推荐阅读
  • C#设计模式之八装饰模式(Decorator Pattern)【结构型】
    一、引言今天我们要讲【结构型】设计模式的第三个模式,该模式是【装饰模式】,英文名称:DecoratorPattern。我第一次看到这个名称想到的是另外一个词语“装修”,我就说说我对“装修”的理 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • Java在运行已编译完成的类时,是通过java虚拟机来装载和执行的,java虚拟机通过操作系统命令JAVA_HOMEbinjava–option来启 ... [详细]
  • 海马s5近光灯能否直接更换为H7?
    本文主要介绍了海马s5车型的近光灯是否可以直接更换为H7灯泡,并提供了完整的教程下载地址。此外,还详细讲解了DSP功能函数中的数据拷贝、数据填充和浮点数转换为定点数的相关内容。 ... [详细]
  • CentOS7.8下编译muduo库找不到Boost库报错的解决方法
    本文介绍了在CentOS7.8下编译muduo库时出现找不到Boost库报错的问题,并提供了解决方法。文章详细介绍了从Github上下载muduo和muduo-tutorial源代码的步骤,并指导如何编译muduo库。最后,作者提供了陈硕老师的Github链接和muduo库的简介。 ... [详细]
  • 本文介绍了在go语言中利用(*interface{})(nil)传递参数类型的原理及应用。通过分析Martini框架中的injector类型的声明,解释了values映射表的作用以及parent Injector的含义。同时,讨论了该技术在实际开发中的应用场景。 ... [详细]
  • 详解 Python 的二元算术运算,为什么说减法只是语法糖?[Python常见问题]
    原题|UnravellingbinaryarithmeticoperationsinPython作者|BrettCannon译者|豌豆花下猫(“Python猫 ... [详细]
  • AndroidStudio 2.3迁移3.0踩坑之——Could not resolve project
    参见StackOverflow如果你的项目引用了自己的库,在迁移到3.0后,编译就会报错。Error:Failedtoresolve:Couldnotresolveproject: ... [详细]
  • 2018年人工智能大数据的爆发,学Java还是Python?
    本文介绍了2018年人工智能大数据的爆发以及学习Java和Python的相关知识。在人工智能和大数据时代,Java和Python这两门编程语言都很优秀且火爆。选择学习哪门语言要根据个人兴趣爱好来决定。Python是一门拥有简洁语法的高级编程语言,容易上手。其特色之一是强制使用空白符作为语句缩进,使得新手可以快速上手。目前,Python在人工智能领域有着广泛的应用。如果对Java、Python或大数据感兴趣,欢迎加入qq群458345782。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 本文介绍了2020年计算机二级MSOffice的选择习题及答案,详细解析了操作系统的五大功能模块,包括处理器管理、作业管理、存储器管理、设备管理和文件管理。同时,还解答了算法的有穷性的含义。 ... [详细]
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • 在2022年,随着信息化时代的发展,手机市场上出现了越来越多的机型选择。如何挑选一部适合自己的手机成为了许多人的困扰。本文提供了一些配置及性价比较高的手机推荐,并总结了选择手机时需要考虑的因素,如性能、屏幕素质、拍照水平、充电续航、颜值质感等。不同人的需求不同,因此在预算范围内找到适合自己的手机才是最重要的。通过本文的指南和技巧,希望能够帮助读者节省选购手机的时间。 ... [详细]
author-avatar
手机用户2502923261
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有