Group of Software Security In Progress

GoSSIP @ LoCCS.Shanghai Jiao Tong University

Who Allocated My Memory? Detecting Custom Memory Allocators in C Binaries

论文下载

这篇文章发表在2013 WCRE上,作者是Vrije Universiteit Amsterdam的Xi Chen。

  • 在识别数据结构的工作中,很重要的一步是识别内存分配函数,然后才能用污点分析等技巧来分析数据结构。库函数中的内存分配函数比较容易识别,可以直接通过函数导出表识别。但是,许多大型软件中,开发者会自己实现一套内部的内存分配器,这就给内存分配函数的识别带来了困难。
  • 这篇文章的目的是要在没有符号信息的二进制程序中,识别出这些开发者自己实现的内存分配函数。
  • 作者先总结了malloc,free,和realloc函数的一些特征用以识别相对应的函数,然后基于此,提出了一套叫Membrush的系统来识别内存分配函数。

内存分配函数特征分析

  • c_malloc:
    • (A1)c_malloc函数会返回一个指向堆的指针p;
    • (A2)程序会向返回的指针p,或根据p计算出的地址,进行内存写操作;
    • (A3)除非c_malloc函数在返回前初始化了内存块,程序应该先写再读这块内存;
    • (A4)c_malloc不能在调用c_free之前多次返回同一个对象;
    • (A5)c_malloc不仅要检查从一个内部函数返回的指针,还要进行一些运算来生成新的对象指针。
  • c_free:
    • (D1)内存分配器会记录内存中哪些是已经分配了的,哪些是未分配的;
    • (D2)除非有bug,c_free释放的内存不会再被访问;
    • (D3)c_free释放的内存可能会再被c_malloc使用;
    • (D4)c_free函数和c_malloc函数有共用的metadata。
  • c_realloc:
    • (R1)c_realloc返回一个指向堆的指针p;
    • (R2)c_realloc会访问c_malloc使用的metadata;
    • (R3)程序会用p,或通过p计算的地址访问内存,而且在读之前会先写这块内存;
    • (R4)一旦c_realloc改变了一个内存块的大小,之后相同的操作不会堆内存进行任何操作;
    • (R5)c_realloc会保留原来内存块里的数据;
    • (R6)c_realloc结合了c_malloc和c_free的特性。当释放一个内存块之后,程序不会再访问这块内存;
    • (R7)c_realloc释放了一个内存块之后,c_malloc可以再次分配这块内存。

Membrush Overview

Membrush用Pin做动态插桩,使用上述的特征来识别内存分配函数。Membrush的输入是没有符号表的二进制程序(1)以及这个程序的输入(2)。(3)通过函数调用栈识别上下文关系。(4)识别函数内局部变量的调用情况。(5)是数据流分析。(6)用来跟踪函数返回指针的使用情况。(7)(8)(9)(10)是检测模块。

Fig

(1)C_malloc函数识别

Fig

Membrush先通过返回值是否符合A1,对函数进行筛选。然后用污点跟踪筛选出满足A2和A3的函数。检测A4时,Membrush插入一个call loop反复调用这个函数,来看是否满足要求。反复调用时,需要对栈帧以及寄存器的值进行保存,然后再调用同一个函数。

(2)C_free函数识别

Fig

Membrush会跟踪c_malloc返回的指针来检测是否满足D1条件。通过跟踪调用该函数后,指针的使用情况来检测D2和D3是否满足。

(3)C_realloc函数识别

Fig

R1,R2,R3的检查类似与c_malloc。检查是否满足R4时同样需要多次调用这个函数确保同样的请求不会堆内存块产生新的操作。检查R5时,Membrush会检查是否存在从c_malloc分配出的内存到一块新内存块的连续内存拷贝操作,若存在则通过检查。R6的检查类似于c_free。

Evaluation

(1) 内存分配函数识别准确率

Fig

对不同类型的内存分配器函数的识别效果

Fig

各项标准对函数筛选效果的评估

Fig

将Membrush与Howard(数据结构识别)结合进行数据结构识别准确率的评估

Fig