推广 热搜: 行业  设备  机械    系统  教师    参数  经纪  蒸汽 

fuzz系列之libfuzzer

   日期:2024-11-10     移动:http://sjzytwl.xhstdz.com/mobile/quote/71697.html

本文以 libfuzzer-workshop 为基础 介绍 libFuzzer 的使用。

fuzz系列之libfuzzer

libFuzzer 是一个,, 的 引擎,是 项目的一部分。

和 要被测试的库 链接在一起,通过一个模糊测试入口点(目标函数),把测试用例喂给要被测试的库。

会跟踪哪些代码区域已经测试过,然后在输入数据的语料库上进行变异,来使代码覆盖率最大化。代码覆盖率的信息由 的 插桩提供。

的种类

  • :通过对目标协议或文件格式建模的方法,从零开始产生测试用例,没有先前的状态
  • :基于一些规则,从已有的数据样本或存在的状态变异而来
  • :包含了上述两种,同时会根据代码覆盖率的回馈进行变异。

target (被 fuzz 的目标)

基本上所有的程序的主要功能都是对一些 字节序列 进行操作, 就是基于这一个事实( 生成 随机的 字节序列 ,扔给 待 的程序,然后检测是否有异常出现) 所以在 看来, 的目标 其实就是一个 以 字节序列 为输入的 函数

fuzzer

一个 生成 测试用例, 交给目标程序测试,然后检测程序是否出现异常 的程序

corpus(语料库)

给目标程序的各种各样的输入

以图片处理程序为例:

语料库就是各种各样的图片文件,这些图片文件可以是正常图片也可以不是。

传统的 大多通过对已有的样本 按照预先设置好的规则 进行变异产生测试用例,然后喂给 目标程序同时监控目标程序的运行状态。

这类 有很多,比如: , 等

本节使用 作为 变异样本生成引擎,对 pdfium 进行 。

相关文件位于


是一个 测试用例生成引擎,它是通过对已有的样本进行变异来生成新的测试用例。

首先看看 测试样本的生成

generate_testcases.py


就是调用 ,然后随机选取 目录中的文件名作为参数,传递给 进行变异,然后把生成的测试用例,放到 。

这样测试样本就生成好了,下面看看 用于 fuzz 的脚本

run_fuzzing.py


就是不断调用 程序 处理刚刚生成的测试用例,根据执行的输出结果中 是否有 和 来判断是否触发了漏洞。

: 由于用于变异样本的选取 和 样本的变异方式是随机的,可能需要重复多次 样本生成 && fuzz 才能找到

写个 脚本,不断重复即可


本节相关资源文件位于:


首先先把 安装一下

首先


然后进入 , 执行 安装好 .

然后进入 ,执行 编译好 。

如果编译成功,会生成

这一节中主要使用 对 中实现的几个有漏洞的 函数 进行


这个函数有两个参数,第一个参数 是 类型的,说明 应该是指向了一个缓冲区, 应该是缓冲区的大小,如果 , 会访问 , 越界访问了。

进行 fuzz 的第一步是 实现一个 入口点,用来接收 libFuzzer 生成的 测试用例(比特序列)。

示例


对于 有一些要注意的

  • 是 生成的 测试数据, 是数据的长度

  • 引擎会在一个进程中进行多次 , 所以其效率非常高

  • 要能处理各种各样的输入 (空数据, 大量的 或者 畸形的数据...)

  • 内部不会调用

  • 如果使用多线程的话,在函数末尾要把 线程

对于 , 直接把 传过来的数据,传给 即可

first_fuzzer.cc


然后用 编译


  • : 表示使用 AddressSanitizer
  • : 为 提供代码覆盖率信息

然后运行


正常的话应该可以看到类似上面的输出,这里对其中的一些信息解析一下

  • 说明这次的种子数据
  • , 用于设置最大的数据长度,默认为
  • 接下来 开头的行是 过程中找到的路径信息
  • 倒数第二行是触发漏洞的测试用例

使用


重现 .


代码量比第一个要复杂了一些,不管那么多先 , 首先看看这个函数的参数, 比 多了一个 类型的参数,所以 fuzz 脚本比 中的加一点修改即可。


测试的目标就是尽可能的测试所有代码路径,又 的第 个参数是 型的(有两种可能), 那我们就对每一个测试用例都用 测试一遍以获取更多的测试路径。

首先编译一下


直接执行会得到类似下面的结果


可以看到 到后面基本找不到新的路径了,一直 。回到 我们发现函数可以处理的最大数据长度是 1024 , 所以给 fuzzer 加个参数设置一下最大数据长度。


可以看到检测到了 栈溢出,触发漏洞的指令位于


跟到该文件内查看,发现是


触发了漏洞,漏洞产生的原因在于, 的 的大小为 , 而这里可以往 的 里面写入最多 字节。


溢出。


就是动态生成了 的值,然后传给 了 。

我们也照着来就行


编译


运行

简单理解 。如果我们要 一个程序,找到一个入口函数,然后利用


接口,我们可以拿到 生成的 测试数据以及测试数据的长度,我们的任务就是把这些生成的测试数据 传入到目标程序中 让程序来处理 测试数据, 同时要尽可能的触发更多的代码逻辑

是用于 某个函数的,所以我们先编译好目标代码库, 然后在根据要 的功能编写 函数。

本节资源文件位于


首先用 编译 .


主要是为了加上 ,用于检测程序中出现的异常(uaf, 堆溢出,栈溢出等漏洞)

常用内存错误检测工具

: 检测 , 缓冲区溢出,,

: 检测未初始化内存的访问

: 检测一些其他的漏洞,整数溢出,类型混淆等

然后写 fuzzer 的逻辑


感觉用 的话,我们需要做的工作就是根据目标程序的逻辑,把 生成的 测试数据 传递 给 目标程序去处理, 然后在编译时采取合适的 用于检测运行时出现的内存错误

比如上面就是模拟了 SSL 握手的逻辑,然后把 生成的 测试数据作为握手包传递给 。

编译之


运行然后就会出现 信息了


可以看到在 中 触发了堆溢出 ( )

本节相关文件位于


和前面一样,首先编译一下这个库。


然后 的逻辑就非常简单了


把 传过来的数据,转成 , 然后扔给 进行处理。

运行就有 了。

感觉 已经把 一个 的核心(样本生成引擎和异常检测系统) 给做好了, 我们需要做的是根据目标程序的逻辑,把 生成的数据,交给目标程序处理。

前面介绍了 的一些简单的使用方法,下面以 为例,介绍一些 的高级用法。

相关文件位于


首先把 用 编译


然后写个 , 这里选择 测试


然后编译之。


: 是 的路径,需要安装 :


编译好 fuzzer 后,我们运行它:


其中的一些参数做个解释

  • : 设置最长的运行时间, 单位是 秒, 这里是 , 也就是 分钟
  • :执行完 后 打印统计信息
  • : 程序可以有多个目录作为参数,此时 会递归遍历所有目录,把目录中的文件读入最为样本数据传给测试函数,同时会把那些可以产生新的的代码路径的样本保存到第一个目录里面。

运行完后会得到类似下面的结果


开始由 夹着的是 在 过程中挑选出来的 , 同时还给出了使用的次数,这些 可以在以后 同类型程序时 节省 的时间。

然后以 开头的是一些 fuzz 的统计信息, 主要看 表示整个 过程中触发了多少个代码单元。

可以看到直接 , 分钟 触发了 个代码单元

貌似是 中提出的 ,具体可以看下面这篇文章


我们知道基本上所有的程序都是处理具有一定格式的数据,比如 文档, 图片等等。 这些数据中会有一些特殊字符序列 (或者说关键字), 比如 在 文档中 就有 等,png图片 就有 png 图片头

如果我们事先就把这些 字符序列 列举出来, 直接使用这些关键字去 组合,就会就可以减少很多没有意义的 尝试,同时还有可能会走到更深的程序分支中去。

就是实现了这种思路。 和 使用的 文件的语法是一样的, 所以可以直接拿 afl 里面的 文件来给 使用。

下面这个网址里面就有一些 的 文件


以 libfuzzer 官网 的示例介绍一下语法


  • 开头的行 和 空行会被忽略
  • 这些就类似于注释, 没有意义
  • 真正有用的是由 包裹的字串,这些 字串 就会作为一个个的关键字, 会用它们进行组合来生成样本。

使用 指定 文件,下面使用 为 文件,进行 。


最终这种方式可以探测到 的代码单元, 效率提升还是很明显的。


在上一节里面我们获得了很多的样本,其中有很多其实是重复的,可以使用 把样本集进行精简。


: 精简后的样本集存放的位置

: 原始样本集存放的位置

可以得到类似的结果


可以看到 个样本被精简成了 个样本

使用 参数。


然后会生成一个 *.sancov 文件


然后把它转换成


然后使用 coverage-report-server 解析这个文件。


用浏览器访问之

通过这个功能,我们可以非常直观的看到每个源文件的覆盖率。

前面已经 了 ,这里 另外一个函数

看看 代码


就是把 数据用 做了个中转,喂给 函数。

编译之


运行


然后过一会就会出现 了。

本文地址:http://sjzytwl.xhstdz.com/quote/71697.html    物流园资讯网 http://sjzytwl.xhstdz.com/ , 查看更多

特别提示:本信息由相关用户自行提供,真实性未证实,仅供参考。请谨慎采用,风险自负。


0相关评论
相关最新动态
推荐最新动态
点击排行
网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报  |  鄂ICP备2020018471号