文章目录

  • 1.简介
    • 1.1.从Sulley说起
    • 1.2.Boofuzz
      • Boofuzz架构
  • 2.Dev环境部署
    • 2.1.使用pip安装部署
    • 2.2.从源码部署boofuzz
    • 2.3.进程监控
    • 2.4.网络监控,network_monitor.py
  • 3.入门快速使用
    • 3.1.实例化`Session`对象
    • 3.2.定义消息(Request)
    • 3.3.构建协议树(Protocol-Tree)
    • 3.4.Fuzz
    • 3.5.查看结果
  • 4.必备知识汇总
    • 4.1.会话,Session
    • 4.2.目标,Target
      • 4.2.1.Repeater
      • 4.2.2.TimeRepeater
      • 4.2.3.CountRepeater
    • 4.3.连接,Connection
      • 4.3.1.ITargetConnection
      • 4.3.2.BaseSocketConnection
      • 4.3.3.TCPSocketConnection
      • 4.3.4.UDPSocketConnection
      • 4.3.5.SSLSocketConnection
      • 4.3.6.RawL2SocketConnection
      • 4.3.7.RawL3SocketConnection
      • 4.3.8.SocketConnection
      • 4.3.9.SerialConnection
    • 4.4.监视器,Monitors
      • 4.4.1BaseMonitor
      • 4.4.2.ProcessMonitor
      • 4.4.3.NetworkMonitor
      • 4.4.4.CallbackMonitor
    • 4.5.日志,Logging
      • 4.5.1.IFuzzLogger
      • 4.5.2.IFuzzLoggerBackend
      • 4.5.3.FuzzLoggerText
      • 4.5.4.FuzzLoggerCsv
      • 4.5.5.FuzzLoggerCurses
      • 4.5.6.FuzzLogger
    • 4.6.协议定义,Protocol Definition
      • 4.6.1.Request
      • 4.6.2.Blocks
      • 4.6.3.Primitives
      • 4.6.4.制作自己的块/原语
        • Fuzzable
        • FuzzableBlock
    • 4.7.静态协议定义,Static Protocol Definition
    • 4.8.其他模块,Other Modules
      • 4.8.1.测试用例会话引用,ProtocolSessionReference
      • 4.8.2.ProtocolSession
      • 4.8.3.Helpers
      • 4.8.4.IP Constants
      • 4.8.5.PED-RPC
      • 4.8.6.DCE-RPC
      • 4.8.7.Crash binning
      • 4.8.8.EventHook
  • 5.Boofuzz功能探究与源码走读
    • 5.1.Session功能探究
      • 5.1.1.session_filename,序列化持久数据到的文件
      • 5.1.2.`index_start`和`index_end`,指定模糊测试testcase开始和结束的索引
      • 5.1.3.回调函数
      • 5.1.4.其他的略
  • 参考

本文主要涉及到对Boofuzz的简单介绍,以及基于Boofuzz官方文档/网上资料的学习、整理和翻译相关内容,希望对想要入门的Boofuzz的朋友有所帮助,谢谢~

1.简介

模糊技术主要的两种形式:

  • 基于变异的模糊化,mutation-based fuzzing,该技术主要包括以下:

    1. 收集已知的良好数据,如文件或网络流量;
    2. 通过随机/启发式等方式方法,对数据进行稍微地修改;
  • 基于生成的模糊化,generation-based fuzzing,从描述特定格式或网络协议报文格式规范或RFC开始,生成具有一定差异的有效测试用例数据,以便在测试的应用程序中造成崩溃。

模糊测试中,应该避免过度转换数据,否则应用程序可能会很快将输入作为无效输入拒绝。

接下来我们提到的Sulley和Boofuzz都是属于基于生成的模糊化fuzzer。

1.1.从Sulley说起

Sulley不仅具有令人印象深刻的数据生成能力,而且还朝着更进一步的方向迈进了一步,其中还包括现代模糊器应提供的许多其他重要方面。Sulley监视网络并有条不紊地维护记录。Sulley可以检测和监视目标的运行状况,并可以使用多种方法将其恢复到已知的良好状态。Sulley对检测到的故障进行检测,跟踪和分类。Sulley可以并行进行测试,从而显着提高测试速度。Sulley可以自动确定哪些独特的测试用例序列会触发故障。Sulley可以自动完成所有这些工作。

上图是Sulley的整体框架图,来源于BlackHat。Sulley主要包括四大组件

  • Data Generation,数据生成
  • Session,会话管理
  • Agents,代理
  • Utilities,独立单元工具

其中,数据生成和会话管理是比较重要的两个模块。Sulley数据生成方式是基于generation-based的方式,需要对协议或者文件进行建模。数据生成的特点:

  • 一个数据报文由基元(Primitives)、块(Blocks组成);
  • 多个基元可以组成块,块可以相互嵌套;
  • 在基元的基础上我们可以创建自定义的特殊的复杂基元(Legos,数据积木,暂且这么翻译吧),例如Email的地址,IP地址等;
  • 最后还有一些有用的工具,例如算length长度、校验和、加密模块等;

1.2.Boofuzz

Boofuzz是一个基于生成(generation-based)的协议Fuzz工具,它通过python语言来描述协议的格式。

Boofuzz是经典模糊测试框架Sulley的继承者,除了众多的bug修复之外,boofuzz还致力于扩展性。Boofuzz对协议的模糊测试有着良好的支持,且其代码开源,目前被广泛使用,但Boofuzz无法直接获取协议相关知识,需人工定义协议模型.

Boofuzz架构

2.Dev环境部署

2.1.使用pip安装部署

强烈建议在虚拟环境(venv)中设置boofuzz。首先,创建一个目录来保存boofuzz安装:

$ mkdir boofuzz && cd boofuzz
$ python3 -m venv env

这将在当前文件夹中创建一个新的虚拟环境env。请注意,虚拟环境中的Python版本是固定的,并在创建时选择。与全局安装不同,在虚拟环境中,python被别名为虚拟环境的python版本。

接下来,激活虚拟环境:

source env/bin/activate

如果在windows平台上,使用命令:

env\Scripts\activate.bat

使用一下命令更pipsetuptools

(env) $ pip install -U pip setuptools

最后安装boofuzz

(env) $ pip install boofuzz

要运行和测试模糊脚本,请确保始终事先激活虚拟环境

2.2.从源码部署boofuzz

#!/bin/bash
sudo echoif [ ! -d ~/work_dir/boofuzz-F ];thenmv ~/Downloads/boofuzz-F ~/work_dir
fisudo apt-get install -y python3-pip \python3-venv \build-essentialpip install -U pip setuptoolspip install pcapy impacket wheelcd ~/work_dir/boofuzz-F
python3 -m venv env
source env/bin/activate
pip install -e .[dev]

使用HTTP代理时,需要设置环境变量:

set HTTPS_PROXY=http://your.proxy.com:port

2.3.进程监控

process monitor是在Windows或Linux上检测崩溃和重新启动应用程序的工具。虽然boofuzz通常在与目标不同的机器上运行,但进程监视器必须在目标机器本身上运行。

注意:windows平台使用process_monitor.py,*nix平台使用process_monitor_unix.py

2.4.网络监控,network_monitor.py

网络监视器是Sulley记录测试数据的主要工具,已经被boofuzz的记录机制所取代。然而,有些人仍然更喜欢PCAP方法。

注意:

网络监视器需要Pcapy和Impacket,它们不会随着boofuzz自动安装。

您可以使用pip install pcapy impacket手动安装它们。

如果遇到错误,请查看Pcapy项目(https://github.com/helpsystems/pcapy)页面上的要求。

3.入门快速使用

一般fuzz的流程为:

  • 实例化Session对象
  • 定义消息(Request)
  • 构建协议树(Protocol-Tree)
  • Fuzz
  • 查看结果

3.1.实例化Session对象

Session对象是fuzz会话的中心。创建时,将向其传递一个Target对象,该对象本身将接收一个Connection对象。例如:

session = Session(target=Target(connection=TCPSocketConnection("127.0.0.1", 8021)))

Connection对象实现ITargetConnection接口。可用的子类包括:

  • TCPSocketConnection
  • UDPSocketConnection
  • SSLSocketConnection
  • RawL2SocketConnection
  • RawL3SocketConnection
  • SocketConnection (depreciated)
  • SerialConnection

3.2.定义消息(Request)

会话对象就绪后,接下来需要在协议中定义消息。

每个消息都是一个请求对象,其子对象定义该消息的结构。

以下是FTP协议中的几个消息定义:

user = Request("user", children=(String("key", "USER"),Delim("space", " "),String("val", "anonymous"),Static("end", "\r\n"),
))passw = Request("pass", children=(String("key", "PASS"),Delim("space", " "),String("val", "james"),Static("end", "\r\n"),
))stor = Request("stor", children=(String("key", "STOR"),Delim("space", " "),String("val", "AAAA"),Static("end", "\r\n"),
))retr = Request("retr", children=(String("key", "RETR"),Delim("space", " "),String("val", "AAAA"),Static("end", "\r\n"),
))

3.3.构建协议树(Protocol-Tree)

定义消息后,您将使用刚才创建的会话对象将消息(Request)连接到图形(graph)中,构建协议树(Protocol-Tree):

session.connect(user)
session.connect(user, passw)
session.connect(passw, stor)
session.connect(passw, retr)

当模糊化时,boofuzz将在模糊化passw之前发送user,在模糊化stor或retr之前发送user和passw。

从以上的表述可以看出,构建协议树(Protocol-Tree),其实是Session对象组织维护了以root为根节点的消息(Request)状态转移图(graph)。

若要绘制Session构建的消息(Request)状态转移图(graph),使用以下代码

 with open('somefile.png', 'wb') as file: file.write(session.render_graph_graphviz().create_png())

需要注意,绘图前请确保系统中已经安装好了graphviz,如果没有,使用命令sudo apt install graphviz -y进行安装。

将上述例子中的协议树(Protocol-Tree)画出来,如下所示:

3.4.Fuzz

最后即可开始模糊测试

session.fuzz()

请注意,此时您只有一个非常基本的模糊器。

项目中的examples目录中有一些示例和请求定义可能有助于您进一步了解。

3.5.查看结果

每次运行的日志数据将保存到当前工作目录中boofuzz results目录中的SQLite数据库中。您可以随时使用重新打开这些数据库上的web界面

$ boo open <run-*.db>

检查响应,您需要使用Session.post_test_case_callbacks回调函数。要在请求中使用响应中的数据,请参阅ProtocolSessionReference

4.必备知识汇总

我在这里罗列了几个值得重点关注的点:

  • s_*系列函数;
  • 很多s_*系列函数都有一个bool类型的参数fuzzable,它是控制是否对某个字段进行fuzz的开关;
  • Session.connect函数;
  • Session.fuzz函数;

4.1.会话,Session

Session几乎提供了整个Boofuzz功能的设定,同时通过查看Session类初始化的参数可以了解到Boofuzz提供了那些功能。Session类的初始化参数如下:

参数:
session_filename (str): 序列化持久数据到的文件名. Default None.index_start (int);      设置从哪个索引(index)开始启动testcase.index_end (int);        设置到哪个索引(index)结束testcase.sleep_time (float):     运行testcase之间的时间间隔,单位为秒. Default 0.restart_interval (int): 间隔几个testcase就重启一次目标, 设置为0时表示从不重启目标. Default 0.console_gui (bool):     在终端使用光标生产一个类似于web界面的静态控制台。未在Windows下测试. Default False.crash_threshold_request (int):  请求(request)耗尽前允许的最大崩溃数. Default 12.crash_threshold_element (int):  元素(element)耗尽前允许的最大崩溃数. Default 3.restart_sleep_time (int):       目标不能被重启时,休眠的时间,单位为秒. Default 5.restart_callbacks (list of method): 在回调post_test_case_callback失败后,这些注册调用(restart_callbacks)会执行. Default None.restart_threshold (int):    丢失目标连接时的最大重试次数. Default None(indefinitely).restart_timeout (float):    重试连接尝试的时间(秒). Default None(indefinitely).pre_send_callbacks (list of method): 注册的方法将在每个模糊测试用例之前被调用. Default None.post_test_case_callbacks (list of method): 注册的方法将在每个模糊测试用例之后调用. Default None.post_start_target_callbacks (list of method): 方法将在目标启动或重新启动后调用,例如,由进程监视器调用。web_port (int):             通过web浏览器监视模糊测试的端口. Default 26000.keep_web_open (bool):       会话完成后保持webinterface打开. Default True.fuzz_loggers (list of ifuzz_logger.IFuzzLogger): 用于保存测试数据和结果。默认日志到标准输出。fuzz_db_keep_only_n_pass_cases (int): 为了最大限度地减少磁盘使用量,仅保存位于故障或错误之前的n个测试用例的数据。设置为0,表示保存每个测试用例(高磁盘I/O!). Default 0.receive_data_after_each_request (bool): 如果为True,会话将在发送每个非模糊节点后尝试接收应答. Default True.check_data_received_each_request (bool): 如果为True,会话将验证在传输每个非模糊节点后是否已接收到一些数据,如果未接收到待验证的数据,则注册失败。如果为False,则不会执行此检查。默认为False。除非receive_data_after_each_request为假,否则仍会进行接收尝试。receive_data_after_fuzz (bool): 如果为True,会话将在发送模糊消息后尝试接收回复. Default False.ignore_connection_reset (bool): Log ECONNRESET errors ("Target connection reset") as "info" instead of failures.ignore_connection_aborted (bool): Log ECONNABORTED errors as "info" instead of failures.ignore_connection_issues_when_sending_fuzz_data (bool): 忽略模糊数据传输故障。默认为True。这通常是一个有用的启用设置,因为一旦消息明显无效,目标可能会断开连接。ignore_connection_ssl_errors (bool): Log SSL related errors as "info" instead of failures. Default False.reuse_target_connection (bool): If True, only use one target connection instead of reconnecting each test case. Default False.

从以上Session提供的入参可以看出,其大致提供了几个功能:

  • 通过session_filename进行实例对象数据序列化并保持到本地;
  • 通过index_startindex_end手动指定模糊测试testcase的起始和结束索引;
  • 指定时间间隔(发送请求,重启目标等),超时(发送请求等),阈值等;
  • 指定回调函数(pre,post,重启目标等);
  • 监视模糊测试的web-service设置;
  • 其他;

Session继承扩展了pgraph.graph类,pgraph是操纵有向图和无向图的python库,Session在graph类基础上提供用于架构协议会话的容器。

常用函数包括:

  • connect,构建协议树时,用来连接消息节点;

  • add_target,添加目标;

  • example_test_case_callback;

  • register_post_test_case_callback,注册一个测试后用例方法。注册的方法将在每个模糊测试用例之后调用。调用的顺序:

    pre_send()
    ↓
    req
    ↓
    callback
    ↓
    ...
    ↓
    req
    ↓
    callback
    ↓
    post-test-case-callback
    
  • fuzz,模糊整个协议树(Protocol-Tree)。迭代并模糊所有情况,根据self.skip跳过并根据self.restart_interval重新启动。

    如果希望模糊测试结束后,web服务器仍然可用,则程序必须在结尾调用boofuzz.helpers.pause_for_signal()

  • import_file,导入session序列化的本地配置文件;

  • num_mutations,图中的总突变数。此函数会更新成员变量self.total_num_mutations

  • transmit_fuzz,发送模糊测试请求;

  • transmit_normal,发送正常的请求;

  • render_graph_graphviz,渲染图。使用代码:

    with open('somefile.png', 'wb') as file:file.write(session.render_graph_graphviz().create_png())
    

4.2.目标,Target

目标描述符容器。

常用函数包括:

  • set_fuzz_data_logger,设置此对象的模糊数据记录器——用于发送和接收的模糊数据;

4.2.1.Repeater

基础的重复器类

4.2.2.TimeRepeater

基于时间的重复器类。启动计时器,并重复,直到超过持续时间秒。

4.2.3.CountRepeater

基于数量的重复器。重复固定的次数。

4.3.连接,Connection

连接对象,网络层连接描述类。

4.3.1.ITargetConnection

用于连接模糊目标的接口。

4.3.2.BaseSocketConnection

该类是套接字(socket)上许多连接的基础类。

4.3.3.TCPSocketConnection

用于TCP套接字的BaseSocketConnection实现。

4.3.4.UDPSocketConnection

用于UDP套接字的BaseSocketConnection实现。

4.3.5.SSLSocketConnection

用于SSL套接字的BaseSocketConnection实现。

4.3.6.RawL2SocketConnection

用于网络L2层的BaseSocketConnection实现。

4.3.7.RawL3SocketConnection

用于网络L3层的BaseSocketConnection实现。

4.3.8.SocketConnection

ITargetConnection使用套接字实现。

4.3.9.SerialConnection

ITargetConnection实现通用串行端口。

4.4.监视器,Monitors

监控器是针对特定行为监控目标的组件。监视器可以是被动的,只是观察和提供数据,或者更主动地与目标直接交互。某些监控器还具有启动、停止和重新启动目标的功能。

根据您在目标主机上可用的工具,检测目标的崩溃或不当行为可能是一个复杂、非直接的过程;这尤其适用于嵌入式设备。Boofuzz提供了三种主要的监视器实现:

  • ProcessMonitor,在Windows和Unix上从进程收集调试信息的监视器。它还可以重新启动目标进程并检测故障。

  • NetworkMonitor,一种通过PCAP被动捕获网络流量并将其附加到测试用例日志的监视器。

  • CallbackMonitor,用于实现可提供给会话类的回调。

4.4.1BaseMonitor

目标监视器的接口。所有监视器必须遵守本规范。

4.4.2.ProcessMonitor

进程监视器由两部分组成:

  • ProcessMonitor类,实现BaseMonitor;
  • 要在目标主机上运行的模块,windows平台使用process_monitor.py,*nix平台使用process_monitor_unix.py

4.4.3.NetworkMonitor

网络监视器由两部分组成:

  • NetworkMonitor类,它实现BaseMonitor;

  • 要在目标主机上运行的模块,使用network_monitor.py

4.4.4.CallbackMonitor

Session中用于提供回调数组的新型回调监视器。它的目的是在会话类中保留*_callbacks参数,同时通过将这些回调转发到监视器基础结构来简化会话的实现。

参数到此类的方法实现的映射关系,如下所示:

  • restart_callbacks –> target_restart
  • pre_send_callbacks –> pre_send
  • post_test_case_callbacks –> post_send
  • post_start_target_callbacks –> post_start_target

所有其他实现的接口成员都只是存根(stubs),因为会话中不存在相应的参数。在任何情况下,实现自定义监视器可能比使用回调函数更明智。

4.5.日志,Logging

Boofuzz提供了灵活的日志记录。所有日志类都实现IFuzzLogger。下面详细介绍了内置日志类。

要同时使用多个记录器,请参阅 FuzzLogger

4.5.1.IFuzzLogger

用于记录模糊数据的抽象类。

IFuzzLogger为Sulley框架和测试编写器提供了日志接口。

提供的方法旨在反映功能测试动作。IFuzzLogger提供了一种记录测试用例、通过、失败、测试步骤等的方法,而不是一般的调试/信息/警告方法。

这个假设的示例输出给出了如何使用记录器的想法:

  • Test Case: UDP.Header.Address 3300

    Test Step: Fuzzing

    ​ Send: 45 00 13 ab 00 01 40 00 40 11 c9 …

    Test Step: Process monitor

    ​ checkCheck OK

    Test Step: DNP

    ​ CheckSend: ff ff ff ff ff ff 00 0c 29 d1 10 …

    ​ Recv: 00 0c 29 d1 10 81 00 30 a7 05 6e …

    ​ Check: Reply is as expected. Check OK

  • Test Case: UDP.Header.Address 3301

    Test Step: Fuzzing

    ​ Send: 45 00 13 ab 00 01 40 00 40 11 c9 …

    Test Step: Process monitor check

    ​ Check Failed: “Process returned exit code 1”

    Test Step: DNP Check

    ​ Send: ff ff ff ff ff ff 00 0c 29 d1 10 …

    ​ Recv: None

    ​ Check: Reply is as expected. Check Failed

为每个模糊案例打开一个测试案例。为每个高级测试步骤打开一个测试步骤。测试步骤可以包括,例如:

  • Fuzzing
  • Set up (pre-fuzzing)
  • Post-test cleanup
  • Instrumentation checks
  • Reset due to failure

在测试步骤中,测试可以记录发送的数据、接收的数据、检查、检查结果和其他信息。

4.5.2.IFuzzLoggerBackend

IFuzzLogger的别名

4.5.3.FuzzLoggerText

此类格式化FuzzLogger数据以用于文本显示。可以将其配置为输出到标准输出或命名文件。

使用两个FuzzLoggerText,可以将FuzzLogger实例配置为输出到控制台和文件。

4.5.4.FuzzLoggerCsv

此类为pcap文件格式化FuzzLogger数据。可以将其配置为输出到命名文件。

4.5.5.FuzzLoggerCurses

此类使用curses为控制台GUI格式化FuzzLogger数据。这还没有在Windows上测试过。

4.5.6.FuzzLogger

获取IFuzzLogger对象的列表,并将记录的数据多路传输到每个对象。

FuzzLogger还维护概要故障和错误数据。

4.6.协议定义,Protocol Definition

有关老式Spike样式的静态协议定义格式,请参阅静态协议定义函数。这里描述的非静态协议定义是较新的(但仍有些实验性)方法。

请求是消息,消息中包含了块,原语(Primitives)是块/请求的组成(bytes, strings, numbers, checksums等)。

下面是一个HTTP消息的示例。它演示了如何使用请求、块和几个原语:

req = Request("HTTP-Request",children=(Block("Request-Line", children=(Group("Method", values= ["GET", "HEAD", "POST", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE"]),Delim("space-1", " "),String("URI", "/index.html"),Delim("space-2", " "),String("HTTP-Version", "HTTP/1.1"),Static("CRLF", "\r\n"),)),Block("Host-Line", children=(String("Host-Key", "Host:"),Delim("space", " "),String("Host-Value", "example.com"),Static("CRLF", "\r\n"),)),Static("CRLF", "\r\n"),
))

4.6.1.Request

顶层容器。可以保存任何块结构或原语(Primitives)。

这基本上可以被认为是超级块、根块、父块等别名。

4.6.2.Blocks

基本构建块。可以包含primitives, sizers, checksums或其他blocks。

4.6.3.Primitives

  • Static

    静态原语是固定的,在模糊化时不会发生变化。

  • Simple

    只能通过简单手动指定的,模糊字节值。

  • Delim

    分隔符,它的突变包括重复、替换和排除。分隔符包括:,\r,\n, ,=,>,<等等;

  • Group

    此原语表示,在突变时将便利一个指定的静态值列表的每个元素。

    可以将块绑定到组原语,以指定块应循环遍历组中每个值的所有可能突变。例如,group原语在表示有效操作码列表时非常有用。

    下面是Group原语表示HTTP请求方法的所有突变的可能。

        with s_block("Request-Line"):s_group("Method", ["GET", "HEAD", "POST", "PUT", "DELETE", "CONNECT", "OPTIONS", "TRACE"])s_delim(" ", name="space-1")s_string("/index.html", name="Request-URI")s_delim(" ", name="space-2")s_string("HTTP/1.1", name="HTTP-Version")s_static("\r\n", name="Request-Line-CRLF")s_string("Host:", name="Host-Line")s_delim(" ", name="space-3")s_string("example.com", name="Host-Line-Value")s_static("\r\n", name="Host-Line-CRLF")s_static("\r\n", "Request-CRLF")
    
  • RandomData

    生成随机数据块,同时保留原始数据的副本。
    可以指定随机长度范围。对于静态长度,请将最小/最大长度设置为相同。

  • String

    在“坏”字符串库中循环的基元。
    类变量“fuzz_library”包含所有实例的全局智能模糊值列表。当前我使用的代码中的_fuzz_library如下:

        _fuzz_library = ["!@#$%%^#$%#$@#$%$$@#$%^^**(()","",  # strings ripped from spike (and some others I added)"$(reboot)","$;reboot","%00","%00/",
    .........'%0DCMD=$"reboot";$CMD',"%0Dreboot","%n" * 500,"%s" * 100,"%s" * 500,"%u0000","& reboot &","& reboot","&&CMD=$'reboot';$CMD",'&&CMD=$"reboot";$CMD',"&&reboot","&&reboot&&","..:..:..:..:..:..:..:..:..:..:..:..:..:","/%00/","/." * 5000,"/.../" + "B" * 5000 + "\x00\x00","/.../.../.../.../.../.../.../.../.../.../","/../../../../../../../../../../../../boot.ini","/../../../../../../../../../../../../etc/passwd","/.:/" + "A" * 5000 + "\x00\x00","/\\" * 5000,"/index.html|reboot|","; reboot",";CMD=$'reboot';$CMD",';CMD=$"reboot";$CMD',";id",
    .........]
    

    _fuzz_library库变量包含特定于实例化原语的模糊值。这允许我们避免在每个实例化的原语中复制大约70MB的_fuzz_library数据结构。

  • FromFile

    循环浏览文件中的“坏”值列表。
    获取文件名并打开文件以读取模糊化过程中使用的值。文件名可能包含通配符(glob characters)。

  • Mirror

    原语用于使用另一个原语保持更新。

  • BitField

    位字段原语表示许多可变长度,用于定义所有其他整数类型。

  • Byte

    1个字节大小的位字段原语。

  • Bytes

    将任意长度的二进制字节字符串模糊化的原语。

  • Word

    2个字节大小的位字段原语。

  • DWord

    4个字节大小的位字段原语。

  • QWord

    8个字节大小的位字段原语。

4.6.4.制作自己的块/原语

要创建自己的块/基本体,请执行以下操作:

  • FuzzableFuzzableBlock继承一个自定义块/原语类;
  • override父类的mutations和/或encode的方法;

Overload,Override,Overwrite区别

  • Overload重载,同一个作用域中,语义功能相似,仅函数名相同;
  • Override覆盖,继承关系中,Override一般用于多态技术,函数必须实现基类的统一接口;
  • Overwrite重写,继承关系中,子类函数名与父类相同。
  • 可选:创建附带的静态原语函数。示例,请参见boofuzz的__init__.py文件。

如果您的块依赖于对其他块的引用,那么校验和或长度字段依赖于消息的其他部分的方式,请参阅Size源代码以获取如何避免递归问题,并小心。

Fuzzable

自定义块/原语时,需要继承此类。它是所有块/原语的基类。

FuzzableBlock

设计为具有子元素的可模糊类型。

FuzzableBlock重写以下方法,更改基于FuzzableBlock的任何类型的默认行为:

  1. mutations() ,遍历所有子节点产生的突变。
  2. num_mutations() ,对每个子节点表示的突变求和。
  3. encode() ,调用函数 get_child_data().

FuzzableBlock添加了以下方法:

  1. get_child_data(),渲染并连接所有子节点。
  2. push() ,添加额外的子节点;通常只在内部使用。

4.7.静态协议定义,Static Protocol Definition

老式Spike样式的静态协议定义格式,请参阅静态协议定义函数。不在赘述了,推荐使用新的Protocol Definition,见4.6节。

4.8.其他模块,Other Modules

4.8.1.测试用例会话引用,ProtocolSessionReference

指在单个测试用例的上下文中接收或生成的动态值。

将此对象作为原语的default_value参数传递,并确保使用回调设置引用的值,例如,post_test_case_callbacks(请参阅Session

4.8.2.ProtocolSession

包含一个session_variables字典,用于存储特定于单个模糊测试用例的数据。

通常,session_variables中的值将在回调函数中设置,例如,post_test_case_callbacks(请参阅Session)。

变量可以在以后的回调函数中使用,也可以由ProtocolSessionReference对象使用。

4.8.3.Helpers

该类包含了许多助手函授和小工具,熟悉它们,让你更加得心应手。

4.8.4.IP Constants

此文件包含IPv4协议的常量。

在版本0.2.0中更改:ip_constants已移动到connections子包中。完整路径现在是boofuzz.connections.ip_constants

4.8.5.PED-RPC

Boofuzz提供了一个RPC原语来在远程机器上托管监控器。主boofuzz实例充当连接到(远程)运行的RPC服务器实例的客户端,透明地调用在服务器实例的客户端实例上调用的函数,并将其结果作为python对象返回。一般来说,通过RPC接口传递的数据需要能够被pickle。

请注意,PED-RPC不提供任何形式的身份验证或授权。建议仅在受信任的网络上运行它。

4.8.6.DCE-RPC

期待更新…

4.8.7.Crash binning

期待更新…

4.8.8.EventHook

期待更新…

5.Boofuzz功能探究与源码走读

5.1.Session功能探究

前面4.1章节我们已经大概了梳理了Session类提供的功能,以及常用的函数方法。

接下来我们会逐个尝试Session的不同参数设置,对fuzz过程的影响;

5.1.1.session_filename,序列化持久数据到的文件

测试代码使用了example/http_simple.py。修改如下:

def main():session = Session(
+++        session_filename = r'to_specify_path\http_simple.session',target=Target(connection=TCPSocketConnection("127.0.0.1", 80)),)

当指定了session_filename参数后,在fuzz过程中,会产生如下调用栈:

export_file, sessions.py:691 # 将session对象的各个变量dump到本地↑
_fuzz_current_case, sessions.py:1775 # 模糊测试当前用例↑
_main_fuzz_loop, sessions.py:1388 # 模糊测试用例主循环↑
fuzz, sessions.py:1264 # 模糊测试主入口↑
main, http_simple.py:20↑
<module>, http_simple.py:78↑
execfile, _pydev_execfile.py:18↑
run, pydevd.py:1068↑
main, pydevd.py:1658↑
<module>, pydevd.py:1664

5.1.2.index_startindex_end,指定模糊测试testcase开始和结束的索引

测试代码使用了example/http_simple.py。修改如下:

def main():session = Session(
+++        index_start=5,
+++        index_end=10,target=Target(connection=TCPSocketConnection("127.0.0.1", 80)),)

通过调试和走读源码可以发现index_startindex_end主要在_main_fuzz_loop函数中起作用,控制着模糊测试testcase开始和结束。

如下:

# file: boofuzz\sessions.py
# 其中self.total_mutant_index的值是在生成testcase迭代器过程中而增加的。
def _main_fuzz_loop(self, fuzz_case_iterator):...try:...for mutation_context in fuzz_case_iterator:if self.total_mutant_index < self._index_start: # 如果小于index_start则忽略continue# Check restart interval...self._fuzz_current_case(mutation_context)self.num_cases_actually_fuzzed += 1if self._index_end is not None and self.total_mutant_index >= self._index_end: # 如果大于等于index_end则退出Fuzzbreak...except KeyboardInterrupt:...finally:...

5.1.3.回调函数

  • restart_callbacks (list of method),在回调post_test_case_callback失败后,这些调用会执行. Default None.
  • pre_send_callbacks (list of method),注册的方法将在每个模糊测试用例之前被调用. Default None.
  • post_test_case_callbacks (list of method),注册的方法将在每个模糊测试用例之后调用. Default None.
  • post_start_arget_callbacks (list of method),方法将在目标启动或重新启动后调用,例如,由进程监视器调用。

boofuzz中与回调函数主要的相关代码,如下:

# file: boofuzz\sessions.py
class Session(pgraph.Graph):def __init__(self,...restart_callbacks=None,...pre_send_callbacks=None,post_test_case_callbacks=None,post_start_target_callbacks=None,...target=None,):...if pre_send_callbacks is None:pre_send_methods = []else:pre_send_methods = pre_send_callbacksif post_test_case_callbacks is None:post_test_case_methods = []else:post_test_case_methods = post_test_case_callbacksif post_start_target_callbacks is None:post_start_target_methods = []else:post_start_target_methods = post_start_target_callbacksif restart_callbacks is None:restart_methods = []else:restart_methods = restart_callbacksself._callback_monitor = CallbackMonitor(on_pre_send=pre_send_methods,on_post_send=post_test_case_methods,on_restart_target=restart_methods,on_post_start_target=post_start_target_methods,)...

如上Session构造函数中初始化时,创建了一个CallbackMonitor类型的成员变量,CallbackMonitor是Session中用于提供回调数组的回调监视器。它的目的是在Session类中保留*_callbacks的回调参数,同时通过将这些回调转发到监视器基础结构来简化会话的实现。

所有其他实现的接口成员都只是存根(Stub),因为会话中不存在相应的参数。在任何情况下,实现自定义监视器可能比使用回调函数更好一点。

# file: boofuzz\sessions.py
def _fuzz_current_case(self, mutation_context):target = self.targets[0]...try:self._open_connection_keep_trying(target)self._pre_send(target) # 这里会调用Session的pre_send_callbacksfor e in mutation_context.message_path[:-1]:prev_node = self.nodes[e.src]node = self.nodes[e.dst]protocol_session = ProtocolSession(previous_message=prev_node,current_message=node,)mutation_context.protocol_session = protocol_sessioncallback_data = self._callback_current_node(node=node, edge=e, test_case_context=protocol_session) # 这里调用edge的callbackself._fuzz_data_logger.open_test_step("Transmit Prep Node '{0}'".format(node.name))self.transmit_normal(target, node, e, callback_data=callback_data, mutation_context=mutation_context)prev_node = self.nodes[mutation_context.message_path[-1].src]node = self.nodes[mutation_context.message_path[-1].dst]protocol_session = ProtocolSession(previous_message=prev_node,current_message=node,)mutation_context.protocol_session = protocol_sessioncallback_data = self._callback_current_node(node=self.fuzz_node, edge=mutation_context.message_path[-1], test_case_context=protocol_session) # 这里调用edge的callbackself._fuzz_data_logger.open_test_step("Fuzzing Node '{0}'".format(self.fuzz_node.name))self.transmit_fuzz(target,self.fuzz_node,mutation_context.message_path[-1],callback_data=callback_data,mutation_context=mutation_context,)self._check_for_passively_detected_failures(target=target) # 这里会调用Session的post_test_case_callbacks...

注意:除了Session有回调函数,使用Session.connect函数也可以对edge定义调用回调。

5.1.4.其他的略

参考

项目github地址,https://github.com/jtpereyda/boofuzz

boofuzz手册,https://boofuzz.readthedocs.io/en/stable/

IoT 设备网络协议模糊测试工具boofuzz实战,https://blog.csdn.net/song_lee/article/details/104334096

Practical Modbus Fuzzing with boofuzz,https://64k.space/practical-modbus-fuzzing-with-boofuzz.html

Boofuzz协议漏洞挖掘入门教程与使用心得相关推荐

  1. 物联网漏洞挖掘入门--DLINK-DIR-645路由器栈溢出漏洞分析复现

    https://www.rapid7.de/db/modules/exploit/linux/http/dlink_hedwig_cgi_bof 这个栈溢出的原因是由于cookie的值过长导致的栈溢出 ...

  2. Linux 二进制漏洞挖掘入门系列之(五)UAF 漏洞分析与利用

    0x10 UAF(Use After Free) 漏洞原理 这里,需要先介绍一下堆分配内存的原则.ptmalloc 是 glibc 的堆管理器,前身是 dlmalloc,Linux 中进程分配内存的两 ...

  3. 视频教程-逆向工程:游戏安全入门教程-漏洞挖掘与利用

    逆向工程:游戏安全入门教程 杨闯(rkvir)天融信阿尔法实验室安全研究员.看雪漏洞分析小组成员,看雪讲师,MS08067小组成员.从事安全行业多年,擅长二进制安全领域的研究与工程化实现.有多年教育经 ...

  4. Kali Linux 从入门到精通(十)-漏洞挖掘之缓冲区溢出

    Kali Linux 从入门到精通(十)-漏洞挖掘之缓冲区溢出 程序漏洞从哪里来? 罪恶的根源:变量 数据与代码边界不清(注入攻击) 最简漏洞原理-shell 脚本漏洞(本质:输入数据本身,程序本身没 ...

  5. leach协议c++代码_入门教程4:教你STM32F407标准库移植机智云代码(控制LED灯)

    我们知道,使用机智云自助开发平台会根据产品定义的数据点生成对应产品的设备端代码即MCU代码包.自动生成的代码实现了机智云通信协议的解析与封包.传感器数据与通信数据的转换逻辑,并封装成了简单的API,且 ...

  6. 【SEO入门教程】如何从用户需求中挖掘关键词

    网站优化效果好不好,首先要看挖掘的关键词是否合适,这就要求我们在选择关键词的时候一定要从用户需求中去挖掘,不能没有依据瞎选关键词. 1.百度搜索结果10个位置是不是按照用户需求排列呢?(百度说过:能帮 ...

  7. 教育src漏洞挖掘-2022-白帽必挖出教程

    0.关于为什么要写这篇文章 作为刚接触渗透的小伙伴儿肯定都想快速挖到漏洞提交平台获取注册码,或者想获取更多积分换取证书,这篇文章就是为了帮助各位师傅们快速上手挖取教育src 1.开始前准备 每一次成功 ...

  8. 物联网IoT协议之OPC UA快速入门教程

    本文转载,原文作者:源码先生, 文章链接:https://www.debugself.com/2019/11/27/opc_guide/, 请勿用于商业用途.如有侵权,请告知删除,谢谢! 八大物联网I ...

  9. 如何入门漏洞挖掘,以及提高自己的挖掘能力

    0x01:前言 大家好我是米斯特团队的一员,我的id香瓜,我们团队在这次i春秋第二次漏洞挖掘大赛中,包揽了前五名,我key表哥一不小心拿了一个第一,导致很多人来加他好友问他,如何修炼漏洞挖掘能力,我今 ...

最新文章

  1. 初学 Delphi 嵌入汇编[3] - 第一个 Delphi 与汇编的例子
  2. React入门与实践
  3. centos查看特定程序占用端口情况
  4. ubuntu14.04 LTS 源码编译安装postgreSQL
  5. 缺少linux内核,Linux内核缺页
  6. WIN7开启WIFI
  7. 合成孔径雷达算法与实现_[SAR笔记0]合成孔径雷达成像算法与实现
  8. python备注(持续更新……)
  9. 简述神经网络的优点和缺点,人工神经网络优缺点
  10. 【智库解读】明天系、安邦系、海航系、复星系、联想系、中植系、三胞系、宝能系等27个超级民营金融巨头名单及其持股图揭秘!
  11. win10去掉快捷方式小箭头_win7电脑桌面图标有这样的小箭头,怎么去掉?
  12. 单基因gsea_单基因突变+肿瘤突变负荷+免疫细胞浸润文章套路
  13. 跨境电商独立站转化率提升神器-SaleSmartly
  14. MVC 使用ViewBag 加载数据 与laypage 结合
  15. cif和cip的区别_CIF与CIP价的区别?CIP价怎么算的?...
  16. Python代码实现图像增强(线性变换、对数变换、幂律变换、分段线性变换、灰度级分层、直方图均衡化、平滑滤波器、锐化滤波器)
  17. 简单行编辑程序设计文档(数据结构)课设
  18. Access临时学习
  19. 专家表示:土地管理法修订应和物权法精神统一
  20. 服务器的垃圾清扫系统指令,求win10清除系统垃圾的几个命令

热门文章

  1. kettle连接不上es7_kettle常见问题解决
  2. 很有哲理的句子,每天都值得看一遍
  3. CSS3的动画与变形
  4. 爬虫——scrapy框架爬取多个页面电影的二级子页面的详细信息
  5. PATCHY-SAN - Learning Convolutional Neural Networks for Graphs ICML
  6. 【笔记】ConcurrentHashMap,保证线程安全,并且效率高
  7. IT架构——降低成本和复杂性
  8. Spring Security OAuth2 实现使用JWT
  9. 基于Java毕业设计弹幕视频网站源码+系统+mysql+lw文档+部署软件
  10. python+selenium+pycharm自动化测试环境搭建