Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
gdbfuzz — Фаззинг встраиваемых систем с использованием аппаратных точек останова | Kitploit
Инструменты/GitHubGitHub/boschresearch/gdbfuzz
Безопасность встроенных системАнализ уязвимостейОтладчикиФаззингАппаратная БезопасностьАнализ Бинарных ФайловСтатьи и ИсследованияОбучение и ОбразованиеАнализ ПрошивокArchived
GitHubboschresearch/gdbfuzz

gdbfuzz

Фаззинг встраиваемых систем с использованием аппаратных точек останова

19420112 лет назадПроверено Kitploit

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться
Репозиторий

GDBFuzz: Фаззинг с помощью отладчика

Этот репозиторий содержит сопутствующий код для статьи: 'Fuzzing Embedded Systems using Debugger Interfaces'. Препринт статьи можно найти здесь https://publications.cispa.saarland/3950/. Код позволяет пользователям воспроизвести и расширить результаты, представленные в статье. Пожалуйста, цитируйте вышеуказанную статью при сообщении, воспроизведении или расширении результатов.

Структура папок

root@kitploit:~
.
    ├── benchmark               # Скрипты для сборки тестового набора фаззеров Google и запуска экспериментов
    ├── dependencies            # Содержит Makefile для установки зависимостей GDBFuzz
    ├── evaluation              # Необработанные данные экспериментов, представленные в статье
    ├── example_firmware        # Примеры встроенных приложений, используемые для оценки
    ├── example_programs        # Содержит скомпилированную примерную программу и конфиги для тестирования GDBFuzz
    ├── src                     # Содержит реализацию GDBFuzz
    ├── Dockerfile              # Для создания Docker-образа со всеми установленными зависимостями GDBFuzz
    ├── LICENSE                 # Лицензия
    ├── Makefile                # Makefile для создания docker-образа или локальной установки GDBFuzz
    └── README.md               # Этот файл README

Назначение проекта

Идея GDBFuzz заключается в использовании аппаратных точек останова от микроконтроллеров в качестве обратной связи для фаззинга, управляемого покрытием. Для этого GDB используется как универсальный интерфейс для обеспечения широкой применимости. Для бинарного анализа прошивки используется Ghidra. Код содержит настройки эталонного теста для оценки метода. Кроме того, включены примеры файлов прошивок.

Начало работы

GDBFuzz обеспечивает фаззинг, управляемый покрытием, для встраиваемых систем, но – в целях оценки – также может фаззить произвольные пользовательские приложения. Для фаззинга на микроконтроллерах мы рекомендуем локальную установку GDBFuzz, чтобы иметь возможность беспрепятственно отправлять фазз-данные на тестируемое устройство.

Установка локально

GDBFuzz протестирован на Ubuntu 20.04 LTS и Raspberry Pi OS (32-битная). Предварительные требования: java и python3. Сначала создайте новое виртуальное окружение и установите все зависимости.

root@kitploit:~
virtualenv .venv
source .venv/bin/activate
make
chmod a+x ./src/GDBFuzz/main.py

Запуск локально на примере программы

GDBFuzz читает настройки из конфигурационного файла со следующими ключами.

root@kitploit:~
[SUT]
# Путь к бинарному файлу SUT.
# Это может быть, например, файл .elf или .bin.
binary_file_path = <path>

# Адрес корневого узла CFG.
# Точки останова устанавливаются на узлы этого CFG.
# Например, 'LLVMFuzzerTestOneInput' или 'main'
entrypoint = <entrypoint>

# Количество входных данных, которые должны быть выполнены без попадания в точку останова, прежде чем
# точки останова будут повёрнуты.
until_rotate_breakpoints = <number>


# Максимальное количество точек останова, которое может быть установлено в любой момент времени.
max_breakpoints = <number>

# Функции, которые следует игнорировать (чёрный список).
# ignore_functions — это разделённый пробелами список имён функций, например 'malloc free'.
ignore_functions = <space separated list>

# Один из вариантов {Hardware, QEMU, SUTRunsOnHost}
# Hardware: Внешний компонент запускает gdb сервер, и GDBFuzz может подключиться к этому gdb серверу.
# QEMU: GDBFuzz запускает QEMU. QEMU эмулирует binary_file_path и запускает gdbserver.
# SUTRunsOnHost: GDBFuzz запускает целевую программу внутри GDB.
target_mode = <mode>

# Установите это значение в False, если вы хотите запустить ghidra, проанализировать SUT,
# и вручную запустить мост ghidra.
start_ghidra = True


# Разделённый пробелами список адресов, где установлены программные точки останова (для кода
# обработки ошибок). Выполнение по этим адресам считается сбоем.
# Пример: software_breakpoint_addresses = 0x123 0x432
software_breakpoint_addresses = 


# Считаются ли все сработавшие программные точки останова сбоями
consider_sw_breakpoint_as_error = False

[SUTConnection]
# Класс 'SUT_connection_class' в файле 'SUT_connection_path' реализует
# способ отправки входных данных в SUT.
# Входные данные могут, например, отправляться по Wi-Fi, через последовательный порт, Bluetooth и т.д.
# Этот класс должен наследоваться от ./connections/SUTConnection.py.
# См. ./connections/SUTConnection.py для получения дополнительной информации.
SUT_connection_file = FIFOConnection.py

[GDB]
path_to_gdb = gdb-multiarch
# Запись в формате адрес:порт
gdb_server_address = localhost:4242

[Fuzzer]
# В байтах
maximum_input_length = 100000
# В секундах
single_run_timeout = 20
# В секундах
total_runtime = 3600

# Необязательно
# Путь к каталогу, где каждый файл содержит одно начальное значение (seed). Если вы не хотите
# использовать seeds, оставьте значение пустым.
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 отправляет элементы пользовательского интерфейса (например, графики)
enable_UI = False

Пример конфигурационного файла находится в ./example_programs/ вместе с примером программы, которая была скомпилирована с использованием нашей обвязки для фаззинга в benchmark/benchSUTs/GDBFuzz_wrapper/common/. Запустите фаззинг на один час следующей командой.

root@kitploit:~
chmod a+x ./example_programs/json-2017-02-12
./src/GDBFuzz/main.py --config ./example_programs/fuzz_json.cfg

Сначала мы видим вывод от Ghidra, анализирующего бинарный исполняемый файл, а затем сообщения о перемещении или срабатывании точек останова.

Результат фаззинга

В зависимости от указанного output_directory в конфигурационном файле, теперь должна появиться папка trial-0 со следующей структурой

root@kitploit:~
.
    ├── corpus            # Папка, содержащая корпус входных данных.
    ├── crashes           # Папка, содержащая сбойные входные данные (если есть).
    ├── cfg               # Граф потока управления в виде списка смежности.
    ├── fuzzer_stats      # Статистика кампании фаззинга.
    ├── plot_data         # Таблица, показывающая, на каком относительном времени в кампании фаззинга был достигнут какой базовый блок.
    ├── reverse_cfg       # Обратный граф потока управления.

Использование Ghidra в режиме GUI

Установив start_ghidra = False в конфигурационном файле, GDBFuzz подключается к экземпляру Ghidra, работающему в режиме GUI. Для этого плагин ghidra_bridge необходимо запустить вручную из менеджера скриптов. Во время фаззинга достигнутые программные блоки подсвечиваются зелёным цветом.

GDBFuzz на пользовательских программах Linux

Для фаззинга пользовательских приложений Linux GDBFuzz использует стандартную точку входа LLVMFuzzOneInput, которая используется почти всеми фаззерами, такими как AFL, AFL++, libFuzzer и т.д. В benchmark/benchSUTs/GDBFuzz_wrapper/common находится обёртка, которую можно использовать для компиляции любой совместимой обвязки фаззинга в отдельную программу, которая получает входные данные через именованный канал по адресу /tmp/fromGDBFuzz. Это позволяет имитировать встроенное устройство, потребляющее данные через чётко определённый интерфейс ввода, и, следовательно, запускать GDBFuzz на любом приложении. Для удобства мы создали скрипт в benchmark/benchSUTs, который компилирует все программы из нашей оценки с нашей обёрткой, как объяснено позже.

ПРИМЕЧАНИЕ: GDBFuzz не предназначен для фаззинга пользовательских приложений Linux. Для этого используйте AFL++ или другие фаззеры. Обёртка существует только для целей оценки, чтобы обеспечить возможность запуска эталонных тестов и сравнений в масштабе!

Установка и запуск в Docker-контейнере

Общая эффективность нашего подхода показана в крупномасштабном эталонном тесте, развёрнутом в виде Docker-контейнеров.

root@kitploit:~
make dockerimage

Чтобы запустить вышеуказанный эксперимент в Docker-контейнере (на один час, как указано в конфигурационном файле), смонтируйте папки example_programs и output как тома и запустите GDBFuzz следующим образом.

root@kitploit:~
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

В текущем рабочем каталоге должна появиться выходная папка со структурой, описанной выше.

Подробные инструкции

Наша оценка разделена на две части.

  1. GDBFuzz в его предполагаемой конфигурации — непосредственно на оборудовании.
  2. GDBFuzz в эмулированной среде для обеспечения независимого анализа и сравнения результатов.

GDBFuzz может работать с любым GDB-сервером и, следовательно, с большинством отладочных проб для микроконтроллеров.

GDBFuzz против чёрного ящика (RQ1)

Относительно RQ1 из статьи, мы выполняем GDBFuzz на различных микроконтроллерах с разными прошивками, расположенными в example_firmware. Для каждого эксперимента мы запускаем GDBFuzz со стратегией RandomBasicBlock и RandomBasicBlockNoCorpus. Последняя ведёт себя как фаззинг без обратной связи, но мы всё ещё можем измерять достигнутое покрытие. Для ответа на RQ1 мы сравниваем достигнутое покрытие стратегий RandomBasicBlock и RandomBasicBlockNoCorpus. Соответствующие конфигурационные файлы находятся в соответствующих подпапках, и теперь мы объясним, как настроить фаззинг на четырёх отладочных платах.

GDBFuzz на плате STM32 B-L4S5I-IOT01A

GDBFuzz требует доступа к GDB-серверу. В этом случае используются плата B-L4S5I-IOT01A и её встроенный отладчик. Этот встроенный отладчик настраивает GDB-сервер через программу 'st-util' и обеспечивает доступ к этому GDB-серверу через localhost:4242.

  • Установите драйвер STLINK ссылка
  • Подключите плату МК и ПК через USB (на плате МК подключитесь к разъёму USB, помеченному как 'USB STLINK')
root@kitploit:~
sudo apt-get install stlink-tools gdb-multiarch

Соберите и прошейте прошивку для STM32 B-L4S5I-IOT01A, например, проект arduinojson.

Предварительное условие: Установите platformio (pio)

root@kitploit:~
cd ./example_firmware/stm32_disco_arduinojson/
pio run --target upload

Для вашего сведения: platformio сохранил .elf файл SUT здесь: ./example_firmware/stm32_disco_arduinojson/.pio/build/disco_l4s5i_iot01a/firmware.elf. Этот .elf файл также используется позже в пользовательской конфигурации для Ghidra.

Откройте новый терминал и выполните следующее для запуска GDB-сервера:

root@kitploit:~
st-util

Запустите GDBFuzz с пользовательской конфигурацией для arduinojson. Мы можем отправлять данные через USB-порт на микроконтроллер. Микроконтроллер пересылает эти данные через последовательный порт на SUT. В нашем случае /dev/ttyACM0 — это USB-устройство платы микроконтроллера. Если ваша система назначила другое устройство плате микроконтроллера, измените /dev/ttyACM0 в конфигурационном файле на ваше устройство.

root@kitploit:~
./src/GDBFuzz/main.py --config ./example_firmware/stm32_disco_arduinojson/fuzz_serial_json.cfg

Статистика фаззера и журналы находятся в каталоге ./output/...

GDBFuzz на плате CY8CKIT-062-WiFi-BT

Установите pyocd:

root@kitploit:~
pip install --upgrade pip 'mbed-ls>=1.7.1' 'pyocd>=0.16'

Убедитесь, что на устройстве установлен 'KitProg v3', и переведите плату в режим 'Arm DAPLink', нажав соответствующую кнопку. Запустите GDB-сервер:

root@kitploit:~
pyocd gdbserver --persist

Прошейте прошивку и запустите фаззинг, например, с помощью:

root@kitploit:~
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, например, пример arduinojson с помощью platformio.

root@kitploit:~
cd ./example_firmware/esp32_arduinojson/
pio run --target upload

Добавьте следующую строку в файл конфигурации openocd для отладчика J-Link: jlink.cfg

root@kitploit:~
adapter speed 10000

Откройте новый терминал и выполните следующее для запуска GDB-сервера:

root@kitploit:~
get_idf
openocd -f interface/jlink.cfg -f target/esp32.cfg -c "telnet_port 7777" -c "gdb_port 8888"

Запустите GDBFuzz с пользовательской конфигурацией для arduinojson. Мы можем отправлять данные через USB-порт на микроконтроллер. Микроконтроллер пересылает эти данные через последовательный порт на SUT. В нашем случае /dev/ttyUSB0 — это USB-устройство платы микроконтроллера. Если ваша система назначила другое устройство плате микроконтроллера, измените /dev/ttyUSB0 в конфигурационном файле на ваше устройство.

root@kitploit:~
./src/GDBFuzz/main.py --config ./example_firmware/esp32_arduinojson/fuzz_serial.cfg

Статистика фаззера и журналы находятся в каталоге ./output/...

GDBFuzz на MSP430F5529LP

Установите TI MSP430 GCC с https://www.ti.com/tool/MSP430-GCC-OPENSOURCE

Запустите GDB-сервер

root@kitploit:~
./gdb_agent_console libmsp430.so

или (более стабильно). Соберите mspdebug из https://github.com/dlbeer/mspdebug/ и используйте:

root@kitploit:~
until mspdebug --fet-skip-close --force-reset tilib "opt gdb_loop True" gdb ; do sleep 1 ; done

Ghidra не может анализировать бинарные файлы для контроллера TI MSP430 "из коробки". Чтобы это исправить, импортируйте файл в GUI Ghidra, выберите MSP430X в качестве архитектуры и пропустите автоматический анализ. Затем откройте 'Таблицу символов', отсортируйте их по имени и удалите все символы с именами вида $C$L*. Теперь можно выполнить автоматический анализ. После анализа вручную запустите мост ghidra из GUI Ghidra, а затем запустите GDBFuzz.

root@kitploit:~
./src/GDBFuzz/main.py --config ./example_firmware/msp430_arduinojson/fuzz_serial.cfg

Фаззинг USB

Для доступа к USB-устройствам от имени не-root пользователя с помощью pyusb мы добавляем соответствующие правила в udev. Вставьте следующие строки в /etc/udev/rules.d/50-myusb.rules:

root@kitploit:~
SUBSYSTEM=="usb", ATTRS{idVendor}=="1234", ATTRS{idProduct}=="5678" GROUP="usbusers", MODE="666"

Перезагрузите udev:

root@kitploit:~
sudo udevadm control --reload
sudo udevadm trigger

Сравнение с Fuzzware (RQ2)

В RQ2 из статьи мы сравниваем GDBFuzz с подходом, основанным на эмуляции, Fuzzware. Сначала мы выполняем GDBFuzz и Fuzzware, как описано ранее, на прилагаемых файлах прошивок. Для каждого эксперимента GDBFuzz мы создаём файл с корректными базовыми блоками из файлов графа потока управления следующим образом:

root@kitploit:~
cut -d " " -f1 ./cfg > valid_bbs.txt

Теперь мы можем воспроизвести покрытие по сравнению с результатом fuzzware: fuzzware genstats --valid-bb-file valid_bbs.txt

Поиск ошибок (RQ3)

Когда находятся сбойные или зависающие входные данные, они сохраняются в папке crashes. В ходе оценки мы нашли следующие три ошибки:

  1. Бесконечный цикл в стеке USB-устройств STM32, вызванный подсчётом индексной переменной uint8_t до управляемой атакующим переменной uint32_t в цикле for.
  2. Переполнение буфера в JSON-парсере Cypress, вызванное отсутствием проверок длины для внутреннего буфера фиксированного размера.
  3. Разыменование нулевого указателя в JSON-парсере Cypress, вызванное отсутствием проверок.

GDBFuzz на Raspberry Pi 4a (8 ГБ)

GDBFuzz также может работать на хосте Raspberry Pi с небольшими изменениями:

  1. Ghidra необходимо модифицировать, чтобы он работал в 32-битной ОС.

В файле ./dependencies/ghidra/support/launch.sh:125 переменная JAVA_HOME должна быть жёстко задана, например, как JAVA_HOME="/usr/lib/jvm/default-java"

  1. STLink должен быть версии >= 1.7 для корректной работы -> Соберите из исходников

GDBFuzz на других платах

Для фаззинга программного обеспечения на других платах GDBFuzz требует:

  1. Микроконтроллер с аппаратными точками останова и GDB-совместимой отладочной пробой.
  2. Файл прошивки.
  3. Работающий GDBServer и подходящее приложение GDB.
  4. Точка входа, с которой должен начаться фаззинг, например, функция парсера или адрес.
  5. Интерфейс ввода (см. src/GDBFuzz/connections), который запускает выполнение кода в точке входа, например, последовательное соединение.

Все эти свойства должны быть указаны в конфигурационном файле.

Запуск полного эталонного теста (RQ4 - 8)

Для RQ 4–8 мы запускаем крупномасштабный эталонный тест. Сначала соберите Docker-образ, как описано ранее, и скомпилируйте приложения из Fuzzer Test Suite Google с нашей обвязкой для фаззинга в benchmark/benchSUTs/GDBFuzz_wrapper/common.

root@kitploit:~
cd ./benchmark/benchSUTs
chmod a+x setup_benchmark_SUTs.py
make dockerbenchmarkimage

Затем адаптируйте настройки эталонного теста в benchmark/scripts/benchmark.py и benchmark/scripts/benchmark_aflpp.py под свои требования (особенно number_of_cores, trials и seconds_per_trial) и запустите эталонный тест с помощью:

root@kitploit:~
cd ./benchmark/scripts
./benchmark.py $(pwd)/../benchSUTs/SUTs/ SUTs.json
./benchmark_aflpp.py $(pwd)/../benchSUTs/SUTs/ SUTs.json

В ./benchmark/scripts появится папка, содержащая файлы графиков (покрытие во времени), файлы статистики фаззера и файлы графа потока управления для каждого эксперимента, как в evaluation/fuzzer_test_suite_qemu_runs.

[Опционально] Установка визуализации и пример визуализации

GDBFuzz имеет опциональную функцию, которая отображает граф потока управления покрытых узлов. Она отключена по умолчанию. Вы можете включить её, следуя инструкциям этого раздела и установив 'enable_UI' в 'True' в пользовательской конфигурации.

На хосте:

Установите

root@kitploit:~
sudo apt-get install graphviz

Установите последнюю версию node, например, Вариант 2 из здесь. Используйте Вариант 2, а не вариант 1. Это должно установить как node, так и npm. Для справки, наши номера версий (более новые версии тоже должны работать):

root@kitploit:~
➜ node --version
v16.9.1
➜ npm --version
7.21.1

Установите зависимости веб-интерфейса:

root@kitploit:~
cd ./src/webui
npm install

Установите MQTT-брокер mosquitto, например, см. здесь

Обновите конфигурацию брокера mosquitto: Замените файл /etc/mosquitto/conf.d/mosquitto.conf следующим содержимым:

root@kitploit:~
listener 1883
allow_anonymous true

listener 9001
protocol websockets

Перезапустите брокер mosquitto:

root@kitploit:~
sudo service mosquitto restart

Проверьте, работает ли брокер mosquitto:

root@kitploit:~
sudo service mosquitto status

Вывод должен содержать текст 'Active: active (running)'

Запустите веб-интерфейс:

root@kitploit:~
cd ./src/webui
npm start

Ваш веб-браузер должен автоматически открыться по адресу 'http://localhost:3000/'.

Запустите GDBFuzz и используйте пользовательский конфигурационный файл, в котором enable_UI установлено в True. Вы можете использовать Docker-контейнер и SUT arduinojson из примера выше. Но убедитесь, что установили 'enable_UI' в 'True'.

Узлы, покрытые 'синим' цветом, покрыты. Белые узлы не покрыты. Мы показываем только непокрытые узлы, если их родитель покрыт (отрисовка полного графа потока управления занимает слишком много времени, если граф большой).

Лицензия

GDBFuzz распространяется с открытым исходным кодом под лицензией AGPL-3.0. Подробности см. в файле LICENSE.

Список других компонентов с открытым исходным кодом, включённых в GDBFuzz, см. в файле 3rd-party-licenses.txt.

Скачать инструмент