This fork repository contains the supplemental material to the paper 'Stateful Black-Box Fuzzing of Bluetooth Devices Using Automata Learning' by Andrea Pferscher and Bernhard K. Aichernig (Institute of Software Technology, Graz University of Technology).

This repository provides a learning-based fuzzing framework for Bluetooth Low Energy (BLE) devices. The framework consists of two components. The first component is the learning component, which learns the behavioral models of BLE devices. The second component is the stateful fuzzer, which performs fuzz testing on BLE devices based on the previously learned model.
This repository also contains the learned models used in the presented case study in the paper. Furthermore, some exploits and test scripts for anomalies are provided. We also include a script that tests for a possible key downgrade during the learning process.
EDIT / UPDATE by @shipcod3 for ble-fuzzingv2:
I love this project, and I have used it for fuzzing some devices for SPIRITCYBER IoT Hackathon, so I decided to fix some errors, like the script was crashing with the following errors:
- The error when launching fuzzing with a learned model
TypeError: 'NoneType' object is not iterable
Fixed with characterizing_outputs() and find_cex().
- The issues in the fuzzing time (bembang time) are trying to create an LL_FEATURE_REQ packet with an invalid feature set flag. The error occurs because 'le_pwr_class' is not a valid flag in the LL_FEATURE_REQ packet definition. We tried to fix this with MCP + Claude Desktop.
I have also added a learning model from my favorite device, Xiaomi :)
- Xiaomi model
- Firmware (firmware/)
- Nordic nRF52840 Dongle
- Nordic nRF52840 Development Kit: s140_nrf52_6.1.1_softdevice + nrf52840_dk_firmware
- Framework
- learning execution (ble_learning.py)
- learning execution after establishing connection (ble_learning_connecting_start.py)
- fuzzing execution (ble_fuzzing.py)
- fuzzing execution after establishing connection (ble_fuzzing_connecting_start.py)
- BLE Tests
- Test for key size downgrade (pairing_max_key_size_test.py)
- Invalid connection request crash (connection_interval_crash.py)
- Multiple answers to version indication (multiple_version_ind_test)
- Entering unknown state (length_unexpected_state.py)
-
Nordic nRF52840 Dongle or Development Kit flashed with corresponding firmware
Flashing: You can use the programmer tool of the nRF Connect for Desktop application to flash the provided firmware on the Nordic nRF52840 Dongle or Nordic nRF52840 Development Kit.
The firmware is taken from the SweynTooth project.
-
Python 3.9
-
Python libraries pySerial, Scapy >=v2.4.5, AALpy >=1.1.7 and Colorama
Requirements installation:
sudo pip3 install -r requirements.txt
The learning-based fuzzing framework is a two-step procedure. First, you learn the behavioral model. Second, you execute the fuzzer with the previously learned model.
The learning procedure of a Bluetooth Low Energy (BLE) device can be executed via (ble_learning.py). The program requires the serial port name of the nRF52 device and the BLE address of the peripheral device (advertiser) that should be learned. Additionally, a file name for the learned model and the pcap log might be defined.
python3 ble_learning.py <serial_port> <advertiser_address> [<pcap|dot filename>]
Example:
python3 ble_learning.py /dev/ttyACM0 00:A0:50:00:00:03 CYBLE-416045-02
The program outputs the learning results after a successful learning procedure and saves the learned model to learned_model.dot
or to a dot-file with the provided filename. Furthermore, a pcap log with all performed queries is saved to learned_data.pcap
or to a file with the provided filename.
After the learning procedure, the fuzzing procedure of a Bluetooth Low Energy (BLE) device can be executed via (ble_fuzzing.py). The program requires the serial port name of the nRF52 device and the BLE address of the peripheral device (advertiser) that should be learned. Additionally, a file name for the learned model and the pcap log might be defined.
python3 ble_fuzzing.py <automaton_file> <serial_port> <advertiser_address> <data_directory> [<pcap_filename>]
Example:
python3 ble_fuzzing.py automata/cyble-416045-02.dot /dev/ttyACM0 00:A0:50:00:00:03 ./ cyble-416045-02
The fuzzer logs all performed queries in a report called fuzzing_report.txt
, which is saved in the provided data directory. A second report, fuzzing_cex_report.txt
, is created that contains all input sequences that led to counterexamples, the corresponding observed outputs, and the performed state analysis. Furthermore, for every found counterexample, a pcap log is created.
For BLE devices that should be learned/fuzzed after establishing a valid connection, use the ble_learning_connecting_start.py and ble_fuzzing_connecting_start.py scripts.
We provide scripts that enable a simple reproduction of found issues and anomalies.
Garbelini et al. presented CVE-2019-19193 which leads to crashes due to invalid values in the connection request.
Execution of exploit:
python3 consecutive_connection_crash.py <serial_port> <advertiser_address> [<pcap_filename>]
Execution of exploit:
python3 connection_interval_crash.py <serial_port> <advertiser_address> [<pcap_filename>]
Execution of exploit:
python3 connection_timeout_crash.py <serial_port> <advertiser_address> [<pcap_filename>]
Execution of exploit:
python3 connection_latency_crash.py <serial_port> <advertiser_address> [<pcap_filename>]
According to the BLE specification, an already answered version indication should not be answered again. The following script tests for the behavior on multiple version indications.
Execution of exploit:
python3 multiple_version_ind_test.py <serial_port> <advertiser_address> [<pcap_filename>]
Execution of exploit:
python3 pairing_max_key_size_greater_than_spec.py <serial_port> <advertiser_address> [<pcap_filename>]
Execution of exploit:
python3 length_rsp_terminates_connection.py <serial_port> <advertiser_address> [<pcap_filename>]
The CC2652R1 enters an unknown state if an invalid length request or response is performed. The following script shows the behavior when entering this unknown state.
Execution of exploit:
python3 length_unexpected_state.py <serial_port> <advertiser_address> [<pcap_filename>]
Antonioli et al. showed that the possibility of key downgrades enables the exploitation of KNOB attacks.
Execution of exploit:
python3 pairing_max_key_size_test.py <serial_port> <advertiser_address> [<pcap_filename>]
- SweynTooth: nRF52 driver, firmware and code snippets for BLE package construction
- AALpy: active automata learning library
- Scapy: BLE package parsing and composition
- Colorama: colored terminal text
- Andrea Pferscher and Bernhard K. Aichernig (Institute of Software Technology, Graz University of Technology) > OGs of this repo! Hey, I am just a fork with minor additions.