意大利安全研究人员是否都有《教父》的气质?我们不知道,但是至少今天要给大家推荐的这篇论文HEAPSTER: Analyzing the Security of Dynamic Allocators for Monolithic Firmware Images的一作是否跟加勒比海盗有点神似?
这篇论文我们在之前的IEEE S&P云端报道系列中提到过,它的思路和我们的Goshawk论文有点类似——通过识别内存管理函数来帮助代码分析引擎检测内存破坏漏洞。作者设计的HEAPSTER
工具,分析对象是我们相对比较陌生的monolithic firmware image——那种不依赖于什么嵌入式操作系统,直接把生产代码一股脑编译成单一binary的固件image。作者首先设计了针对monolithic firmware image的内存管理函数识别技术,然后结合USENIX Security 2018上的论文HEAPHOPPER: Bringing Bounded Model Checking to Heap Implementation Security中提出的HEAPHOPPER
系统,完成了对固件中heap内存管理的安全分析。
在整个工作中,比较重要的部分是如何识别monolithic firmware image中的内存管理函数,除了一些基本的固件加载、固件二进制代码反汇编和函数识别工作,HEAPSTER
的基本思路是首先发现basic function,即函数参数中至少有一个是内存地址、同时内部实现中对这个地址上的内存数据进行过操作的函数;在这种启发式的方法基础上,HEAPSTER
进一步开展数据流分析,追踪内存地址的source,尝试分析找到allocator;最后,HEAPSTER
还会追踪内存对象,尝试找到deallocator,并以这些收集到的信息为重要的参考,完成后续的安全分析。
由于缺乏符号信息,HEAPSTER
识别allocator的核心技术在于代码模拟执行。当HEAPSTER
发现一个可能的内存指针,并一路追溯回到其源头时,会对产生这个指针的源函数进行模拟符号执行,如果该源函数确实是一个allocator,那么执行结果可以反映出其特点——每次执行,均会返回一个不一样的内存地址(作为动态分配的内存buffer);同时,作者提出了一个非常有趣的识别deallocator的方法:假设前面步骤已经发现了一个allocator,那么模拟执行n次这个allocator,会分配出来n个不同的内存对象,然后把这n个内存对象丢给一个可能的deallocator(去模拟符号执行),如果被测试的函数确实是一个deallocator,那么它应该会把n个内存对象都回收掉,然后再一次执行allocator,如果此时分配出的内存对象和刚刚被回收的n个对象中的某一个相同(即拥有相同的内存地址),那么就可以确认这个被测试的函数的deallocator身份。在实际中,作者发现这个n的取值只要为3,即可很好地完成测试。
作者在实验中针对两组firmware进行了分析,一组是已经建立了ground truth的20个image(从已有研究中拿到),另一组则是794个没有ground truth的image,
实验结果表明,作者那个启发式的allocator/deallocator识别效果还挺好的(确实需要diss一下某些审稿人,一看到启发式方法就觉得不行,你行你上啊!)同时在某些image的二进制代码符号执行中需要做一些patch(具体是什么没有细看,应该是处理一些corner case,这种实事求是的科学态度小编觉得也很值得称赞,不是所有的工作都能很完美地开展各种binary code analysis的,我们要认识世界的复杂性,允许边边角角的问题存在)
论文的测试结果表明,在这些image中,很大一部分比例(对于第一组image是20/20,对于第二组iamge是340/794)的内存管理存在如下四种问题(实际上是在说,这些内存管理函数没有做防护,如果存在漏洞就会被攻击者利用,但是具体有没有漏洞,另说):
论文中使用的到相关固件:
https://github.com/ucsb-seclab/monolithic-firmware-collection
GitHub代码:
https://github.com/ucsb-seclab/heapster
论文PDF:
https://seclab.cs.ucsb.edu/files/publications/gritti_heapster_22.pdf