Coverage-based Greybox Fuzzing as Markov Chain

news2025/1/16 17:55:06

AFLFast: Coverage-based Greybox Fuzzing as Markov Chain

一、论文阅读

论文来自CCS2016

作者:Marcel Böhme 模糊测试领域巨佬

Abstract

基于覆盖的灰盒模糊测试 Coverage-based Greybox Fuzzing (CGF)。大多数测试用例执行少数高频路径,制定策略倾向于低频路径,使用马尔科夫链模型解释了CGF,该模型指出了执行路径 i 的种子产生覆盖路径 j 的测试用例的概率。每个种子都有能量,即从该种子产生的测试用例数量。如果每次被选择的种子的能量与固定分布的密度成反比并且单调递增

1. Introduction

  • 利用马尔科夫链模型解释了AFL的挑战以及AFLFast的卓越性。
  • 引入并评估了几种控制种子产生测试用例数量的策略,在相同时间内执行更多低频路径
  • 设计并评估了几种控制种子选择的策略
  • 实现了AFLFast并开源 https://github.com/mboehme/aflfast

2. Background

2.1 Covera-based Greybox Fuzzing

2.2 Markov Chain

https://blog.csdn.net/weixin_42437114/article/details/120935992

马尔可夫链是从从一个状态转换为另一个状态的随机过程,在任意时间,只能处于一个状态。状态集合被称为状态空间。从一个状态转移到另一个状态的概率被称为转移概率,转移概率只和前一状态有关。

3. Markov Chain Model

作者认为模糊器如果专注于马尔可夫链的低密度区域将会执行更多路径。所以作者的目标是更多访问位于平稳分布中的低密度区域的状态,更少访问位于平稳分布中的高密度区域的状态。

3.1 Coverage-based Fuzzing as Markov Chain

模糊器发现路径的序列可以由马尔可夫链描述,转移概率 p i , j p_{i,j} pi,j 为执行路径i的种子变异出执行路径j的测试用例的概率,但不是时间齐次的,即不同时间 p i , j p_{i,j} pi,j可能不同。这不能保证平稳分布存在。

时间齐次模型。给定种子集T,S+为种子发现的路径集合,S-为测试用例发现路径集合。马尔可夫链的状态空间为 S = S + ⋃ S − S=S^+ \bigcup S^- S=S+S

转移概率 p i , j p_{i,j} pi,j 定义如下:如果 i ∈ S + i \in S^+ iS+ p i , j p_{i,j} pi,j 为执行路径i的种子变异出执行路径j的测试用例的概率;如果 i ∈ S − i \in S^- iS ,则 p i , i = 1 − ∑ t j ∈ T p j , i p_{i,i}=1-\sum_{t_j\in T}p_{j,i} pi,i=1tjTpj,i ,并且对于所有的 t j ∈ T t_j\in T tjT p i , j = p j , i p_{i,j}=p_{j,i} pi,j=pj,i。即作者做了两个假设:执行路径i的种子变异出执行路径j的测试用例的概率和执行路径j的种子变异出执行路径i的测试用例的概率相同; i ∈ S − i \in S^- iS没有其它未被发现的邻居。

马尔可夫链的平稳分布 π \pi π简言之就是当步数N(应该指转移次数)趋于无限大时,停留在状态i占比。占比大于算术平均值为高密度区域,低于算术平均值为低密度区域。

能量为一个种子生成的测试用例数量,某个状态的能量由预先定义的能量调度决定。

在这里插入图片描述

10%的路径有1000至100000个测试用例执行,而30%的路径只有一个测试用例执行。

这样的马尔可夫链是快速收敛的,根据平稳分布,不论初始时是哪一类种子都将有更高的概率执行高频路径,

3.2 Running Example

void crashme(char* s){
    if (s[0] == ’b’)
        if (s[1] == ’a’)
            if (s[2] == ’d’)
                if (s[3] ==!)
                    abort();
}

上面的代码有五条路径,马尔可夫链如下:

在这里插入图片描述

每次变异一个字符,选择某个字符的概率为1/4(2-2),变异为28个字符集中的一个,变异成某个字符的概率为2-8。剩下的就很好理解了。

3.3 Challenges of Coverage-based Fuzzers

在这里插入图片描述

上图AFL的能量分配示例,假设从字符串“ball”开始,每个种子的能量为 29

则根据上面的状态转移概率,将会有1/4的概率执行****即27,1/4的概率执行b***,即27,1/2的概率执行ba**,即2·27。根据AFL的种子选择策略,按照添加进队列的顺序选择种子进行fuzz。接下来分别fuzz **** 和 b***,则执行各个路径的能量累加即为上图第二行和第三行。

4. Boosting Greybox Fuzzing

文中提出了单调的能量调度方案,首先为种子分配较低的能量,随后当每个种子被选择时单调递增。此外,能量分配和平稳分配的密度成反比。

为了分配更多能量给低密度区的状态,设计了种子选择策略,优先选择最少被选择的种子或是最少被测试用例执行的种子。

4.1 Power Schedules

p ( i ) p(i) p(i) fuzz执行路径i的种子t时分配给其的能量, p ( i ) p(i) p(i)是关于种子被选择次数 s ( i ) s(i) s(i)和执行路径i的测试用例数量 f ( i ) f(i) f(i)的函数。事实上 f ( i ) f(i) f(i)用作分布密度的近似值。

  • exploer模式

p ( i ) = α ( i ) β p(i)={\alpha (i) \over \beta} p(i)=βα(i)

  • coe模式,不fuzz高频路径,只fuzz低频路径,慢慢地高频路径会变为低频路径

p ( i ) = { 0 , i f   f ( i ) > μ m i n ( α ( i ) β ⋅ 2 s ( i ) , M ) , o t h e r w i s e p(i)= \begin{cases} 0, & if \ f(i)>\mu\\ min({\alpha (i) \over \beta}·2^{s(i)}, M), & otherwise \end{cases} p(i)={0,min(βα(i)2s(i),M),if f(i)>μotherwise

其中 μ \mu μ是队列中所有种子的执行路径的平均执行频率,M 为上限
μ = ∑ i ∈ S + f ( i ) ∣ S + ∣ \mu={\sum_{i \in S^+ }f(i) \over \lvert S^+\rvert} μ=S+iS+f(i)

  • fast模式,coe模式的扩展,小于 μ \mu μ 时,能量与 f ( i ) f(i) f(i) 成反比

p ( i ) = m i n ( α ( i ) β ⋅ 2 s ( i ) f ( i ) , M ) p(i)={min({\alpha (i) \over \beta}·{2^{s(i)} \over f(i)}}, M) p(i)=min(βα(i)f(i)2s(i),M)

  • linear模式,与fast模式类似,能量由指数增长变为线性增长

p ( i ) = m i n ( α ( i ) β ⋅ s ( i ) f ( i ) , M ) p(i)={min({\alpha (i) \over \beta}·{s(i) \over f(i)}}, M) p(i)=min(βα(i)f(i)s(i),M)

  • quad模式,平方

x p ( i ) = m i n ( α ( i ) β ⋅ s ( i ) 2 f ( i ) , M ) xp(i)={min({\alpha (i) \over \beta}·{s(i)^2 \over f(i)}}, M) xp(i)=min(βα(i)f(i)s(i)2,M)

4.2 Search Strategies

s(i)优先,被fuzz次数少的种子优先

f(i)优先,执行路径i的测试用例数量少的优先

4.3 Implementation of AFLFast

AFL根据种子的执行速度、覆盖以及生成时间决定分配的能量,AFLFast的五种模式中都保持了这一策略。

AFL中,第一次被fuzz的种子执行确定性变异,而AFLFast一开始分配给种子的能量较低,所以当分配的能量符合确定性变异需要的能量时才执行确定性变异。

此外,AFL首先计算出种子的能量,在本轮fuzz该种子的过程中如果发现了interesting的测试用例,会增加该种子本轮的能量,AFLFast禁用了该功能。

在标记favored时,对于每一条边,AFL选择最小最快的。AFLFast首先标记覆盖这条边并且被fuzz次数最少的种子(源码中未体现),如果存在多个,则标记执行了 被最少数量的测试用例执行的路径f(i) 的种子,如果仍然有多个,才选择最小最快的。

在种子选择时,AFL中离当前种子最近的下一个favored种子将会被选择(即按照队列中的顺序)。AFLFast中选择s(i)最小的,如果有多个,选择f(i) 最小的。(源码中未体现)

5. Evaluation

作者根据cksum判断路径是否相同,并实现了一个哈希表(cksum(i), f(i)),

分别讨论了每种能量分配模式以及每种种子选择策略的效果

总的来说,fast模式的调度策略效果最好。

二、源码分析

1. 新增参数选项

分别对应五种能量调度模式,第三个是AFL默认的能量调度

  • -p fast
  • -p coe
  • -p exploit
  • -p lin
  • -p quad
  • -p explore

2. 一些变量

fuzz_level:种子被fuzz的次数,即 s(i)

n_fuzz:该种子执行路径的执行频率(换言之,该种子执行路径被多少测试用例执行过)

3. calculate_score

static u32 calculate_score(struct queue_entry* q) {

  u32 avg_exec_us = total_cal_us / total_cal_cycles;
  u32 avg_bitmap_size = total_bitmap_size / total_bitmap_entries;
  u32 perf_score = 100;

  /* Adjust score based on execution speed of this path, compared to the
     global average. Multiplier ranges from 0.1x to 3x. Fast inputs are
     less expensive to fuzz, so we're giving them more air time. */

  if (q->exec_us * 0.1 > avg_exec_us) perf_score = 10;
  else if (q->exec_us * 0.25 > avg_exec_us) perf_score = 25;
  else if (q->exec_us * 0.5 > avg_exec_us) perf_score = 50;
  else if (q->exec_us * 0.75 > avg_exec_us) perf_score = 75;
  else if (q->exec_us * 4 < avg_exec_us) perf_score = 300;
  else if (q->exec_us * 3 < avg_exec_us) perf_score = 200;
  else if (q->exec_us * 2 < avg_exec_us) perf_score = 150;

  /* Adjust score based on bitmap size. The working theory is that better
     coverage translates to better targets. Multiplier from 0.25x to 3x. */

  if (q->bitmap_size * 0.3 > avg_bitmap_size) perf_score *= 3;
  else if (q->bitmap_size * 0.5 > avg_bitmap_size) perf_score *= 2;
  else if (q->bitmap_size * 0.75 > avg_bitmap_size) perf_score *= 1.5;
  else if (q->bitmap_size * 3 < avg_bitmap_size) perf_score *= 0.25;
  else if (q->bitmap_size * 2 < avg_bitmap_size) perf_score *= 0.5;
  else if (q->bitmap_size * 1.5 < avg_bitmap_size) perf_score *= 0.75;

  /* Adjust score based on handicap. Handicap is proportional to how late
     in the game we learned about this path. Latecomers are allowed to run
     for a bit longer until they catch up with the rest. */

  if (q->handicap >= 4) {

    perf_score *= 4;
    q->handicap -= 4;

  } else if (q->handicap) {

    perf_score *= 2;
    q->handicap--;

  }

  /* Final adjustment based on input depth, under the assumption that fuzzing
     deeper test cases is more likely to reveal stuff that can't be
     discovered with traditional fuzzers. */

  switch (q->depth) {

    case 0 ... 3:   break;
    case 4 ... 7:   perf_score *= 2; break;
    case 8 ... 13:  perf_score *= 3; break;
    case 14 ... 25: perf_score *= 4; break;
    default:        perf_score *= 5;

  }
    
  // 以上为AFL默认能量调度策略,即论文中的 alpha

  u64 fuzz = q->n_fuzz;	// 路径频率
  u64 fuzz_total;	

  u32 n_paths, fuzz_mu;
  u32 factor = 1;	// 公式中的右半部分

  switch (schedule) {

    case EXPLORE: 
      break;

    case EXPLOIT:
      factor = MAX_FACTOR;	// 默认策略
      break;

    case COE:
      fuzz_total = 0;
      n_paths = 0;

      struct queue_entry *queue_it = queue;	
      while (queue_it) {	// 统计所有种子的路径执行频率,这里不会重复统计,因为加入队列的种子都是执行不同路径的
        fuzz_total += queue_it->n_fuzz;
        n_paths ++;	// 种子数量
        queue_it = queue_it->next;
      }

      fuzz_mu = fuzz_total / n_paths;	// 求mu
      if (fuzz <= fuzz_mu) {	// 低频路径
        if (q->fuzz_level < 16)
          factor = ((u32) (1 << q->fuzz_level));
        else 
          factor = MAX_FACTOR;	// MAX_FACTOR 即论文中的M
      } else {	// 高频路径
        factor = 0;
      }
      break;
    
    case FAST:
      if (q->fuzz_level < 16) {
         factor = ((u32) (1 << q->fuzz_level)) / (fuzz == 0 ? 1 : fuzz); 
      } else
        factor = MAX_FACTOR / (fuzz == 0 ? 1 : next_p2 (fuzz));
      break;

    case LIN:	// 线性
      factor = q->fuzz_level / (fuzz == 0 ? 1 : fuzz); 
      break;

    case QUAD:	// 平方
      factor = q->fuzz_level * q->fuzz_level / (fuzz == 0 ? 1 : fuzz);
      break;

    default:
      PFATAL ("Unkown Power Schedule");
  }
  if (factor > MAX_FACTOR) 
    factor = MAX_FACTOR;	// MAX_FACTOR = 32

  perf_score *= factor / POWER_BETA;	// POWER_BETA = 1

  /* Make sure that we don't go over limit. */

  if (perf_score > HAVOC_MAX_MULT * 100) perf_score = HAVOC_MAX_MULT * 100;

  return perf_score;

}

4. save_if_interesting 中的更改

  // 每个测试用例执行完后都计算表示路径的校验和,然后将队列中执行相同路径的种子的路径频率+1
  /* Update path frequency. */
  u32 cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST);

  struct queue_entry* q = queue;
  while (q) {
    if (q->exec_cksum == cksum)
      q->n_fuzz = q->n_fuzz + 1;

    q = q->next;

  }

5. update_bitmap_score

static void update_bitmap_score(struct queue_entry* q) {

  u32 i;
  u64 fuzz_p2      = next_p2 (q->n_fuzz);	// 求大于等于n_fuzz的第一个2的次方
  u64 fav_factor = q->exec_us * q->len;

  /* For every byte set in trace_bits[], see if there is a previous winner,
     and how it compares to us. */

  for (i = 0; i < MAP_SIZE; i++)

    if (trace_bits[i]) {	// 对于每一个覆盖到的边

       if (top_rated[i]) {	// 如果存在最优者

         u64 top_rated_fuzz_p2    = next_p2 (top_rated[i]->n_fuzz);
         u64 top_rated_fav_factor = top_rated[i]->exec_us * top_rated[i]->len;
		 // 如果执行频率大于原有最优着,则跳过
         if (fuzz_p2 > top_rated_fuzz_p2) continue;
         else if (fuzz_p2 == top_rated_fuzz_p2) {	// 如果等于

           if (fav_factor > top_rated_fav_factor) continue;	// 根据速度和大小决定去留

         }

         /* Looks like we're going to win. Decrease ref count for the
            previous winner, discard its trace_bits[] if necessary. */

         if (!--top_rated[i]->tc_ref) {
           ck_free(top_rated[i]->trace_mini);
           top_rated[i]->trace_mini = 0;
         }

       }

       /* Insert ourselves as the new winner. */

       top_rated[i] = q;
       q->tc_ref++;

       if (!q->trace_mini) {
         q->trace_mini = ck_alloc(MAP_SIZE >> 3);
         minimize_bits(q->trace_mini, trace_bits);
       }

       score_changed = 1;

     }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/10237.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浪潮信息工程师:谈一谈设备透传虚拟机启动慢背后的原因及其优化方法 | 第 51 期

本周「龙蜥大讲堂」预告来啦&#xff01;龙蜥社区邀请了浪潮信息操作系统研发工程师崔士伟分享《设备透传虚拟机的快速启动优化》&#xff0c;快来扫码入群&#xff0c;预定前排小板凳观看直播吧&#xff01; 直播主题及内容介绍 直播主题&#xff1a;设备透传虚拟机的快速启…

360+城市空气质量指数-日度数据、良好天数统计(2001-2022年)

360城市空气质量指数-日度数据、良好天数统计&#xff08;2001-2022年&#xff09; 城市空气质量指数-日度数据、良好天数统计 1、包括&#xff1a;360个城市 2、时间&#xff1a;2001.1-2022.1月 3、样本量&#xff1a;1371937条 4、数据来源&#xff1a;空气质量在线…

使用Excel 表示汽车、摩托车10年免检时间、非常清晰。

1&#xff0c;汽车摩托车10年内年检问题 根据最新的国家法律&#xff1a; http://www.wenjiang.gov.cn/wjzzw/c152333/2022-09/30/content_66efe4febb8040758f3f079cf0baa310.shtml 搜索了下&#xff0c;找到了成都的规定&#xff1a; 近日&#xff0c;公安部、市场监管总局…

中电海康-中电52所面经

中电海康&#xff0c;中电52所面经中电海康面经一面&#xff08;电话面&#xff09;二面&#xff08;现场面&#xff09;自我回顾中电海康面经 一面&#xff08;电话面&#xff09; Redis的使用和配置多线程的使用&#xff0c;线程池的使用SpringBoot的核心注解和流程AOP IOC …

java项目-第133期ssm物流服务管理平台系统-java毕业设计

java项目-第133期ssm物流服务管理平台系统-毕业设计 【源码请到资源专栏下载】 今天分享的项目是《物流服务管理平台系统》 该项目分为前台和后台。主要分成三个角色&#xff1a;游客、普通管理员、管理员三个角色。 游客就是用户&#xff0c;只要是访问系统前台的用户都可以算…

华为防火墙的四种智能选路方式

FW支持四种智能选路方式&#xff0c;不同的智能选路方式可以满足不同的需求&#xff0c;管理员可以根据设备和网络的实际情况进行选择。 表1 智能选路方式 智能选路方式 定义 根据链路带宽负载分担 FW按照带宽比例将流量分配到各条链路上。带宽大的链路转发较多的流量&…

【我的渲染技术进阶之旅】基于Filament渲染引擎绘制一个不停旋转的彩色矩形

一、绘制三角形回顾 在上一篇博客 【我的渲染技术进阶之旅】Google开源的基于物理的实时渲染引擎Filament源码分析:Android版本的Filament第一个示例:sample-hello-triangle 中,我们分析了如何使用Filament来绘制一个三角形,效果如下所示,有一个不停旋转的彩色三角形: …

“外卷”的羽绒服

【潮汐商业评论/ 原创】 2022年的寒潮要比以往来得更早。 “你能想到我今年的第一件羽绒服竟然是在十一期间买的。”没等上“双十一”的车&#xff0c;Eva在国庆期间就已下单了“秋天的第一件羽绒服”。把保暖战线拉长的也不止Eva一个人&#xff0c;据浙商证券研报显示&#…

SpringBoot原理初探以及第一个SpringBoot程序【SpringBoot】

文章目录一.SpringBoot1.1 Spring和SpringBoot1.2 本阶段学习任务1.3 微服务架构二.搭建一个SpringBoot程序2.1 新建SpringBoot项目&#xff08;官方&#xff09;2.2 正常创建SpringBoot项目2.3 项目结构2.4 启动项目2.5 写一个接口HelloControlier2.6 原理2.7 更改配置三.原理…

Plaxis Python 命令流自动化处理、岩土工程渗流问题之有限单元法

目录 岩土工程渗流问题之有限单元法&#xff1a;理论、模块化编程实现、开源程序手把手实操应用 基于python命令流及代码的Plaxis自动化建模与典型案例实践应用 岩土工程渗流问题之有限单元法&#xff1a;理论、模块化编程实现、开源程序手把手实操应用 有限单元法在岩土工程…

NC65 sql server 报数据库“xxx”事务日志已满 的解决方案。

近日公司的NC系统在做薪资发放的计算是&#xff0c;报了如下图的错误&#xff1a; 如何解决解决事务日志已满的问题&#xff08;SQL Server 错误 9002&#xff09;这个问题呢&#xff1f; 微软给的方案 适用于&#xff1a; SQL Server&#xff08;所有受支持的版本&#xf…

IPWorks Encrypt Delphi强加密的一整套组件

IPWorks Encrypt Delphi强加密的一整套组件 通过主要加密标准实现强加密的一整套组件。 IPWorks Encrypt是一个广泛的组件库&#xff0c;允许您通过主要的加密标准(包括S/MIME、OpenPGP、TripleDES、TwoFish、RSA、AES等)对文件、电子邮件、文档和消息进行加密和解密。 IPWorks…

整理了173家国企清单,跳槽必备!

我这里汇总了一些计算机专业可以加入的国企&#xff0c;分享给求职的小伙伴们&#xff0c;内容很多&#xff0c;先收藏再看&#xff01; 一、首选证券公司 各省基本都有一所证券公司&#xff0c;沿海省份集中在税前30-40万左右&#xff0c;内地集中在20-30万。很少加班&#…

二、使用java简单操作kafka

系列文章目录 1.kafka基本原理 文章目录系列文章目录一、搭建一个kafka的demo2.引入依赖3.创建对应的类二、生产者2-1发送到指定分区&#xff0c;等待消息发送成功&#xff08;会阻塞&#xff09;2-2发送到指定分区&#xff0c;异步方式2-3其余两种情况&#xff0c;不指定分区…

如何在 Ubuntu 22.04 上安装 最新版本Wine

过渡到 Linux 的用户的担忧之一是他们是否可以在 Linux 上运行自己喜欢的应用程序。这些范围可以从 Windows 游戏和简单的应用程序软件。值得庆幸的是&#xff0c;Wine 允许用户在 Linux/Unix 系统上运行和执行 Windows 程序。 Wine &#xff08;“Wine Is Not an Emulator” …

【MySQL | 运维篇】06、MySQL 分库分表之 MyCat 分片规则

目录 一、范围分片 1. 介绍 2. 配置 schema.xml逻辑表配置&#xff1a; schema.xml数据节点配置&#xff1a; rule.xml分片规则配置&#xff1a; 二、取模分片 1. 介绍 2. 配置 schema.xml逻辑表配置&#xff1a; schema.xml数据节点配置&#xff1a; rule.xml分片规…

微信小程序--自定义组件(超详细 从新建到使用)

微信小程序–自定义组件 微信小程序官网介绍&#xff01; 本文提供给急需使用自定义组件人群&#xff0c;以下是博主个人理解和案例&#xff01;可以辅助官网来看 介绍&#xff1a; 从小程序基础库版本 1.6.3 开始&#xff0c;小程序支持简洁的组件化编程。所有自定义组件相关…

第6章 数据库事务 第7章 DAO及相关实现类

第6章 数据库事务 1.数据库事务介绍 *事务&#xff1a;一组逻辑操作单元&#xff0c;使数据从一种状态变换到另一种状态 *事务处理&#xff1a;保证所有事务都作为一个工作单元来执行 2.JDBC事务处理 *数据一旦提交则不可回滚 *导致数据自动提交的操作&#xff1a;DDL操…

UE4 回合游戏项目 17- 进入指定区域触发战斗事件

在上一节&#xff08;UE4 回合游戏项目 16- 控制玩家&#xff09;基础上&#xff0c;增加角色走进指定区域从而触发战斗场景的功能 主要思想是添加一个碰撞区域&#xff0c;当玩家与该区域碰撞时&#xff0c;触发战斗事件 效果&#xff1a; 步骤&#xff1a; 1.新建蓝图类 选…

循环检测算法(哈希,双指针)

文章目录快乐数环形链表环形链表II快乐数 寻找快乐数 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。 然后重复这个过程直到这个数变为 1&#xff0c;也可能是 无限循环…