CSI-Fuzz: Full-speed Edge Tracing Using Coverage Sensitive Instrumentation

CSI-Fuzz: Full-speed Edge Tracing Using Coverage Sensitive Instrumentation

文章来自 TDSC2020

作者来自斯威本科技大学

一、论文阅读

1. Introduction

首先UnTracer指出AFL中的问题:AFL通过当前覆盖位图与全局位图决定当前测试用例是否有新的覆盖。然而绝大部分测试用例是不会产生新覆盖的,所以如果能跳过对这些测试用例的追踪将会节省大量开销。但是UnTracer是基于块插桩的,会带来边冲突,从而降低fuzz的有效性。此外,UnTracer不追踪无新覆盖的测试用例,所以fuzzer也就缺失了路径频率信息。

一种解决方案是基于边覆盖,但是静态分析检测不到间接控制流,即间接调用中的很多边检测不到。

提出了CSI-Fuzz,用Dyninst首先插桩确定边(包括条件满足转移和条件不满足转移),其次插桩间接边的源块(包括switch、call)在运行时区分这些边。

CSI-Fuzz还通过计算路径标记的哈希值设置路径标识符。

贡献:

  • 分析了现有全速Fuzzer的问题:存在边冲突,不能计算路径频率,影响fuzz有效性。
  • 设计了CSI-Fuzz,在确定边和间接边插桩,只追踪有新覆盖的测试用例。对于间接边的难题,在源块插桩。
  • 基于AFL实现了CSI-Fuzz,实验结果表明在发现边、执行速度和发现bug方面高效。
  • 开源 https://github.com/ Vul4Vendetta/csi-afl

2. Overview of CSI-Fuzz

2.1 Background of Fuzzing

UnTracer的处理方式

在这里插入图片描述

在每个基本块的开头都插入断点,覆盖后移除。但是UnTracer忽略了一些新的边,比如走过 A->B->D 和 A->C->E 这两条路径后,基本块中的断点就会被移除,当执行 A->B->E 时,就检查不到新的边BE。

2.2 Edge Instrumentation

CSI-Fuzz插桩边,并且只有在覆盖到新的边时才追踪路径。

2.3 Full-speed edge tracing

oracle:中断新的边

tracer:更新边覆盖信息

2.3.1 oracle

在每条边插入了一个 exit() 的调用,执行到新的边时就会退出,这也导致了无法知道测试用例的完整执行路径,所以会用tracer追踪完整的执行路径,并且移除oracle中对应边的桩代码(确定边),或是记录在新边上的块(间接边)

2.3.2 tracer

跟踪完整路径并更新覆盖信息。当一些bug是在发现新边后才能触发的则只有tracer能检测到,oracle检测不到。

2.3.3 crasher

检测崩溃。类似oracle,当触发崩溃并且执行新边时会调用exit()。在tracer或是oracle中触发的崩溃会在crasher中检验,如果被crasher终止执行则是新的崩溃,如果触发崩溃则是已经识别过的崩溃。

2.4 path Identifier

在这里插入图片描述

如图,当执行 A->B->C->D 时,由于AB是新边,会在其上标记m1。当执行A->B->F->H 时,由于BF是新边,会在其上标记m2。当再次执行 A->B->F->H 时则利用 m1和m2计算路径标识符。

3. Implementation of CSI-Fuzz

插入 exit(N),以一个特殊的状态码(N=66 表示确定边,N=67表示间接边)结束,以区别系统状态码。

在这里插入图片描述

  • AFL初始化
  • 获取所有的边
  • 插桩Oracle和Tracer
  • 进入循环
    • 生成测试用例
    • 如果覆盖新边
      • 将覆盖到的第一条新边标记
      • 测试用例添加到队列中
      • 调用Tracer跟踪所有的边
      • 如果执行了循环,则为种子分配更多能量
      • 利用Tracer的信息移除Oracle中的桩代码
      • 计算路径标识符
      • 更新间接边
      • 重启 fork server
3.1 Edge coverage

0:程序正常退出状态码为

1:异常退出状态码为

66,67:自定义退出状态码

在这里插入图片描述

  • 为每条确定边分配标识符,Tracer并将覆盖的边的标识符存在共享内存中,Oracle能够从共享内存中快速读取标识符并移除桩代码。
  • 对于间接边,在 call 和 jump 指令处插桩,桩代码内容为:获取所有的历史目标快集合,如果当前目标块不在集合中,则是新的边。将当前目标快加入到集合中。间接边的源块和目标块的地址都记录在文件中并在启用forks erver之前读到内存中,所以可以根据源块查找到目标块的记录。
3.2 Removal scheme

在这里插入图片描述

移除操作的实现:将桩代码的第一条指令修改为无条件跳转指令,跳转至桩代码的最后,所以桩代码不会执行。其实是伪删除,还是占空间的,只是不执行了。如下图所示(为什么不让第一条指令直接为 jmp B 呢,这样不是少一次跳转?有无大佬解答一下!)。

作者最开始的解决方案是重插桩,但是开销太大。

3.3 Path identifier

(一直没看懂这是个啥东西,但感觉就是个很简单东西,作者有意说得很复杂很高大上)

4. Evaluation of binaries

与AFL、AFLFast、UnTracer 从边发现,执行速度,bug发现三个方面对比,

4.1 Evaluation on QEMU mode

CSI-FUZZ发现了更多的边,但是边的统计方式是作者自己实现的。还发现条件满足转移的边少于条件不满足转移的边,这也说明了路径约束问题。

4.2 Evaluation on Dyninst mode

比较执行速度

4.3 Bug discovery

这部分的实验效果一般

6. Discussion and future work

可以使用其他插桩工具,当前的路径标识符方案导致可能存在路径碰撞。

二、源码分析

有时间读读源码后再更新。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值