AFL havoc_stage

AFL fuzz_one函数,有个地方判断skip_deterministic ,而AFLNet的例子里面,定义了-d参数,也就是skip_deterministic=1,直接进入到havoc_stage,所以这里想分析下havoc_stage。

  if (skip_deterministic || queue_cur->was_fuzzed || queue_cur->passed_det)goto havoc_stage;
havoc_stage:stage_cur_byte = -1;stage_name  = "havoc";stage_short = "havoc";// fuzz次数和perf_score有关stage_max   = (doing_det ? HAVOC_CYCLES_INIT : HAVOC_CYCLES) *perf_score / havoc_div / 100;if (stage_max < HAVOC_MIN) stage_max = HAVOC_MIN;// temp_leng = testcase的长度,输入文件的长度temp_len = len;orig_hit_cnt = queued_paths + unique_crashes;havoc_queued = queued_paths;/* We essentially just do several thousand runs (depending on perf_score)where we take the input file and make random stacked tweaks. */for (stage_cur = 0; stage_cur < stage_max; stage_cur++) {// 生成一个2-256的随机数u32 use_stacking = 1 << (1 + UR(HAVOC_STACK_POW2));stage_cur_val = use_stacking;// 每次会对输入文件进行一种随机操作	 for (i = 0; i < use_stacking; i++) {// 随机选择一种突变操作switch (UR(15 + ((extras_cnt + a_extras_cnt) ? 2 : 0))) {case 0:/* Flip a single bit somewhere. Spooky! */FLIP_BIT(out_buf, UR(temp_len << 3));break;case 1: case 2:case 16:}}// 这个地方完成突变// 执行突变后的的testcaseif (common_fuzz_stuff(argv, out_buf, temp_len))goto abandon_entry;/* out_buf might have been mangled a bit, so let's restore it to itsoriginal size and shape. */if (temp_len < len) out_buf = ck_realloc(out_buf, len);temp_len = len;memcpy(out_buf, in_buf, len);/* If we're finding new stuff, let's run for a bit longer, limitspermitting. */if (queued_paths != havoc_queued) {if (perf_score <= HAVOC_MAX_MULT * 100) {stage_max  *= 2;perf_score *= 2;}havoc_queued = queued_paths;}}new_hit_cnt = queued_paths + unique_crashes;if (!splice_cycle) {stage_finds[STAGE_HAVOC]  += new_hit_cnt - orig_hit_cnt;stage_cycles[STAGE_HAVOC] += stage_max;} else {stage_finds[STAGE_SPLICE]  += new_hit_cnt - orig_hit_cnt;stage_cycles[STAGE_SPLICE] += stage_max;}

这段代码比较关键的部分是这个循环:

    for (i = 0; i < use_stacking; i++) {switch (UR(15 + ((extras_cnt + a_extras_cnt) ? 2 : 0))) {

这里需要搞明白2个问题:use_stacking的含义,UR(15 + ((extras_cnt + a_extras_cnt) ? 2 : 0))的含义

use_stacking,结合注释

  /* We essentially just do several thousand runs (depending on perf_score)where we take the input file and make random stacked tweaks. */

take the input file and make random stacked tweaks.,对输入文件进行随机的 堆叠的 微调。
所以use_stacking是一个随机值,表示对某输入文件进行突变的次数。

UR(15 + ((extras_cnt + a_extras_cnt) ? 2 : 0)),这也是一个随机数,随机选择突变的方法。

接下来单独看一个突变,加深下理解,这里就看case 0,FLIP_BIT

#define FLIP_BIT(_ar, _b) do { \u8* _arf = (u8*)(_ar); \u32 _bf = (_b); \_arf[(_bf) >> 3] ^= (128 >> ((_bf) & 7)); \} while (0)

这段代码也很简单,反转输入_ar(也就是testcase)的第_b位。

综合来看,前面那段代码的意思就是,对于当前的testcase,突变use_stacking次,每次随机选择1种突变策略。

继续往下,执行common_fuzz_stuff函数:

/* Write a modified test case, run program, process results. Handleerror conditions, returning 1 if it's time to bail out. This isa helper function for fuzz_one(). */EXP_ST u8 common_fuzz_stuff(char** argv, u8* out_buf, u32 len) {u8 fault;if (post_handler) {out_buf = post_handler(out_buf, &len);if (!out_buf || !len) return 0;}write_to_testcase(out_buf, len);fault = run_target(argv, exec_tmout);if (fault == FAULT_TMOUT) {if (subseq_tmouts++ > TMOUT_LIMIT) {cur_skipped_paths++;return 1;}} else subseq_tmouts = 0;/* This handles FAULT_ERROR for us: */queued_discovered += save_if_interesting(argv, out_buf, len, fault);if (!(stage_cur % stats_update_freq) || stage_cur + 1 == stage_max)show_stats();return 0;}

根据注释,Write a modified test case, run program, process results.,这里应该要执行代码。
post_handler函数,不太明白
write_to_testcase,这个函数在calibrate_case中也有使用,后续有需要就研究下。
接下来就是调用run_target,参考之前的博客:https://blog.csdn.net/weixin_44033321/article/details/136430578:

调用save_if_interesting来处理run_target返回的错误:

/* Check if the result of an execve() during routine fuzzing is interesting,save or queue the input test case for further analysis if so. Returns 1 ifentry is saved, 0 otherwise. */
// 如果保存了有意思的testcase,就返回1;没保存,返回0
static u8 save_if_interesting(char** argv, void* mem, u32 len, u8 fault) {u8  *fn = "";u8  hnb;s32 fd;u8  keeping = 0, res;switch (fault) {case FAULT_TMOUT:/* Timeouts are not very interesting, but we're still obliged to keepa handful of samples. We use the presence of new bits in thehang-specific bitmap as a signal of uniqueness. In "dumb" mode, wejust keep everything. */total_tmouts++;if (unique_hangs >= KEEP_UNIQUE_HANG) return keeping;if (!dumb_mode) {simplify_trace((u64*)trace_bits);// 如果没有触发新的覆盖,那么就返回函数if (!has_new_bits(virgin_tmout)) return keeping;}unique_tmouts++;/* Before saving, we make sure that it's a genuine hang by re-runningthe target with a more generous timeout (unless the default timeoutis already generous). */// 用一个更宽松的时间,重新执行代码,如果还是返回错误,那么就处理该错误if (exec_tmout < hang_tmout) {u8 new_fault;write_to_testcase(mem, len);new_fault = run_target(argv, hang_tmout);/* A corner case that one user reported bumping into: increasing thetimeout actually uncovers a crash. Make sure we don't discard it ifso. */if (!stop_soon && new_fault == FAULT_CRASH) goto keep_as_crash;if (stop_soon || new_fault != FAULT_TMOUT) return keeping;}// 记录错误到输出文件夹fn = alloc_printf("%s/hangs/id_%06llu", out_dir, unique_hangs);unique_hangs++;last_hang_time = get_cur_time();break;case FAULT_CRASH:keep_as_crash:/* This is handled in a manner roughly similar to timeouts,except for slightly different limits and no need to re-run testcases. */total_crashes++;if (unique_crashes >= KEEP_UNIQUE_CRASH) return keeping;if (!dumb_mode) {simplify_trace((u64*)trace_bits);// 如果没有触发新的路径,那么就丢弃这个testcaseif (!has_new_bits(virgin_crash)) return keeping;}if (!unique_crashes) write_crash_readme();fn = alloc_printf("%s/crashes/id_%06llu_%02u", out_dir, unique_crashes, kill_signal);unique_crashes++;last_crash_time = get_cur_time();last_crash_execs = total_execs;break;case FAULT_ERROR: FATAL("Unable to execute target application");default: return keeping;}/* If we're here, we apparently want to save the crash or hangtest case, too. */fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);if (fd < 0) PFATAL("Unable to create '%s'", fn);ck_write(fd, mem, len, fn);close(fd);ck_free(fn);return keeping;}

这里又调用了simplify_trace:

static void simplify_trace(u64* mem) {u32 i = MAP_SIZE >> 3;while (i--) {/* Optimize for sparse bitmaps. */if (unlikely(*mem)) {u8* mem8 = (u8*)mem;mem8[0] = simplify_lookup[mem8[0]];mem8[1] = simplify_lookup[mem8[1]];mem8[2] = simplify_lookup[mem8[2]];mem8[3] = simplify_lookup[mem8[3]];mem8[4] = simplify_lookup[mem8[4]];mem8[5] = simplify_lookup[mem8[5]];mem8[6] = simplify_lookup[mem8[6]];mem8[7] = simplify_lookup[mem8[7]];} else *mem = 0x0101010101010101ULL;mem++;}}
/* Destructively simplify trace by eliminating hit count informationand replacing it with 0x80 or 0x01 depending on whether the tupleis hit or not. Called on every new crash or timeout, should bereasonably fast. */static const u8 simplify_lookup[256] = { [0]         = 1,[1 ... 255] = 128};

如果trace_bits的某个字节是0,也就是没覆盖到,那么通过simplify_lookup,这一位被转化为1,也就是u8的最低位置1。
如果trace_bits的某个字节是非0,也就是覆盖到,那么通过simplify_lookup,这一位被转化为128,也就是u8的最高位置1。
simplify_trace函数就是把trace_bits进行了一个转化,转化为了0x80,或者0x01。

整个save_if_interesting的作用就是,根据错误类型,以及是否触发了新的覆盖率,来判断是否保存该突变出来的testcase。

但是这里我有3个问题,save_if_interesting函数,经过一系列判断之后,保存当前testcase,并返回keeping。
第一个问题是,keeping当时的值为0,应该返回1?
第二个问题是,这个testcase应该被保存到队列中,具体实现保存的代码是哪里呢?
第三个问题是,has_new_bits对trace_bits进行了转化,转化为0x80,或者0x01,这个会不会影响has_new_bits(virgin_crash)函数的执行结果?

先验证下第一个问题:在return keeping;前面打印下keeping的值,看看是0还是1
在这里插入图片描述
结果这个地方确实=0
那么queued_discovered += save_if_interesting(argv, out_buf, len, fault);,queued_discovered 参数就不会+1

第二个问题,我觉得得先继续往下看,后续可能有对队列的处理

第三个问题,转到分析 trace_bits 和 virgin_bits的博客,继续分析。

目前3个问题都还没有完全搞清楚,先继续往下看了

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

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

相关文章

Ollama内网离线部署大模型

为了演示方便&#xff0c;我这里选用参数较小的Qwen1.5-0.5B-Chat模型。 下载GGUF模型 访问huggingface下载qwen1_5-0_5b-chat-q5_k_m.gguf模型。 https://huggingface.co/Qwen/Qwen1.5-0.5B-Chat-GGUF/tree/main注意&#xff1a; huggingface访问不到&#xff0c;可以选择…

华为智慧教室3.0的晨光,点亮教育智能化变革

“教室外有更大的世界&#xff0c;但世界上没有比教室更伟大的地方。” 我们在求学阶段&#xff0c;都听说过这句话&#xff0c;但往往是在走出校园之后&#xff0c;才真正理解了这句话。为了让走出校园的孩子能够有能力&#xff0c;有勇气探索广阔的世界。我们应该准备最好的教…

@德人合科技|公司数据防泄漏软件,防止内部文件数据资料外泄!

现如今&#xff0c;企业都普遍面临数据安全问题的挑战&#xff0c;随着数据泄漏事件不断增加&#xff0c;企业需要强有力的数据防泄漏系统来保护机密信息。 www.drhchina.com 德人合科技 | 公司数据防泄漏软件&#xff0c;防止内部文件数据资料外泄&#xff01; 公司数据防泄漏…

openGauss环境搭建 | 新手指南

一、搭建准备 openGauss开发需要使用linux环境&#xff0c;先下载远程连接工具Xshell/MobaXterm 。 1. 使用工具连接远程linux服务器&#xff0c;使用root账号远程登录&#xff0c;创建个人账号。 useradd -d /home/xxx -m xxx 2. 设置密码。 passwd xxx 3. 切换到个人账…

【中国电信】光猫 PT632 使用超管权限修改 IP 地址租期时间

背景 由于光猫默认设置的动态 IP 租期是 24 小时&#xff0c;所以每天都会断网一次&#xff0c;严重影响用网体验&#xff0c;所以打算通过修改动态 IP 租期为 一周&#xff08;最长就一周&#xff0c;没有永久的选项&#xff09;来改善。 需求 一台电脑&#xff08;已开启 …

JS_选择文件夹,选择文件夹下所有文件,选择多个文件

选择多个文件 <input type"file" multiple />选择文件夹 选择文件夹下所有文件及递归选择下面所有文件夹的文件 webkitdirectory&#xff1a;适配webkit内核浏览器 mozdirectory&#xff1a;适配火狐浏览器 odirectory&#xff1a;适配opera内核浏览器 IE浏览…

Qt 二维数组的访问与应用

配色方案有多种类型&#xff0c;可以根据不同的需求和应用场景来选择合适的配色方法。在柱状图、饼状图中都会用到不同的配色&#xff0c;本文将配色方案使用二维数组进行存储&#xff0c;对常用的配色进行了整理&#xff1a; 效果图 示例代码 void MainWindow::InitUI() {QS…

ActivityResultLauncher获取Activity返回数据

ActivityResultLauncher(活动结果启动器)是 Android 中用于启动活动并接收结果的新 API。它是在 AndroidX 框架中引入的&#xff0c;用于简化之前使用 startActivityForResult()方法的流程。 在使用 ActivityResultLauncher 之前&#xff0c;你需要选择适当的合同&#xff08;…

java 二分查找(迭代与递归)

二分搜索被定义为一种在排序数组中使用的搜索算法&#xff0c;通过重复将搜索间隔一分为二。二分查找的思想是利用数组已排序的信息&#xff0c;将时间复杂度降低到O(log N)。 二分查找算法示例 何时在数据结构中应用二分查找的条件&#xff1a; 应用二分查找算法&#xff1a…

深入了解 Jetpack Compose 中的 Modifier

Jetpack Compose 是 Android 中用于构建用户界面的现代化工具包。其中&#xff0c;Modifier 是一个非常重要的概念&#xff0c;它允许我们对 UI 组件进行各种样式和布局的调整。在本篇博客中&#xff0c;我们将深入了解 Modifier&#xff0c;以及如何在 Compose 中使用它。 什…

Day5 JS基础-对象

5.1 概念 js里的一种数据类型&#xff0c;无序的数据的集合 5.2 对象使用 语法&#xff1a;let 对象名{ } 对象由属性和方法组成 属性&#xff1a;名词 方法&#xff1a;动词 let 对象名{ 属性名&#xff1a;属性值, 方法名&#xff1a;函数 } 查&#xff1a;对象名.属性 或…

【贪心算法】最大子序和

给你一个整数数组 nums &#xff0c;请你找出一个具有最大和的连续子数组&#xff08;子数组最少包含一个元素&#xff09;&#xff0c;返回其最大和。 子数组是数组中的一个连续部分。 示例 1&#xff1a; 输入&#xff1a;nums [-2,1,-3,4,-1,2,1,-5,4] 输出&#xff1a;6…

Android中的传感器类型和接口名称

本文将介绍传感器坐标轴、基础传感器和复合传感器&#xff08;动作传感器、姿势传感器、未校准传感器和互动传感器&#xff09;。 1. 传感器坐标轴 许多传感器的传感器事件值在相对于设备静止的特定坐标系中表示。 1.1 移动设备坐标轴 Sensor API 仅与屏幕的自然方向相关&a…

java linq 关于常用list的表达式

在Java中&#xff0c;LINQ&#xff08;Language-Integrated Query&#xff09;并非原生支持&#xff0c;而是主要与C#相关。然而&#xff0c;Java 8引入了Stream API&#xff0c;这是一种功能相似的概念&#xff0c;允许通过lambda表达式进行集合操作&#xff0c;类似于LINQ。虽…

【每日一题】1976. 到达目的地的方案数-2024.3.5

题目: 1976. 到达目的地的方案数 你在一个城市里,城市由 n 个路口组成,路口编号为 0 到 n - 1 ,某些路口之间有 双向 道路。输入保证你可以从任意路口出发到达其他任意路口,且任意两个路口之间最多有一条路。 给你一个整数 n 和二维整数数组 roads ,其中 roads[i] = […

mac上传本地文件到远程阿里云

在Mac上将本地文件上传到远程阿里云服务器通常通过SSH协议实现&#xff0c;最常用的命令是scp&#xff08;安全复制&#xff09;。在使用scp之前&#xff0c;请确保您有远程服务器的SSH访问权限&#xff0c;并知道服务器的IP地址&#xff08;或域名&#xff09;、SSH端口&#…

LeetCode 1641.统计字典序元音字符串的数目

给你一个整数 n&#xff0c;请返回长度为 n 、仅由元音 (a, e, i, o, u) 组成且按 字典序排列 的字符串数量。 字符串 s 按 字典序排列 需要满足&#xff1a;对于所有有效的 i&#xff0c;s[i] 在字母表中的位置总是与 s[i1] 相同或在 s[i1] 之前。 示例 1&#xff1a; 输入…

微信小程序 提交表单

微信小程序form如何提交表单 - 简书 <form bindsubmit"formSubmit">

JavaScript的for循环与双重for循环,妈妈再也不用担心我找工作了

学习路线 第一阶段&#xff1a;网页制作 HTML&#xff1a;常用标签&#xff0c;锚点&#xff0c;列表标签&#xff0c;表单标签&#xff0c;表格标签&#xff0c;标签分类&#xff0c;标签语义化&#xff0c;注释&#xff0c;字符实体 CSS&#xff1a;CSS介绍&#xff0c;全局…

解决MySQL 5.7在Redhat 9中启动报错:libncurses.so.5和libtinfo.so.5缺失问题

在使用Linux系统搭建MySQL数据库的过程中&#xff0c;我们往往会遇到各种依赖库的问题&#xff0c;尤其是在安装较旧版本的MySQL时。最近&#xff0c;在RedHat 9&#xff08;rocky linux 9&#xff09;系统上安装MySQL 5.7版本时&#xff0c;我遇到了一个典型的依赖库缺失错误&…