# Fuzzing Error Handling Code using Context-Sensitive Software Fault Injection

**URL:** <https://forum.90sec.com/t/topic/1344>\
**Category:** 学术研究\
**Created:** [2020 年10 月 17 日 08:01 UTC](https://forum.90sec.com/t/topic/1344 "2020-10-17T08:01:58Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

作者： ![maplgebra](https://forum.90sec.com/user_avatar/forum.90sec.com/maplgebra/32/1628_2.png) [@maplgebra](https://forum.90sec.com/u/maplgebra)\
发布日期： [2020 年10 月 17 日 08:01 UTC](https://forum.90sec.com/t/topic/1344/1 "2020-10-17T08:01:58Z")

</div>

# Fuzzing Error Handling Code using Context-Sensitive Software Fault Injection

[原文地址](https://www.usenix.org/system/files/sec20-jiang.pdf)

### 0x00 Introduction

**Why should fuzzing error handling code?**

因为有一些bug存在于错误和异常处理当中，而且想要_fuzzing_覆盖错误处理，实际上是比较难。

_just a challenge,nothing else!_

**History**

_static analysis_ 容易造成很多的_false positives_(缺少运行时的信息, _reachable_?)，为了减少_false positives_,开始尝试用_fuzzing_来解决问题，简单的_input-driven_只能在一定程度上解决问题，因为存在一些异常并不依赖输入。基于直觉的\*software fault injection (SFI)\*运营而生，尝试人为的注入一些错误和异常，观察程序在运行时是否能正常的捕获这些错误和异常。

现存的一些_SFI_技术,通常采用是_context insensitive fault injection_,这种技术单纯地静态在某一些位置注入异常或者错误，可能会导致程序每次执行到该位置时都会触发错误，而导致一些其他行为，例如程序可能就直接_exit_,这样的情况下可能会错过一些_real bugs_,引用文中的例子：

 ![image-20201015104630396](https://forum.90sec.com/uploads/default/original/2X/3/309560a7de055b38c473317481dd30f7c5935059.jpeg)  
采用上下文不敏感的方法在_FuncP_中的_malloc_注入错误，将会导致在调用_FuncB_时就直接退出了，而你就会错过调用_FuncB_而导致的_double-free_。试想有选择性地在_FuncP_的_malloc_中注入错误，将会有机会捕获到这个异常（第一个疑问_when injects?_ ）。

**Bug Examples in Error Handling Code**

文中有一个例子举的很好，一下直观的说明了解决这个问题的意义：

 ![image-20201016104742594](https://forum.90sec.com/uploads/default/original/2X/c/c70cb1b180aa730e57b3b589e40eba171f13d9b2.png)

在_patch_之前很明显这是_UAF_ ,但是触发这个_UAF_必须先进入上这个_if_，文中提到必须在_av\_frame\_new\_side\_data_在申请内存失败，才会进这个_if_，这下子文章的整个主题\*“bugs in error handling code”_就变得有意义起来了，有些异常的触发极有可能不依赖于输入，文中将异常分为了两类:1) input-related error 和 2) occasional error,第一类好理解，输入相关，第二类通常为内存或者网络引发的错误。为了触发第二类异常，需要改变改变_mutate_对象，结合_Fuzzing\* 和_fault injection_可以擦出怎样的灿烂火花？

### 0x01 Basic Idea and Approach

**Basic idea**

为了实现_Fuzzing_和_fault injection_结合，文中构造了一个_error sequence_，其中包含多个_error point_，一个_error point_表示异常和错误可达且可被捕获，当使用_fault injection_可以决定每一个_error point_是否触发错误和异常，类似一个选择开关,形式化的表示如下：

ErrSeq = [ErrPt\_1,ErrPt\_2,\ldots,ErrPt\_x],ErrPt\_i=\{0,1\}

类似程序输入，同样影响着程序执行，其中核心问题变成了“ **哪些_error point_应该被触发？使其能覆盖尽可能多的异常处理代码** “，在这里插入_Fuzzing_的思想，把_mutation_作用到_error sequence_，来解决这个核心核心。

**Error Sequence Model**

基础定义：

_context insensitive error point_： ErrPt = \<ErrLoc\> (单纯用_error site_来描述)

_context sensitive error point:_ErrPt = \<ErrLoc, CallCtx\> (在_error site_的基础上，添加了运行时的调用栈来表示上下文)

其中 CallCtx = [CallInfo\_1,CallInfo\_2,\ldots,CallInfo\_x]

每一次函数调用包括_caller_和_calle_， CallInfo\_i=\<CallLoc,FuncLoc\>

**FIFUZZ**

_FIFUZZ_就是原文提出的一种针对上面问题的_context sensitive fault injection_解决方法。它由6个步骤组成：

1. _statically identifying the error sites in the source code of the tested program_ （静态地识别被测程序源码中的_error sites_）
2. _running the tested program and collecting runtime information about calling contexts of each executed error site and code coverage_ （在运行时收集_error site_执行时的上下文和覆盖率）
3. creating error sequences about executed error sites according to runtime information, and each element of such a sequence is differentiated by the location of the executed error site and the information about its calling context （利用收集到的运行时的_error point_信息，构造用于执行_mutation_和_fault inject_的错误序列，）
4. after running the program, mutating each created error sequence to generate new sequences （迭代生成新的错误序列）
5. running the tested program and injecting faults according to the mutated error sequences （继续跑输入，并且在运行时执行_fault injection_）
6. collecting runtime information, creating new error sequences and performing mutation of these error sequences again, which constructs a fuzzing loop （循环往复）

_error side_定义是指注入的_fault_可以被正常触发和捕获的位置（_code location_）

 ![image-20201017154306819](https://forum.90sec.com/uploads/default/original/2X/5/52fc42076a46581fc582d1448dce82b8993f4dd7.png)  
我从直觉上猜测的是，通过_instrument_标记_error side_，一次运行程序，得到可以被覆盖的_error side_，并不是简单的_count_，应该是有上下文敏感的_count_,通过得到这个信息，构造一个_error sequence_序列，表示应该去触发哪些_error side_。

文中整个_Fuzzing Loop_的不同于一般情况下,_mutation_的对象重点关注错误序列，还有一个问题哪些因素会去影响_mutation_？其实还是覆盖率，只是变成了_error sequence_带来的覆盖率，如果一次_error sequence_可以带来新覆盖率，就把它加到_mutation_过程的_pool_里面（还有一个优先级的东西，但是太模糊，“贡献的覆盖率”是指这个_error sequence_完整的覆盖率，还是在_prev error sequence_上增长的覆盖率，显然后一种似乎并没有什么道理）。

_Fuzzing Loop_有一个 **初始化** 的过程，因为第一次跑程序的时候，其实是没有反馈的信息的，构造了下面一个初始化的_mutation_过程，_initial error sequence_每个_error point_都是0，然后把它拆开成多个_error sequence_，其中每个_error sequence_都只有一个_error point_是1，且每个_error sequence_是唯一的。

 ![image-20201017123848006](https://forum.90sec.com/uploads/default/original/2X/a/aaaced0f431042b6d635bb29534c2b3f29b922e8.png)

后面的迭代过程基于覆盖率，_mutation_尝试将_mutate_每一个_error point_(1 \rightarrow 0 \ or\ 0 \rightarrow 1) ,整个过程并无亮点，我觉得难点在于 **怎么在动态根据上下文做到的_fault injection_？** 和 **如何做到的同时_mutate_程序输入和错误序列？**

**How to identity error side？**

这一章节是第一次接触_fault injection_的人应该最想要知道的，用它的时候，你必须保证你触发的错误是实际中存在的，不然造成的_false positive_是没有任何意义的。文中尝试通过静态分析的方法去识别_error side_,更具体一点，一个特殊的函数调用可能变成一个_error side_，其_unexpect_的返回值可能触发异常和错误处理，所以识别_error side_的粒度其实以函数为标准，具体分析过程如下：

1. _Identifying candidate error sites_ ：在大多数情况下，函数返回值为空指针或者负值时，表示一个_failure_，如果一个函数调用可能是一个_error side_,从两个方面来看：1）如果它的返回值类型为指针或者整型；2）它的返回值流到_if_上，并且检查其值是否为_NULL_或者_zero_。

2. Selecting library functions： 在大多数情况下，异常和错误产生于外部的库函数，从这个角度出发，如果定义在当前程序中的函数可能触发异常和错误，代表着它作用域下库函数可能会触发异常和错误。这个描述太过于模糊，应该建立函数的返回值和库函数（可能触发异常和错误）的联系。

3. 这一步不太容易理解，我尝试用我的理解来讲一下(可能并不是原文的意思，读者需斟酌)，第一步确定了候选的函数调用，需要进一步确定这些函数调用的目标函数返回值是否受错误和异常的影响？第二步给了一个最基础的标准，我们可以已知的库函数会引发错误和异常，通过这些库函数再去迭代标识，程序中定义的函数是否可能引发错误和异常？这两个步骤已经可以基本确定一些_error side_了，然后再这些_error side_处做一些特殊的_instrument_，如下：  

### 0x02 Self Conclusion

有意思的一篇文章，改变了_mutation_的对象，在这里我总结了几个我想要知道的问题：

1. _fault injection_是个什么东西？如何确定_error side_？
2. 文中新的_mutation_对象_error sequence_是如何构造的？
3. 如何在动态运行时根据上下文做到的_fault injection_？
4. 如何做到的同时_mutate_程序输入和错误序列？（相互协调）

这几个问题都在前面有描述了，但是4文中没有提到，_Fuzzing Loop_反馈驱动比较常规，重点在于如何连续的_Perform Software fault injection?_
