Skip to content
KitploitKITPLOIT
工具漏洞利用博客
Log in
提交
工具漏洞利用博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
gdbfuzz — 使用硬件断点对嵌入式系统进行模糊测试 | Kitploit
工具/GitHubGitHub/boschresearch/gdbfuzz
嵌入式系统安全漏洞分析调试器模糊测试硬件安全二进制分析论文与研究学习与教育固件分析Archived
GitHubboschresearch/gdbfuzz

gdbfuzz

使用硬件断点对嵌入式系统进行模糊测试

19420312年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享
查看仓库

GDBFuzz:调试器驱动的模糊测试

本文是论文《使用调试器接口模糊测试嵌入式系统》的配套代码。 论文预印本可在此处获取:https://publications.cispa.saarland/3950/。代码允许用户 复现并扩展论文中报告的结果。在报告、复现或扩展结果时,请引用上述论文。

文件夹结构

.
    ├── benchmark               # 用于构建 Google 模糊测试套件并运行实验的脚本
    ├── dependencies            # 包含安装 GDBFuzz 依赖项的 Makefile
    ├── evaluation              # 论文中呈现的原始实验数据
    ├── example_firmware        # 用于评估的嵌入式示例应用程序
    ├── example_programs        # 包含一个编译好的示例程序及配置,用于测试 GDBFuzz
    ├── src                     # 包含 GDBFuzz 的实现代码
    ├── Dockerfile              # 用于创建安装了全部 GDBFuzz 依赖项的 Docker 镜像
    ├── LICENSE                 # 许可证
    ├── Makefile                # 用于创建 Docker 镜像或在本地安装 GDBFuzz 的 Makefile
    └── README.md               # 本 README 文件

项目目的

GDBFuzz 的思想是利用微控制器的硬件断点作为覆盖引导模糊测试的反馈。因此,使用 GDB 作为通用接口以实现广泛的适用性。对于固件的二进制分析,使用 Ghidra。代码包含一个用于评估该方法的基准测试设置。此外,还附带了示例固件文件。

开始使用

GDBFuzz 能够对嵌入式系统进行覆盖引导模糊测试,但出于评估目的,也可以模糊测试任意的用户应用程序。对于微控制器上的模糊测试,我们建议在本地安装 GDBFuzz,以便能够顺畅地将模糊数据发送到被测设备。

本地安装

GDBFuzz 已在 Ubuntu 20.04 LTS 和 Raspberry Pi OS 32 位版本上测试通过。 前提条件是 java 和 python3。首先,创建一个新的虚拟环境并安装所有依赖项。

virtualenv .venv
source .venv/bin/activate
make
chmod a+x ./src/GDBFuzz/main.py

在示例程序上本地运行

GDBFuzz 从一个包含以下键的配置文件中读取设置。

[SUT]
# 被测系统二进制文件的路径。
# 例如,可以是 .elf 文件或 .bin 文件。
binary_file_path = <路径>

# 控制流图根节点的地址。
# 断点将放置在该 CFG 的节点上。
# 例如 'LLVMFuzzerTestOneInput' 或 'main'
entrypoint = <入口点>

# 在没有命中断点的情况下,必须执行的输入数量,之后将轮换断点。
until_rotate_breakpoints = <数字>

# 任何时候最多可以放置的断点数量。
max_breakpoints = <数字>

# 要忽略的黑名单函数。
# ignore_functions 是一个空格分隔的函数名列表,例如 'malloc free'。
ignore_functions = <空格分隔的列表>

# 枚举值之一:{Hardware, QEMU, SUTRunsOnHost}
# Hardware: 外部组件启动 gdb 服务器,GDBFuzz 可以连接到该 gdb 服务器。
# QEMU: GDBFuzz 启动 QEMU。QEMU 模拟 binary_file_path 并启动 gdbserver。
# SUTRunsOnHost: GDBFuzz 在 GDB 内部启动目标程序。
target_mode = <模式>

# 如果希望手动启动 Ghidra、分析被测系统并启动 Ghidra 桥接服务器,请设置为 False。
start_ghidra = True

# 设置软件断点(用于错误处理代码)的地址列表,以空格分隔。
# 执行到这些地址被视为崩溃。
# 示例:software_breakpoint_addresses = 0x123 0x432
software_breakpoint_addresses = 

# 是否将所有触发的软件断点视为错误
consider_sw_breakpoint_as_error = False

[SUTConnection]
# 文件 'SUT_connection_path' 中的类 'SUT_connection_class' 实现了
# 如何将输入发送到被测系统。
# 例如,可以通过 Wi-Fi、串口、蓝牙等方式发送输入。
# 该类必须继承自 ./connections/SUTConnection.py。
# 更多信息请参阅 ./connections/SUTConnection.py。
SUT_connection_file = FIFOConnection.py

[GDB]
path_to_gdb = gdb-multiarch
# 格式为 address:port
gdb_server_address = localhost:4242

[Fuzzer]
# 以字节为单位
maximum_input_length = 100000
# 以秒为单位
single_run_timeout = 20
# 以秒为单位
total_runtime = 3600

# 可选
# 一个目录的路径,其中每个文件包含一个种子。如果不希望使用种子,请将值留空。
seeds_directory = 

[BreakpointStrategy]
# 选择基本块的策略位于 'src/GDBFuzz/breakpoint_strategies/' 中
# 在论文中,我们使用了以下策略:
# 'RandomBasicBlockStrategy.py' - 随机选择未到达的基本块
# 'RandomBasicBlockNoDomStrategy.py' - 与上一策略类似,但不使用支配关系导出传递到达的节点。
# 'RandomBasicBlockNoCorpusStrategy.py' - 与第一策略类似,但阻止输入语料库增长,因此表现为带有覆盖率测量的黑盒模糊测试。
# 'BlackboxStrategy.py', - 不设置任何断点
breakpoint_strategy_file = RandomBasicBlockStrategy.py

[Dependencies]
path_to_qemu = dependencies/qemu/build/x86_64-linux-user/qemu-x86_64
path_to_ghidra = dependencies/ghidra

[LogsAndVisualizations]
# 枚举值之一:{DEBUG, INFO, WARNING, ERROR, CRITICAL}
loglevel = INFO

# 存储输出文件(如图表、日志文件)的目录路径。
output_directory = ./output

# 如果设置为 True,MQTT 客户端将发送 UI 元素(如图表)
enable_UI = False

示例配置文件位于 ./example_programs/ 中,同时还有一个示例程序,该程序是使用 benchmark/benchSUTs/GDBFuzz_wrapper/common/ 中的模糊测试工具链编译的。 使用以下命令启动一小时的模糊测试:

chmod a+x ./example_programs/json-2017-02-12
./src/GDBFuzz/main.py --config ./example_programs/fuzz_json.cfg

我们首先看到 Ghidra 分析二进制可执行文件的输出,随后是断点重定位或命中时的消息。

模糊测试输出

根据配置文件中指定的 output_directory,现在应该有一个 trial-0 文件夹,其结构如下:

.
    ├── corpus            # 包含输入语料库的文件夹。
    ├── crashes           # 包含崩溃输入的文件夹(如果有)。
    ├── cfg               # 以邻接表形式表示的控制流图。
    ├── fuzzer_stats      # 模糊测试活动的统计信息。
    ├── plot_data         # 显示在模糊测试活动中哪个基本块在哪个相对时间被到达的表。
    ├── reverse_cfg       # 反向控制流图。

在 GUI 模式下使用 Ghidra

通过在配置文件中设置 start_ghidra = False,GDBFuzz 会连接到以 GUI 模式运行的 Ghidra 实例。因此,需要从脚本管理器手动启动 ghidra_bridge 插件。在模糊测试期间,到达的程序块会以绿色高亮显示。

GDBFuzz 在 Linux 用户程序上的使用

对于 Linux 用户应用程序的模糊测试,GDBFuzz 利用几乎所有模糊器(如 AFL、AFL++、libFuzzer 等)都使用的标准 LLVMFuzzOneInput 入口点。 在 benchmark/benchSUTs/GDBFuzz_wrapper/common 中有一个包装器,可以将任何兼容的模糊测试工具链编译成一个独立的程序,该程序通过位于 /tmp/fromGDBFuzz 的命名管道获取输入。 这允许模拟一个通过明确定义的输入接口消费数据的嵌入式设备,从而在任意应用程序上运行 GDBFuzz。为了方便起见,我们在 benchmark/benchSUTs 中创建了一个脚本,该脚本可以按照稍后说明的方式,使用我们的包装器编译来自我们评估的所有程序。

注意: GDBFuzz 并非用于模糊测试 Linux 用户应用程序。请使用 AFL++ 或其他模糊器。该包装器仅用于评估目的,以便在规模上运行基准测试和比较!

在 Docker 容器中安装并运行

我们方法的总体效果在部署为 Docker 容器的大规模基准测试中得到了展示。

make dockerimage

要在 Docker 容器中运行上述实验(按配置文件指定的一小时),请将 example_programs 和 output 文件夹映射为卷,并按如下方式启动 GDBFuzz:

chmod a+x ./example_programs/json-2017-02-12
docker run -it --env CONFIG_FILE=/example_programs/fuzz_json_docker_qemu.cfg -v $(pwd)/example_programs:/example_programs -v $(pwd)/output:/output gdbfuzz:1.0

在当前工作目录中应该会出现一个 output 文件夹,其结构如上所述。

详细说明

我们的评估分为两部分。

  1. GDBFuzz 在其预期的设置上,直接在硬件上运行。
  2. GDBFuzz 在模拟环境中运行,以便对结果进行独立分析和比较。

GDBFuzz 可以配合任何 GDB 服务器工作,因此也适用于大多数微控制器的调试探针。

GDBFuzz 与黑盒模糊测试对比(研究问题1)

关于论文中的研究问题1,我们在不同的微控制器上使用位于 example_firmware 中的不同固件来执行 GDBFuzz。 对于每个实验,我们分别使用 RandomBasicBlock 策略和 RandomBasicBlockNoCorpus 策略运行 GDBFuzz。后者的行为类似于无反馈的模糊测试,但我们仍然可以测量达到的覆盖率。 为了回答研究问题1,我们比较了 RandomBasicBlock 和 RandomBasicBlockNoCorpus 策略所达到的覆盖率。 相应的配置文件位于相应的子文件夹中,下面我们解释如何在四个开发板上设置模糊测试。

GDBFuzz 在 STM32 B-L4S5I-IOT01A 板上的使用

GDBFuzz 需要访问 GDB 服务器。本例中使用 B-L4S5I-IOT01A 及其板载调试器。该板载调试器通过 'st-util' 程序设置 GDB 服务器,并允许通过 localhost:4242 访问该 GDB 服务器。

  • 安装 STLINK 驱动:链接
  • 通过 USB 连接 MCU 板和 PC(在 MCU 板上,连接到标有 'USB STLINK' 的 USB 接口)
sudo apt-get install stlink-tools gdb-multiarch

为 STM32 B-L4S5I-IOT01A 构建并烧录一个固件,例如 arduinojson 项目。

前提条件:安装 platformio (pio)

cd ./example_firmware/stm32_disco_arduinojson/
pio run --target upload

提示:platformio 将被测系统的一个 .elf 文件存储在此处:./example_firmware/stm32_disco_arduinojson/.pio/build/disco_l4s5i_iot01a/firmware.elf 该 .elf 文件稍后也会在 Ghidra 的用户配置中使用。

打开一个新的终端,并运行以下命令启动 GDB 服务器:

st-util

使用 arduinojson 的用户配置运行 GDBFuzz。我们可以通过 USB 端口将数据发送到微控制器。微控制器通过串口将这些数据转发给被测系统。在我们的例子中,/dev/ttyACM0 是连接微控制器板的 USB 设备。如果您的系统将其他设备分配给微控制器板,请在配置文件中将 /dev/ttyACM0 更改为您的设备。

./src/GDBFuzz/main.py --config ./example_firmware/stm32_disco_arduinojson/fuzz_serial_json.cfg

模糊测试统计信息和日志位于 ./output/... 目录中。

GDBFuzz 在 CY8CKIT-062-WiFi-BT 板上的使用

安装 pyocd:

pip install --upgrade pip 'mbed-ls>=1.7.1' 'pyocd>=0.16'

确保设备上装有 'KitProg v3',并通过按相应按钮将板子切换到 'Arm DAPLink' 模式。 启动 GDB 服务器:

pyocd gdbserver --persist

烧录一个固件并开始模糊测试,例如:

gdb-multiarch
    target remote :3333
    load ./example_firmware/CY8CKIT_json/mtb-example-psoc6-uart-transmit-receive.elf
    monitor reset
./src/GDBFuzz/main.py --config ./example_firmware/CY8CKIT_json/fuzz_serial_json.cfg

GDBFuzz 在 ESP32 和 Segger J-Link 上的使用

  • 安装 ESP32 SDK

为 ESP32 构建并烧录一个固件,例如使用 platformio 的 arduinojson 示例。

cd ./example_firmware/esp32_arduinojson/
pio run --target upload

向 J-Link 调试器的 openocd 配置文件中添加以下行:jlink.cfg

adapter speed 10000

打开一个新的终端,并运行以下命令启动 GDB 服务器:

get_idf
openocd -f interface/jlink.cfg -f target/esp32.cfg -c "telnet_port 7777" -c "gdb_port 8888"

使用 arduinojson 的用户配置运行 GDBFuzz。我们可以通过 USB 端口将数据发送到微控制器。微控制器通过串口将这些数据转发给被测系统。在我们的例子中,/dev/ttyUSB0 是连接微控制器板的 USB 设备。如果您的系统将其他设备分配给微控制器板,请在配置文件中将 /dev/ttyUSB0 更改为您的设备。

./src/GDBFuzz/main.py --config ./example_firmware/esp32_arduinojson/fuzz_serial.cfg

模糊测试统计信息和日志位于 ./output/... 目录中。

GDBFuzz 在 MSP430F5529LP 上的使用

从 https://www.ti.com/tool/MSP430-GCC-OPENSOURCE 安装 TI MSP430 GCC

下载工具