导语:在防守方和攻击方之间,挖洞是博弈过程中很重要的一个部分。攻击者只需要发现一个漏洞进行攻击,而防守方需要找到漏洞所在的位置,并且将所有系统的漏洞进行修补。因此,防守方需要比攻击方拥有更有效的工具才能在这次博弈中获得胜利。

找系统漏洞最普遍的方式就是模糊测试,通过生成器将随机产生的字符串发送到系统当中,以便发现其中的错误。但是,没有回显的模糊测试并不是一个很有效的方式去发现漏洞,因为没有一些提示去发现这些漏洞,以及大部分的测试都是徒劳无功。防御方在这一方面就有一定的优势了,因为可以看到源码,以及可以看到在攻击过程中后台显示的内容,挖洞过程中也可以通过静态分析,以及设置断点方法进行更有效的测试。崩溃和漏洞都可以回溯到源代码中,以便于更容易的修复。

Intel的一个名为”Excite”项目就是将符号执行,模糊测试,白盒审计结合起来发现敏感代码中漏洞。通过将符号执行以及白盒审计,Excite已经实现了比较好的效果,并且比单独使用其中一种方式更有效。Excite在自动发现BIOS漏洞方面很强大。这个工具是从2015年进行开发的,并且已经在公开的会议上进行了介绍,比如:WOOT2015ZeroNights 2016

Excite中集成了动态符号的选择以及模糊测试的生成器。它使用了WindRiver”Simics”虚拟平台用来转存开发平台的数据以及代码,并且在检查安全问题以及衡量测量范围时进行重复测试。Excite是在三种技术结合下运行的:

excite-intersection.png

测试目标:系统管理模式(SMM)

此次测试目标是分析在统一可拓展固件接口(UEFI)BIOS中实现系统中断管理的程序(SMI)分析。基于BIOS的攻击在近几年数量剧增,并且Intel通过进行编码,安全设计指南,代码审计,以及静态代码分析进行对BIOS安全的加固。Excite是维护BIOS安全技术之一。

SMM是Intel执行过程中具有最高优先权的程序,因此它是存放rookit的最佳场所。目前操作系统是不知道SMM正在运行,并且不能阻止或者防护SMM代码执行的。因此,SMM的安全是至关重要的。

SMM的数据以及代码存放在系统管理寄存器(SMRAM),SMRAM是系统RAM的一部分,它是专门为SMM服务的,并且受处理器中的安全机制保护。SMM是当特定事件触发时通过系统中断管理程序(SMI)进行的调用的。

当SMI发生时,一个通信缓冲区会用于内部与外部进行数据通信。通信缓冲区存储在常规的RAM当中,并且假设已经暴露在攻击者放攻击范围内。因此,SMI应该非常仔细的检查以及确认在通信缓冲区中的数据,为了防止一些流量能够帮助攻击者。

SMI处理程序可以访问机器上任意内存,如果他们被入侵就会有特别大的破坏能力。一个UEFI BIOS启动应该定义SMI应该访问的内存表,其余的内存都不应该被访问。

SMM是UEFI BIOS的一部分,它不是一个静态组件。相反在引导过程中,BIOS会将SMM驱动和其相关联的SMI程序加载到SMRAM当中。一旦启动完毕,处理器中设定锁定位来锁定SMRAM。

SMM中应用Excite

Excite当前测试的是UEFI SMI处理程序中两个严重的问题:调用SMRAM外的内存函数,可以访问允许的内存区域。为了发现这些问题,Excite工具将如下几个工具和步骤进行了集成,如下:

excite-flow.png

UEFI BIOS的构建是采用标准化的结构,所以不需要特殊的标志未或者变量来启动excite。一旦BIOS构建完成,它就会加载Simics虚拟平台。通过使用Simics,UEFI代码就可以像在实体机一样在虚拟平台进行使用。
SMM驱动程序初始化之后,SMRAM锁定之前,Simics将在SMRAM中的一张图片进行存储,用于测试符号执行。这种方法的优点是存储下来的数据包含了SMM模块初始化的状态,那么就不需要重新开发复杂的SMM模型。

下一步就是生成测试线程。在这个阶段,Excite会扫描SMRAM,进而发现所有寄存器以及所有处理程序。对于每个处理程序,就会有一个测试线程调用CRETE符号执行引擎。测试线程映射SMRAM到CRETE工作的应用程序的内存。CRETE是直接在二进制中工作的,所以不需要关于源的东西。用作进入SMI的通信缓冲区会被标志成一个符号,并且作为符号执行的起始点。

CRETE会将每一个SMI处理程序的行为进行扫描,以及对发现的每个路径都生成一个测试线程。这样就可以简单的为每个处理程序提供数万个测试线程。每个生成的测试用例都是通信缓冲区中的一组具体内容。

生成的测试线程然后启动Simics。作为测试线程的一部分,这个过程会收集代码,然后进行覆盖,并且检测是不是发现了非法的访问内存或者非法调用。

符号分析以及测试生成

符号执行是系统的发现软件路径的一个很强大的技术。他不是通过具体的输入,而是通过带有符号的输入,进行运行程序。在执行过程中,符号执行引擎在符号输入是加一些约束。当遇到输入符号不同,产生分支的情况下,它会分别生成两个不同的符号值进行测试。比如一个测试值为真,则另外一个测试值使用的就是假。在探索程序路径结束时,符号生成引擎就会将约束发送到约束求解器,然后接下来的输入就会遵循计算的路径进行运行。当最后程序的路径全部被发现时,或者用户设置了终止条件时,程序运行结束。

Excite使用CRETE作为符号执行引擎。CRETE是波特兰州立大学开发的一个开源项目。Excite调用了CRETE提供的函数,比如”crete_make_symbolic(var,
size,
name)”是为了标记一个函数输入,或者特定内存进行符号执行。然后CRETE就会从起始点开始探索内存,并且为其生成一个测试线程,线程中会包括这个函数中输入的所有情况。

CRETE在执行过程中可能会导致SMI处理程序崩溃。所以这些标记会帮助我们在Simics执行过程中发现问题,以及漏洞。

如何在Simics虚拟平台中使用Excite

执行Excite的先决条件就是使用一个虚拟平台。因为我们需要很准确的检查SMRAM,并且同样要求我们能够跳转到内存的任意位置,所以使用硬件条件几乎不可能。而且硬件也不会提供给我们工具让我们使用。

Simics虚拟平台在执行Excite过程中,作用如下:

1. 启动UEFI过程中得到SMRAM中的内容,通过Simics检测端点保存目标机器的内存,寄存器,以及设备状态的全部内容。
2. 一旦启动完毕,就回访问SMRAM,为Excite提供转储服务。
3. 运行测试线程。

测试线程通过加载Simics存储的内容,以便恢复之前的准确状态。然后,按照测试线程中的规定设置处理器状态以及内存状态。设置内容包括将通信缓冲区的内容复制到内存当中,以及在寄存器中设置指针和大小值。

处理器核心的指令指针(RIP)被初始化为代码段的起始位置,以便于直接跳转到SMI处理程序当中。这里并不需要让SMI产生中断去运行代码,因为SMI发出的中断是调用了一定程序,其效果是和这里的初始化相同的。假设SMI调度器是可靠的,那么测试线程就可以以更简单的方式去运行了。

由于测试线程是在Simics上面工作的,一个名为exect的模块处于活跃的状态,它会对整个程序运行进行监控,查看SMRAM是否进行非法调用或者访问非法内存区域。因此,exect会第一时间检测到异常行为,并且报告给UEFI开发者们。

另外,exect被用作收集代码覆盖信息。这个过程不具有侵入性,因为这不会改变目标系统的任何代码。通过使用代码覆盖,这就为我们了解正在测试的SMI代码量,以及测试的覆盖范围是否增加了。

模糊测试

为了进一步增添覆盖范围,模糊测试技术将被用在这里。模糊测试将通信缓冲区的输入进行替换,然后将这些测试线程运行在Simics上面。这个过程中,只有提高代码覆盖率的还在进行。其余的线程都被终止。

模糊测试能够找到更多进行测试的地方是因为符号执行有很多限制,并且实际上不会生成所有的测试线程。符号执行也仅仅是在通信缓冲区进行工作的,但是在程序执行中还有一部分没有在通信缓冲区中,所以符号执行不会探索到这里。

下方图片就举了一个简单的例子去展示如何将模糊测试以及符号执行进行结合:

fuzzing_coding_sample.png

代码覆盖率结果

如果我们需要看看多少SMI代码正在被测试,我们就可以看到结合了符号执行和模糊测试之后,代码覆盖率比使用其中一个提高了很多。通过与黑盒测试相比,我们可以注意到白盒测试有不错的效果。

excite-coverage-table.png

漏洞是如何报告的?

当漏洞找到之后,因为UEFI代码正在被测试,所以这些漏洞变得很具体。漏洞会直接在代码中指出。与静态分析不同的是,这里往往会产生一个很模糊的错误,我们需要结合漏洞报告以及代码段去寻找这个漏洞。

一个堆栈溢出就说明了存在非法访问或者非法调用,根据这一点我们就可以对这个问题进行查找并修复。SMRAM转存二进制到C语言的汇编代码是采用了Windows驱动工具包中的”dbh”工具。

通过访问源码,报告中就可以直接指出代码中哪存在问题,在调用栈的附近:

excite-issue-report.png

在虚拟平台上进行调试这一问题比在硬件中简单许多。虚拟平台中不受诸多锁定的限制,就像硬件中会锁定RAM。在虚拟平台中,你可以在系统不知情的情况下查看系统任何地方。这也就意味着在系统中运行的恶意软件也不会察觉到自己正在被扫描,所以可以比较容易发现漏洞。使用像重放执行这样的技术就可以观察到系统中任何行为。关于使用虚拟平台对网络安全中的作用,可以看这篇文章

使用并行测试减少执行时间

大量的测试线程需要太多时间,所以我们采用了并行测试缩短了程序运行的时间。20000个测试线程,从生成,在Simics执行,到进行模糊测试平均每个处理程序需要10个小时。10个SMI处理程序需要测试,那么所有的时间大概就是100个小时也就是大概4天时间。但是每个SMI处理程序可以并行被检查,而且许多测试线程也试可以并行工作的。使用并行测试,总的测试时间可以缩短20倍,也就是4个多小时就能完成。

下方图片就展示了并行工作:

excite-parallel-execution.png

源链接

Hacking more

...