Classroom Glossary Public page

Lab 4: Bluetooth Classic + BLE Protocol RE

563 words

Chapter: 4 (Week 5) Duration: 3.5 hr Substrate: nRF52840 USB dongle + Python (bleak) + Wireshark; ANTSDR E200 optional Points: 8


Overview

Enumerate Bluetooth Low Energy devices, capture an authenticated BLE pairing exchange, and decode the GATT attribute hierarchy using the Wireshark BLE dissector and the bleak Python library.

Physical path: nRF52840 dongle for passive BLE capture; bleak for active GATT enumeration. Virtual path: lab4-ble-pairing.pcapng (pre-captured BLE pairing exchange).


Part 1: BLE Advertising Survey (30 min)

Physical path

Flash the nRF52840 dongle with the Wireshark BLE extcap firmware (see SETUP.md). In Wireshark, open the nRF52840 capture interface (advertising channel 37+38+39).

Run hcitool lescan in parallel:

sudo hcitool lescan --duplicates 2>/dev/null | head -30

Observe and record for 5 minutes:

  • Advertising PDU types seen (ADV_IND, ADV_NONCONN_IND, SCAN_RSP, ADV_DIRECT_IND)
  • Unique AdvA (advertising addresses) — distinguish public (OUI-based) vs. random (bit 6+7 of MSB byte)
  • Advertising data fields: device name, service UUIDs, manufacturer-specific data

Virtual path

Open lab4-ble-pairing.pcapng in Wireshark. Apply display filter btle. Answer the same questions from the capture.


Part 2: GATT Enumeration with bleak (45 min)

Identify a BLE device you have authority to enumerate (your phone with BLE developer mode, a smart bulb, a fitness tracker, or the instructor-provided lab BLE target). Get its BLE address from the scan in Part 1.

import asyncio
from bleak import BleakScanner, BleakClient

# First: scan for BLE devices
async def scan_ble():
    print("Scanning for BLE devices (5 seconds)...")
    devices = await BleakScanner.discover(timeout=5.0)
    for d in sorted(devices, key=lambda x: x.rssi, reverse=True):
        print(f"  {d.address:20s} RSSI={d.rssi:4d}  '{d.name}'")
    return devices

# Then: enumerate a specific device
async def enumerate_device(address):
    print(f"\nConnecting to {address}...")
    async with BleakClient(address, timeout=15.0) as client:
        print(f"Connected: {client.is_connected}")
        print(f"MTU: {client.mtu_size}")
        
        services = await client.get_services()
        for svc in services:
            print(f"\n  SERVICE: {svc.uuid}  ({svc.description})")
            for char in svc.characteristics:
                print(f"    CHAR: {char.uuid}  props={char.properties}")
                if 'read' in char.properties:
                    try:
                        val = await client.read_gatt_char(char.uuid)
                        print(f"      value (hex): {val.hex()}")
                        # Try UTF-8 decode
                        try: print(f"      value (text): {val.decode('utf-8')}")
                        except: pass
                    except Exception as e:
                        print(f"      read error: {e}")
                for desc in char.descriptors:
                    print(f"      DESC: {desc.uuid}  ({desc.description})")

asyncio.run(scan_ble())
# asyncio.run(enumerate_device("AA:BB:CC:DD:EE:FF"))  # replace with target address

Record the complete GATT service/characteristic inventory for your target device.


Part 3: BLE Pairing Capture (60 min)

Perform a BLE pairing (Just Works or Passkey Entry) between two devices you control (phone + laptop, or phone + instructor lab BLE peripheral). Capture the exchange with the nRF52840 sniffer in Wireshark.

The pairing exchange involves these PDU sequences:

1. ADV_IND (advertising) from peripheral
2. CONNECT_IND from central  connection established
3. SMP (Security Manager Protocol) PDUs:
   - Security Request (slave  master)
   - Pairing Request (master  slave)
   - Pairing Response (slave  master)
   - Pairing Public Key exchange (if LESC)
   - Pairing DHKey Check (if LESC)
   - Pairing Random (Passkey)
   - Pairing Confirm
   - Encryption Start (LL_ENC_REQ / LL_ENC_RSP)

In Wireshark, display filter: btle.data_header.llid (to isolate data-channel PDUs) and btatt (ATT layer, post-pairing GATT traffic).

Questions to answer from the capture:

  1. What pairing method was used? (Look at the SMP Pairing Request AuthReq flags: Bonding (bits 0-1), MITM (bit 2), SC (bit 3), Keypress (bit 4))
  2. What IO Capabilities did each device advertise? (SMP Pairing Request/Response IO Capability field: 0x00=DisplayOnly, 0x01=DisplayYesNo, 0x02=KeyboardOnly, 0x03=NoInputNoOutput, 0x04=KeyboardDisplay)
  3. Was Secure Connections (LESC / LE Secure Connections) used? (AuthReq SC bit)
  4. Is the ATT traffic after pairing encrypted? (Look at LL_ENC_RSP; subsequent data PDUs should show encrypted payload — Wireshark shows "Encrypted Packet" if you have not provided the LTK)

Virtual path

Use lab4-ble-pairing.pcapng. Answer the same four questions from the pre-captured exchange.


Part 4: Wireshark BLE Dissection (30 min)

From your capture (or the virtual-path file), identify and annotate:

  1. One ADV_IND frame: expand the advertising data; identify each AD Type field
  2. One SMP Pairing Request: expand all fields; note the AuthReq bits
  3. One ATT Read Request + ATT Read Response: what characteristic handle was read? What was the value?

Screenshot each in Wireshark with the frame tree fully expanded.


Deliverables

  • BLE scan output (from bleak or hcitool lescan): list of devices with addresses and names
  • GATT enumeration: complete service/characteristic inventory for your chosen device
  • Wireshark screenshots: (1) ADV_IND with advertising data expanded, (2) SMP Pairing Request, (3) ATT Read Request+Response
  • Written answers to the four pairing-capture questions
  • 1-paragraph security assessment: what could an attacker do with the ability to capture this pairing exchange? What pairing method would resist passive eavesdropping?

Grading (8 points)

Item Points
BLE scan output with ≥3 unique devices 1
GATT enumeration: complete service/char inventory 2
Wireshark screenshots (all three) 2
Four pairing-capture questions answered correctly 2
Security assessment paragraph 1