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;已开启 …

Qt 二维数组的访问与应用

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

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

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

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

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

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

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

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;我遇到了一个典型的依赖库缺失错误&…

无法枚举容器内对象 访问被拒绝

一、什么是“无法枚举容器中的对象。访问被拒绝”错误&#xff1f; 在Windows设备当中&#xff0c;对文件或文件夹的权限进行设置可以有效地保护隐私内容。因此&#xff0c;管理员账户可以对权限进行更改&#xff0c;并且有权决定是否将内容共享给多个用户使用。但是在某些情况…

如何使用Python操作MySQL的各种功能?高级用法?

当今互联网时代&#xff0c;数据处理已经成为了一个非常重要的任务。而MySQL作为一款开源的关系型数据库&#xff0c;被广泛应用于各种场景。本篇博客将介绍如何使用Python操作MySQL的各种功能&#xff0c;以及一些高级用法。 连接MySQL 在Python中&#xff0c;我们可以使用p…

在Vue中搭建Three.js环境(超详细、保姆级),创建场景、相机、渲染器《一》

目录 Three.js简介创建vue项目引入Three.js实际操作环节文件目录创建初始化场景、相机 Three.js简介 Three.js 是一款基于 WebGL的 JavaScript 3D 库&#xff0c;它封装了 WebGL API&#xff0c;为开发者提供了简单易用的 API 来在 Web 浏览器中展示 3D 图形。Three.js 提供了…

CUDA学习笔记04:向量之和

参考资料 CUDA编程模型系列二(向量操作)_哔哩哔哩_bilibili &#xff08;非常好的学习资料&#xff01;&#xff09; vs2019 随意新建一个空项目&#xff0c;按照之前的环境配置配好项目依赖&#xff1a; CUDA学习笔记02&#xff1a;测试程序hello world-CSDN博客 代码结构…

《 前端挑战与未来:如何看待“前端已死”》

在技术领域&#xff0c;时常会有一些激进的言论引发热议&#xff0c;比如近年来不少人声称“前端已死”。这样的言论引发了广泛的讨论和反思。本文将从几个方向探讨这个话题&#xff1a;为什么会出现“前端已死”的言论、如何看待这种说法、前端技术的未来发展趋势以及前端人如…

MS8911S/8921S/8922M/8931S——4ns 延时、轨到轨高速比较器

产品简述 MS8911S/MS8921S/MS8922M/MS8931S 是一款具 有内部迟滞的高速比较器。其电源电压范围为 3.0V- 5.5V &#xff0c;输入和输出范围均可做到轨到轨。其输出为推 挽结构&#xff0c;兼容 CMOS/TTL 逻辑电平标准。传输延时为 4ns &#xff0c;且失调电压低。单一比…

在虚拟机vm下的Linux系统下 安装redis 超详细

打开Linux后 右键打开终端 1.输入:su root 登录root 密码是123456 2.然后输入:yum -y install gcc-c 安装gcc基础依赖包 3.yum -y install centos-release-scl 4.yum -y install devtoolset-9-gcc devtoolset-9-gcc-c devtoolset-9-binutils //为了编译最新版本的Redis源码 用…

二维码门楼牌管理系统应用场景:城市规划与土地管理的新利器

文章目录 前言一、城市规划部门的新助手二、门牌数据的深度应用三、支持可持续城市发展四、与城市规划部门的联动 前言 随着科技的不断进步&#xff0c;二维码技术已经深入到我们生活的方方面面。在城市规划与土地管理领域&#xff0c;二维码门楼牌管理系统正成为一项革命性的…

【Selenium】UI自动化|元素定位常见问题

1、报错NoSuchElementException——定位不到元素 分析的可能原因&#xff1a; 页面还没有加载出来&#xff0c;就对页面上的元素进行的操作 元素在iframe中&#xff0c;先要理解下frame的实质&#xff0c;frame中实际上是嵌入了另一个页面&#xff0c;而webdriver每次只能在一…