Wiki / Protocols

Bluetooth HCI

The interface between a Bluetooth host stack and its controller, and the capture format that makes it the most useful place to record Bluetooth traffic.

Where HCI sits
Application
Host stack (GATT, ATT, L2CAP, SMP)
HCI, the recording point
Link encryption lives in the controller, below HCI. Everything a snoop records at HCI is therefore plaintext, including the Security Manager key distribution that an over-the-air sniffer only ever sees as ciphertext.

HCI, the Host Controller Interface, is the boundary between the two halves of every Bluetooth implementation. The controller owns the radio, the link layer and the encryption engine; it is the chip. The host owns L2CAP, ATT, GATT and the Security Manager; it is the operating system. HCI is the command and event protocol they speak across whatever wire joins them, and it is the single most productive place to record Bluetooth traffic.

What it is

Four packet types cross the interface, each with a one-byte type indicator in the H4 transport:

Type Direction Carries
0x01 Command host to controller "start scanning", "connect to this address", "enable encryption"
0x02 ACL data both L2CAP, and therefore ATT, GATT and SMP
0x03 SCO data both Classic audio
0x04 Event controller to host command results, connection complete, advertising reports, key requests

Most of BLE reconnaissance arrives as one event: LE Meta, sub-event Advertising Report, one per advert the controller heard, carrying the address, the address type, the RSSI and the advertising data. Everything a scanner shows you is a rendering of those.

Captures come in a few shapes and the difference matters when a tool refuses a file:

  • H4 is the raw transport: type byte then the packet. DLT_BLUETOOTH_HCI_H4 is 187.
  • H4 with pseudo-header adds a four-byte direction field in front, so a reader can tell sent from received. DLT_BLUETOOTH_HCI_H4_WITH_PHDR is 201, and it is what most tooling writes.
  • btsnoop is the container Android's btsnoop_hci.log uses, and Wireshark opens it directly.
  • btmon / monitor is the Linux kernel's richer format, with timestamps and decoded metadata.

Why it matters

The decisive property is where HCI sits: above link encryption. Encryption happens inside the controller, so anything recorded at HCI is recorded before it is encrypted or after it is decrypted. In practice that means an HCI snoop hands you things an air sniff never will:

  • The Security Manager key distribution in clear, LTK and IRK included.
  • Every ATT operation, encrypted link or not.
  • The host's own commands, which tell you what the application was trying to do rather than only what came out of the antenna.

The other side of that coin is that an HCI snoop only records the traffic of the device you took it on, and it needs access to that device. An air sniff sees everybody, and understands nothing that is encrypted. The two capture types answer different questions, and knowing which one you are holding is the first thing to establish about any Bluetooth artifact.

How to work with it

# Linux, live, decoded, and write a capture at the same time
btmon -w capture.btsnoop

# Or the older path
hcidump -w capture.hcidump

# Android: turn on "Enable Bluetooth HCI snoop log" in developer options,
# reproduce, then pull it out of the bug report
adb bugreport bug.zip     # btsnoop_hci.log is inside

# Reading, either way
tshark -r capture.btsnoop -Y 'btatt || btsmp'
tshark -r capture.btsnoop -Y 'bthci_evt.code == 0x3e'   # LE Meta events

Scapy reads and writes these too: HCI_PHDR_Hdr / HCI_Hdr / ... builds the H4-with-phdr shape, which makes an HCI capture a practical thing to synthesise as well as to analyse.

Pitfalls

  • Advertising reports are the controller's summary, not the air. Duplicate filtering, scan-response merging and the controller's own RSSI handling all happen before you see them. Timing and repetition are not faithful to the air interface.
  • Direction is not always recorded. Plain H4 (187) has no direction field, so a tool can only guess from the packet type. Prefer 201 or btsnoop when you can choose.
  • An HCI snoop is a device's diary, not a room's. It contains what your host did and heard, and nothing about a connection between two other devices.
  • The snoop log is often stale or truncated. Android's rotates and is capped; if the interesting event is missing, it usually rolled off rather than never happened.
  • Handles are per connection and get reused. A connection handle in one part of the log is a different connection later. Track them across the Connection Complete and Disconnection Complete events.

Further reading