基于LLVM的AFL分析

news2024/12/28 3:20:29

简介

Fuzzing是指通过构造测试输入,对软件进行大量测试来发现软件中的漏洞的一种模糊测试方法。当前大多数远程代码执行和特权提升等比较严重的漏洞都是使用Fuzzing技术挖掘的,Fuzzing技术被证明是当前鉴别软件安全问题方面最强大测试技术。
然而Fuzzing技术仍然存在着覆盖率低的缺陷,而许多的代码漏洞需要更大的路径覆盖率才能触发,而不是通过纯粹的随机尝试。
AFL (American Fuzzy Lop)是一款采取遗传算法生成用例的Fuzzing工具,可以有效地解决这些问题。AFL有两种Fuzzing方法:

  1. 针对开源软件:AFL软件在编译的同时进行插桩,以方便fuzz
  2. 针对闭源软件:配合QEMU直接对闭源的二进制代码进行fuzz
    另外,AFL有基于gcc和llvm的两种实现方式,本文只讨论基于llvm的AFL对开源软件即有源码的程序的插桩和fuzz过程。

使用

流程概述

首先用afl-clang-fast编译源代码进行插桩,然后启动afl-fuzz程序,将testcase(输入的测试文件)作为程序的输入执行程序,AFL会在这个testcase的基础上进行自动变异输入,使得程序产生crash,产生的crash会被记录起来用于进一步分析。

插桩编译

首先使用以下命令编译源文件,编译过程中会进行插桩:

afl-clang-fast -g -o afl_test afl_test.c

如果是编译c++的源码,那就需要用afl-clang-fast++
接着建立两个目录:fuzz_in和fuzz_out,用来存放程序的输入文件和fuzz的输出文件。在fuzz_in中创建一个testcase文件,用于写入被测试程序的输入。
在编译项目时,通常有Makefile,这时就需要在Makefile中添加内容:

CC=/path/to/afl/afl-clang-fast ./configure
make

使用afl-fuzz

对那些可以直接从stdin读取输入的目标程序来说,语法如下:

$ ./afl-fuzz -i testcase_dir -o findings_dir /path/to/program […params…]

对从文件读取输入的目标程序来说,要用“@@”,语法如下:

$ ./afl-fuzz -i testcase_dir -o findings_dir /path/to/program @@

AFL界面

在这里插入图片描述

process timing:
这里展示了当前fuzz的运行时间、最近一次发现新执行路径的时间、最近一次崩溃的时间、最近一次超时的时间。
值得注意的是第2项,最近一次发现新路径的时间。如果从fuzzing开始一直没有发现新的执行路径,那么就要考虑是否有二进制或者命令行参数错误的问题了,对于此状况,AFL也会智能地进行提醒。
overall results:
这里包括运行的总周期数、总路径数、崩溃次数、超时次数。
其中,总周期数可以用来作为何时停止fuzzing的参考。随着不断地fuzzing,周期数会不断增大,其颜色也会由洋红色,逐步变为黄色、蓝色、绿色。一般来说,当其变为绿色时,代表可执行的内容已经很少了,继续fuzzing下去也不会有什么新的发现了。此时,我们便可以通过Ctrl-C,中止当前的fuzzing。
stage progress:
这里包括正在测试的fuzzing策略、进度、目标的执行总次数、目标的执行速度。
执行速度可以直观地反映当前跑的快不快,如果速度过慢,比如低于500次每秒,那么测试时间就会变得非常漫长。如果发生了这种情况,那么我们需要进一步调整优化我们的fuzzing。

分析

AFL-FUZZ框架在/AFL_PATH/llvm_mode下包含了基于LLVM的实现源码,包括alf-clang-fast.c/afl-llvm-pass.so.cc/afl-llvm-rt.o.c三个文件:

afl-clang-fast.c
其主要功能是在/AFL_PATH目录下编译出afl-clang-fastafl-clang-fast++的ELF可执行文件。
main函数中包括了以下3个主要实现步骤:

find_obj(argv[0]);
edit_params(argc, argv);
execvp(cc_params[0], (char**)cc_params);

find_obj是为了确定afl-llvm-rt.o和afl-llvm-pass.so是否存在,如果不存在将会报错。
edit_params的功能是组装参数,过程中会根据宏USE_TRACE_PC来判断是普通模式还是trace-pc-guard模式,普通模式通过使用afl-llvm-pass.so来插桩。

clang -Xclang -load -Xclang /afl_path/afl-llvm-pass.so -Qunused-arguments ......
clang++ -Xclang -load -Xclang /afl_path/afl-llvm-pass.so -Qunused-arguments ......

trace-pc-guard模式使用原生LLVM回调函数来插桩。

clang -fsanitize-coverage=trace-pc-guard -mllvm -sanitizer-coverage-block-threshold=0 -Qunused-arguments ......
clang++ -fsanitize-coverage=trace-pc-guard -mllvm -sanitizer-coverage-block-threshold=0 -Qunused-arguments ......

下来会根据使用者具体的编译配置对编译命令的参数进行进一步改动(主要包括判断32位/64位环境,添加afl-llvm-rt.o库),把需要调用的clang或者clang++放到cc_params[0]中,进一步传递给execvp后开始执行程序。

afl-llvm-pass.so.cc
注册一个pass,下来就可以在命令行中通过-load来引用该pass。

static void registerAFLPass(const PassManagerBuilder &,
                            legacy::PassManagerBase &PM) {
  PM.add(new AFLCoverage());
}

static RegisterStandardPasses RegisterAFLPass(
    PassManagerBuilder::EP_OptimizerLast, registerAFLPass);

static RegisterStandardPasses RegisterAFLPass0(
    PassManagerBuilder::EP_EnabledOnOptLevel0, registerAFLPass);

该pass遍历所有代码块进行分块随机插桩。同时还会根据环境变量AFL_INST_RETIO来调整插桩的比例inst_ratio,范围为1-100。

for (auto &F : M)
    for (auto &BB : F) {
      BasicBlock::iterator IP = BB.getFirstInsertionPt();
      IRBuilder<> IRB(&(*IP));
      if (AFL_R(100) >= inst_ratio) continue;
	  ……
	  }

afl-llvm-rt.o.c
该代码定义了persistent mode和trace-pc-guard mode的具体调用。

persistent mode
该模式将已经完成fuzz一个testcase的子进程进行复用,从而节省计算机开销。但是需要注意的是每次fuzz过程都会改变一些进程或线程的状态变量,因此,在复用这个fuzz子进程的时候需要将这些变量恢复成初始状态,否则会导致下一次fuzz过程的不准确。从下面代码中可以看到,状态初始化的工作只对第一个循环做,之后的初始化工作都交给父进程。

if (first_pass) {
/* ...... */
if (is_persistent) {
memset(__afl_area_ptr, 0, MAP_SIZE);
__afl_area_ptr[0] = 1;
__afl_prev_loc = 0;
}
cycle_cnt = max_cnt;
first_pass = 0;
return 1;
}

trace-pc-guard mode
该模式是依靠了LLVM本身的特性来实现,AFL中仅实现了使用LLVM-trace-pc-guard功能的两个回调函数。

  1. __sanitizer_cov_trace_pc_guard(uint32_t* guard)
    每个代码块的尾部都会插入这个函数的代码,并且每个代码块都有独立的guard变量可以操作。此处通过guard变量的值来代表各个代码块的ID,从而使用如下代码来标记目标代码块被执行到,以此作为新路径的判断依据
    __afl_area_ptr[*guard]++;
  2. __sanitizer_cov_trace_pc_guard_init(uint32_t* start, uint32_t* stop)
    对guard做了一些初始化的工作,给每个代码块的guard都分配一个随机的ID。如果用户通过AFL_INST_RATIO环境变量来设置了插桩覆盖比例,则根据这个比例的值来对部分代码块的ID标记为0,代表不用插桩。主要逻辑代码如下:
if (R(100) < inst_ratio) *start = R(MAP_SIZE - 1) + 1;
else *start = 0;

同时该函数也会对如下constructor进行调用:

__attribute__((constructor(CONST_PRIO))) void __afl_auto_init(void) {
is_persistent = !!getenv(PERSIST_ENV_VAR);
if (getenv(DEFER_ENV_VAR)) return;
__afl_manual_init();
}

该constructor完成了共享内存,forkserver等功能。其过程与普通模式下afl-fuzz.c中实现的功能一致。

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

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

相关文章

Linux Shell 脚本的10个高频面试问答

Linux 的浩瀚无垠&#xff0c;使人总能每次都提交与众不同的内容。这些内容不仅对他们的职业生涯很有用&#xff0c;同时也让他们增长知识。在此&#xff0c;我们就尝试这么去做&#xff0c;至于能取得多大的成功&#xff0c;就由我们的读者朋友们来判断吧。 在此&#xff0c;…

CopyOnWriteArrayList真的线程安全吗?

前几天刷博客时&#xff0c;无意中看到一篇名为《CopyOnWriteArrayList真的完全线程安全吗》博客。心中不禁泛起疑问&#xff0c;它就是线程安全的啊&#xff0c;难道还有啥特殊情况&#xff1f; 我们知道CopyOnWrite的核心思想正如其名&#xff1a;写时复制。在对数据有修改操…

只要背着电脑,他可以去任何地方

12月是微软全球开发者月&#xff0c;MSDN 微软开发者社区将在此期间推出特别专栏《技术狂旅》&#xff0c;解读这些技术狂热爱好者的个人经历&#xff0c;循着他们的人生旅程看到我们自己的影子&#xff0c;希望能带给你一些启发或激励&#xff0c;一起探寻自身更多的可能性。 …

Android三种数据存储的方式

文章目录Android数据存储技术持久化技术文件存储将数据存储到文件当中示例_将数据存储到文件当中示例_从文件当中读取数据SharedPreferences存储将数据存储到SharedPreferences1.Context类中getSharedPreferences()方法2.Activity类中的getSharedPreferences()方法往SharedPref…

html+css鼠标悬停发光按钮![HTML鼠标悬停的代码]使用HTML + CSS实现鼠标悬停的一些奇幻效果!

源码如下: <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title></title> <style> *{ /* 初始化 清除页面元素得内外边距 */ paddin…

【HTML期末作业】大学生抗疫感动专题网页设计作业 抗疫最美逆行者网页 致敬疫情感动人物网页设计制作

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

LIN总线入门

文章目录 前言一、LIN简介1.1 什么是LIN&#xff1f;1.2 为什么要LIN总线1.3 LIN的发展历史1.4 LIN子网1.5 LIN节点1.6 LIN总线特点 二、LIN的协议层2.1 帧结构2.1.1 同步间隔段(Break Field)2.1.2 同步段(Sync Byte Field)2.1.3 受保护 ID 段(Protected Identifier Field)2.1.…

SpringBoot3.x中spring.factories功能被移除的解决方案

背景笔者所在项目组在搭建一个全新项目的时候选用了SpringBoot3.x&#xff0c;项目中应用了很多SpringBoot2.x时代相关的第三方组件例如baomidou出品的mybatis-plus、dynamic-datasource等。在配置好相关依赖、最小启动类和配置之后&#xff0c;发现项目无法启动。于是根据启动…

万字大章_标题、段落、链接、图像等_HTML入门必备基础

万字大章_HTML入门必备基础HTML篇_第四章、HTML基础一、标题二、段落三、链接3.1文本超链接3.2锚点链接3.3功能性链接四、图像4.1 图像标签&#xff08;<img>&#xff09;和源属性&#xff08;Src&#xff09;4.2 alt属性4.3title属性4.4、设置图像4.4.1设置图像的宽度和…

awk命令的使用

1、获取根分区剩余大小 先用df -h命令查看磁盘&#xff0c;确定我们需要获取字段的位置 再使用awk命令获取此字段 df -hdf -h | awk NR6 {print $4}2、获取当前机器ip地址 ifconfig | awk NR2 {print $2}3、统计出apache的access.log中访问量最多的5个IP 使用awk {print $…

Flink CDC-2.3版本概述

问题导读&#xff1a;1、Flink CDC 2.3 版本有哪些重大改进和核心特性&#xff1f; 2、Flink CDC 2.3 版本中MySQL CDC 连接器有哪些优化&#xff1f; 3、Flink CDC 2.4 版本有哪些规划&#xff1f;01 Flink CDC 简介Flink CDC [1] 是基于数据库的日志 CDC 技术&#xff0c;实现…

HTML5期末大作业:基于HTML+CSS+JavaScript校园文化企业网站模板【学生网页设计作业源码】

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

5个拿来就能用的整人代码脚本

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 整蛊代码脚本一、你的电脑正在被攻击&#xff01;&#xff01;&#xff01;二、CMD炸弹三、无限弹窗四、启动项关机脚本五、舔狗代码一、你的…

毕业后,我的第一辆车

你好&#xff0c;我是阿秀。从学校毕业的时候&#xff0c;我身上差不多有将近12W块钱&#xff0c;有些是自己慢慢存的&#xff0c;有些是在校期间做私活兼职赚的&#xff1a;聊聊我读研期间做过的一些私活和兼职六月毕业后我和我对象去北京玩了几天&#xff0c;去天安门看了毛爷…

微信支付配置

目标&#xff1a;需要生成一个公钥和秘钥配对。放在代码中安全请求。 参考文档&#xff1a;https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_1.shtml https://kf.qq.com/faq/161222NneAJf161222U7fARv.html 一、下载工具 点击下载证书工具&#xff1b;下载…

毕业设计 大数据电商用户行为分析 -python 大数据

文章目录0 前言一.背景描述二.项目背景三.数据来源四.提出问题五.理解数据六.数据清洗6.1缺失值处理6.2查看数据6.3一致化处理6.4查看data_user数据集数据类型&#xff1a;6.5数据类型转换6.6异常值处理七.用户行为分析7.1日访问量分析7.2小时访问量分析7.3不同行为类型用户PV分…

【JavaScript】分支结构和循环结构

目录 一、流程控制 二、分支结构 1. if语句 2. if…else语句 3. if…else if语句 4. switch语句 5. 条件表达式构成的选择结构 三、循环结构 1.while循环 2. do-while循环 3. for循环 3.1 for循环转换为while循环 3.2 断点调试 4. 循环嵌套 一、流程控制 流程控…

知识点2--Docker的安装

上一节知识点说了&#xff0c;一般使用Docker都是在Linux上&#xff0c;Windows有VMware就够了&#xff0c;所以本篇知识点同理带大家在CentOS Linux上安装Docker&#xff0c;但是要知道一个事情&#xff0c;CentOS 6系列的系统由于官方yum的关闭而处于不推荐使用的系统&#x…

微服务框架 SpringCloud微服务架构 16 SpringAMQP 16.9 消息转换器

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构16 SpringAMQP16.9 消息转换器16.9.1 一个案例16.9.2 消息转换器16.9.3 总…

【笔记】JS的[Object file]类型转string

文件上传&#xff0c;用到若依不分离版&#xff0c;其中文件上传时需要控制文件类型&#xff0c;于是就有了这篇笔记。废话不多说&#xff0c;上代码&#xff1a; var formData new FormData();if ($(#filePath)[0].files[0] null) {$.modal.alertWarning("请先选择文件…