AFL源码阅读笔记(三)—— fuzzer 核心代码 afl-fuzz.c
创始人
2024-05-11 06:49:23
0次

书接上回:AFL源码阅读笔记(二)—— llvm_mode 和 pass 源码

💬 前两个笔记,我们看了两类插桩模式(gcc 和 llvm)及其代码。尽管插桩是 fuzzer 的一个重要环节,但我们不能只看到一点而忽略整体。afl-fuzz.c 文件就撑起了 AFL 整体,包括了种子变异、种子队列、种子选择等模糊测试的核心概念。
🧭 afl-fuzz.c 代码洋洋洒洒 8900 多行,对代码的解读不可能像前两个笔记一样,一行一行读。这部分代码阅读重在捋逻辑,弄清各部分间的关系。

四、AFL 的骨架 —— afl-fuzz.c

程序作者(谷歌大佬)对整体代码的注释:

/* american fuzzy lop - fuzzer code --------------------------------由 Michael Zalewski 编写和维护;Forkserver 由 Jann Horn 设计这部分是真家伙(the real deal): 程序接受一个插桩的二进制文件,并尝试各种基本的模糊测试技巧,关注它们如何影响执行路径。
*/

4.1 头文件

头文件主要有三类来源,自定义头文件、C 标准库和 Linux C 头文件。
自定义头文件有:config.h、types.h、debug.h、alloc-inl.h、hash.h和android-ashmen.h。
Linux C 的头文件格式为 ,如 、。

4.2 准备工作(代码环境、变量定义 …)

(1)对于 Linux 环境,定义宏 HAVE_AFFINITY

#ifdef __linux__
#	define HAVE_AFFINITY 1
#endif /* __linux__ */

这个 affinity 是亲和的意思,这里指 CPU 亲和性。这样的直译让人迷惑,其实它指的就是 CPU 绑定。后面代码对 CPU 亲和性有处理。

CPU affinity 是一种调度属性, 它可以将一个进程“绑定” 到一个或一组CPU上。

(2)全局变量定义

作者对这部分做了一个描述,“许多全局变量,但它们主要是状态 UI 和其它没必要作为函数参数到处拖来拖去的东西”。
EXP_ST 是定义的宏,可以为空,可以为 static。

#ifdef AFL_LIB
#	define EXP_ST			// 空
#else
#	define EXP_ST static	// 静态
#endif /* ^AFL_LIB */

至于变量类型,它们在 types.h 中定义。u 代表无符号 n 位整型,s 代表有符号 n 位整型。各变量含义见英文注释就行。

(3)测试用例队列 结构体

这是一个重要定义,测试用例队列也是 fuzzing 的核心概念之一,在整个模糊测试过程中都要维护这样一个队列。

struct queue_entry {u8* fname;		 // 测试用例的文件名 u32 len;		 // 输入长度,u8 cal_failed,	 // 校准失败?trim_done,	 // 修剪完了(即去除部分测试用例)? was_fuzzed,	 // 是否已完成过 fuzzing passed_det, 	 // Deterministic stages passed? has_new_cov,	 // 触发新的覆盖率? var_behavior, // Variable behavior?favored, 	 // Currently favored?fs_redundant; // Marked as redundant in the fs? u32 bitmap_size, // Number of bits set in bitmap exec_cksum;  // Checksum of the execution trace u64 exec_us,	 // 执行时间(微秒)handicap,	 // Number of queue cycles behind depth;		 // Path depth u8* trace_mini;  // Trace bytes, if keptu32 tc_ref; 	 // Trace bytes ref count struct queue_entry *next,	  // 队列下一结点,如果有的话*next_100; // 100 elements ahead
};

(4)额外数据 结构体

struct extra_data {u8* data;u32 len;u32 hit_cnt;
};

(5)枚举类型

代码中定义了三种枚举类型,用作 Fuzzing 的阶段标识和错误码。
第一部分是 /* Fuzzing stages */,表示 fuzzer 的种子变异策略。

enum {/* 00 */ STAGE_FLIP1,	// 翻转 1 bit/* 01 */ STAGE_FLIP2,	// 翻转 2 bit.../* 16 */ STAGE_SPLICE
};

第二部分是 /* Stage value types */

enum {/* 00 */ STAGE_VAL_NONE,/* 01 */ STAGE_VAL_LE,/* 02 */ STAGE_VAL_BE
};

第三部分是/* Execution status fault codes */,对应执行过程中出现的异常。

enum {/* 00 */ FAULT_NONE,.../* 05 */ FAULT_NOBITS
};

4.3 main() 函数

上一篇:C# 装箱和拆箱

下一篇:PHP 过滤器

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...