当前位置: 首页 > news >正文

ProFuzzBench入门教学——使用(Ubuntu22.04)

  • ProFuzzBench是网络协议状态模糊测试的基准测试。它包括一套用于流行协议(例如 TLS、SSH、SMTP、FTP、SIP)的代表性开源网络服务器,以及用于自动执行实验的工具。
  • 详细参考:阅读笔记——《ProFuzzBench: A Benchmark for Stateful Protocol Fuzzing》-CSDN博客
  • 环境:Ubuntu22.04(WSL)

1、设置环境变量

  • 克隆项目,设置环境变量。
    • git clone https://github.com/profuzzbench/profuzzbench.git
      cd profuzzbench
      nano ~/.bashrc
  • 添加下面内容。 
    • # profuzzbench
      export PFBENCH=/home/zzs/GitProject/profuzzbench
      export PATH=$PATH:$PFBENCH/scripts/execution:$PFBENCH/scripts/analysis
  • 重新加载配置文件以使更改生效。
    • source ~/.bashrc

2、构建docker镜像

  • 安装docker,参考:Docker——简介、安装(Ubuntu22.04)-CSDN博客
  • 构建docker镜像。
    • cd $PFBENCH
      cd subjects/FTP/LightFTP
      sudo docker build . -t lightftp
      # docker build .:在当前目录(LightFTP)下寻找 Dockerfile 并构建 Docker 镜像
      # -t lightftp:将创建的 Docker 镜像标记为 lightftp
    • 【注】这里创建了一个名为 lightFTP 的 Docker 镜像,该镜像包含了 LightFTP 及其所需的所有依赖项,使其可以在隔离的 Docker 容器中运行。这对于模糊测试和代码覆盖率收集特别有用,因为它提供了一个一致的、可重复的测试环境。
    • 构建时间较长,耐心等待。
    • 【注】可能遇到网络不好,多尝试。
  • 查看构建的镜像。
    • docker images

3、运行模糊测试

  • 运行‘profuzzbench_exec_common.sh’脚本以启动实验。该脚本接受以下 8 个参数:
    • 第一个参数 (DOCIMAGE):Docker镜像的名称。
    • 第二个参数 (RUNS):运行次数,每次运行都会启动一个独立的Docker容器。
    • 第三个参数 (SAVETO):存储结果的文件夹路径。
    • 第四个参数 (FUZZER):模糊测试工具的名称(例如,aflnet)——该名称必须与Docker容器内模糊测试工具文件夹的名称匹配(例如,/home/ubuntu/aflnet)。 
    • 第五个参数 (OUTDIR):在Docker容器内创建的输出文件夹的名称。
    • 第六个参数 (OPTIONS):除目标特定的run.sh脚本中写入的标准选项外,所有模糊测试所需的选项。
    • 第七个参数 (TIMEOUT):模糊测试的时间(以秒为单位)。
    • 第八个参数 (SKIPCOUNT):用于计算随时间变化的覆盖率。例如,SKIPCOUNT=5表示我们在每5个测试用例后运行一次gcovr,因为gcovr需要时间,我们不希望在每个测试用例后都运行它。
  • 以下命令运行一个AFLNet实例,对LightFTP进行60分钟模糊测试。
    • cd $PFBENCH
      mkdir results-lightftp
      profuzzbench_exec_common.sh lightftp 1 results-lightftp aflnet out-lightftp-aflnet "-P FTP -D 10000 -q 3 -s 3 -E -K -R" 3600 5

4、收集结果

  • 所有结果(在 tar 文件中)都应存储在上个步骤(results-lightftp)创建的文件夹中。
  • 具体来说,这些tar文件是所有模糊测试实例生成的输出文件夹的压缩版本。如果模糊测试器是基于AFL的(例如,AFLNet,AFLnwe),每个文件夹应包含诸如 crashes、hangs、queue 等子文件夹。
  • 使用profuzzbench_generate_csv.sh脚本可以收集代码覆盖率随时间变化的结果。该脚本需要以下5个参数:
    • 第一个参数 (PROG):目标程序的名称(例如,lightftp)。
    • 第二个参数 (RUNS):运行次数。
    • 第三个参数 (FUZZER):模糊测试器的名称(例如,aflnet)。
    • 第四个参数 (COVFILE):用于保存结果的 CSV 格式的输出文件。
    • 第五个参数 (APPEND):追加模式;对第一个模糊测试器设置为0,对后续的模糊测试器设置为1。
  • 以下命令收集AFLNet生成的代码覆盖率结果,并将其保存到results.csv。
    • cd $PFBENCH/results-lightftp
      profuzzbench_generate_csv.sh lightftp 1 aflnet results.csv 0
  • results.csv文件如下。该文件有六列,分别显示:
    • 时间(time)
    • 目标程序(subject)
    • 模糊测试器名称(fuzzer)
    • 运行索引(run)
    • 覆盖类型(cov_type)
    • 覆盖率(cov)
  • 文件包含了随时间变化的行覆盖率(l_per、l_abs)分支覆盖率(b_per、b_abs)信息。每种覆盖类型都有两个值,一个是百分比形式(_per),另一个是绝对数值(_abs)。
    • 【注】这里时间为空,暂不知道什么原因。

5、分析结果

  • results.csv中收集的结果可用于绘图。例如,使用示例python脚本绘制代码随时间变化的覆盖率。使用以下命令打印结果并将其保存到文件中。
    • cd $PFBENCH/results-lightftpprofuzzbench_plot.py -i results.csv -p lightftp -r 4 -c 60 -s 1 -o cov_over_time.png
    • 报错:IndexError: index 0 is out of bounds for axis 0 with size 0。
      • 原因是因为文件中time为空,并且只有一个模糊测试器。
  • 改使用aflnwe。删除原先的results-lightftp。
    • cd $PFBENCHrm -rf resluts-lightftpmkdir results-lightftp
      profuzzbench_exec_common.sh lightftp 1 results-lightftp aflnwe out-lightftp-aflnwe "-D 10000 -K" 3600 5cd $PFBENCH/results-lightftp
      profuzzbench_generate_csv.sh lightftp 1 aflnwe results.csv 0
      cat results.csv
  • 修改profuzzbench_plot.py。
    • #!/usr/bin/env pythonimport argparse
      from pandas import read_csv
      from pandas import DataFrame
      from pandas import Grouper
      from matplotlib import pyplot as plt
      import pandas as pddef main(csv_file, put, runs, cut_off, step, out_file):# Read the resultsdf = read_csv(csv_file)# Calculate the mean of code coveragemean_list = []for subject in [put]:fuzzer = 'aflnwe'  # Only use aflnwefor cov_type in ['b_abs', 'b_per', 'l_abs', 'l_per']:# Get subject & fuzzer & cov_type-specific dataframedf1 = df[(df['subject'] == subject) & (df['fuzzer'] == fuzzer) & (df['cov_type'] == cov_type)]mean_list.append((subject, fuzzer, cov_type, 0, 0.0))for time in range(1, cut_off + 1, step):cov_total = 0run_count = 0for run in range(1, runs + 1, 1):# Get run-specific data framedf2 = df1[df1['run'] == run]if df2.empty:continue# Get the starting time for this runstart = df2.iloc[0, 0]# Get all rows given a cutoff timedf3 = df2[df2['time'] <= start + time * 60]if df3.empty:continue# Update total coverage and #runscov_total += df3.tail(1).iloc[0, 5]run_count += 1# Add a new rowif run_count > 0:mean_list.append((subject, fuzzer, cov_type, time, cov_total / run_count))# Convert the list to a dataframemean_df = pd.DataFrame(mean_list, columns=['subject', 'fuzzer', 'cov_type', 'time', 'cov'])fig, axes = plt.subplots(2, 2, figsize=(20, 10))fig.suptitle("Code coverage analysis")for key, grp in mean_df.groupby(['fuzzer', 'cov_type']):if key[1] == 'b_abs':axes[0, 0].plot(grp['time'], grp['cov'])axes[0, 0].set_xlabel('Time (in min)')axes[0, 0].set_ylabel('#edges')if key[1] == 'b_per':axes[1, 0].plot(grp['time'], grp['cov'])axes[1, 0].set_ylim([0, 100])axes[1, 0].set_xlabel('Time (in min)')axes[1, 0].set_ylabel('Edge coverage (%)')if key[1] == 'l_abs':axes[0, 1].plot(grp['time'], grp['cov'])axes[0, 1].set_xlabel('Time (in min)')axes[0, 1].set_ylabel('#lines')if key[1] == 'l_per':axes[1, 1].plot(grp['time'], grp['cov'])axes[1, 1].set_ylim([0, 100])axes[1, 1].set_xlabel('Time (in min)')axes[1, 1].set_ylabel('Line coverage (%)')for i, ax in enumerate(fig.axes):ax.legend(('AFLNwe',), loc='upper left')  # Only AFLNweax.grid()# Save to fileplt.savefig(out_file)# Parse the input arguments
      if __name__ == '__main__':parser = argparse.ArgumentParser()parser.add_argument('-i', '--csv_file', type=str, required=True, help="Full path to results.csv")parser.add_argument('-p', '--put', type=str, required=True, help="Name of the subject program")parser.add_argument('-r', '--runs', type=int, required=True, help="Number of runs in the experiment")parser.add_argument('-c', '--cut_off', type=int, required=True, help="Cut-off time in minutes")parser.add_argument('-s', '--step', type=int, required=True, help="Time step in minutes")parser.add_argument('-o', '--out_file', type=str, required=True, help="Output file")args = parser.parse_args()main(args.csv_file, args.put, args.runs, args.cut_off, args.step, args.out_file)
  • 重新执行:
    • cd $PFBENCH/results-lightftpprofuzzbench_plot.py -i results.csv -p lightftp -r 4 -c 60 -s 1 -o cov_over_time.png

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Java使用POI导出后数字类型为常规类型,不能计算
  • 使用Mplayer实现MP3功能
  • 前端调用有道翻译
  • FPGA设计之跨时钟域(CDC)设计篇(1)----亚稳态到底是什么?
  • 牛市中途深度调整,一览下半场值得关注的 Solana 生态五大潜力项目
  • arm环境安装达梦数据库
  • Linux之免费证书工具certbot安装和使用
  • 设计模式探索:适配器模式
  • 关于ppmlhdfe和possion两个命令回归显示观测值不同
  • 掌握计算机网络基础:从零开始的指南
  • 基于conda包的环境创建、激活、管理与删除
  • 鸿蒙语言基础类库:【@ohos.util.HashMap (非线性容器HashMap)】
  • mes系统在新材料行业中的应用价值
  • 谷粒商城-个人笔记(集群部署篇三)
  • 定义变量和声明变量、定义类和声明类
  • (十五)java多线程之并发集合ArrayBlockingQueue
  • 2017-08-04 前端日报
  • Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment
  • Android优雅地处理按钮重复点击
  • const let
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • ES2017异步函数现已正式可用
  • iOS小技巧之UIImagePickerController实现头像选择
  • JavaScript 是如何工作的:WebRTC 和对等网络的机制!
  • JavaScript新鲜事·第5期
  • JS变量作用域
  • js写一个简单的选项卡
  • js正则,这点儿就够用了
  • php面试题 汇集2
  • SQLServer之创建数据库快照
  • TiDB 源码阅读系列文章(十)Chunk 和执行框架简介
  • 解决iview多表头动态更改列元素发生的错误
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 跨域
  • 聊聊directory traversal attack
  • 猫头鹰的深夜翻译:Java 2D Graphics, 简单的仿射变换
  • 每天10道Java面试题,跟我走,offer有!
  • 世界上最简单的无等待算法(getAndIncrement)
  • 鱼骨图 - 如何绘制?
  • 回归生活:清理微信公众号
  • ​​​​​​​​​​​​​​汽车网络信息安全分析方法论
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • ​一些不规范的GTID使用场景
  • (5)STL算法之复制
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (C语言)fread与fwrite详解
  • (Python第六天)文件处理
  • (Redis使用系列) Springboot 使用Redis+Session实现Session共享 ,简单的单点登录 五
  • (SpringBoot)第七章:SpringBoot日志文件
  • (二)fiber的基本认识
  • (二十一)devops持续集成开发——使用jenkins的Docker Pipeline插件完成docker项目的pipeline流水线发布
  • (附源码)python房屋租赁管理系统 毕业设计 745613
  • (论文阅读30/100)Convolutional Pose Machines
  • (七)理解angular中的module和injector,即依赖注入
  • (算法)求1到1亿间的质数或素数