virtualabs / btlejack

Bluetooth Low Energy Swiss-army knife
MIT License
1.87k stars 196 forks source link

Can not follow the packet exchange between two RaspberryPi's running bleno and noble: Connection lost #46

Closed JuliaChelysheva closed 3 years ago

JuliaChelysheva commented 5 years ago

Hello, thank you a lot for this great sniffing tool for Bluetooth Low Energy Devices.

some short introduction to my problem: I have one RaspberryPi 3B (Jessie) running noble as a central device and the second RaspberryPi as a peripheral device running bleno. I installed btlejack on the third RaspberryPi and attached three Microbits to it for sniffing the BLE connection between two RaspberryPi's (Model 3B with the Bluetooth Version 4.1, BlueZ Version 5.50).

I have already made some good experiences with btlejack using one RaspberryPi as a peripheral and an Iphone running BLE App as a central: I could sniff the established connection and could follow all the packets being transmitted between my peripheral PaspberryPi and my central Iphone while writing the characteristics to my RaspberryPi via nRF-Connect IOS App. I also could hijack the connection.

The goal of my small project is to build a BLE application between two RaspberryPi's in the way, that they can temporary Exchange LL data packets (PDU's), there are some codes available for noble/bleno where we can connect the devices and send a data string in a loop with counter. I need to have packets transmitted all the time, so I can sniff this connection with btlejack and hijack it. After that I need to improve the connection security in Bluetooth LE 4.2 to prevent it from being hijacked with btlejack.

I have already tried lots of connection examples running Node.js libraries noble and bleno, and also tried to use hcitool and gatttool options, but I wonder why the transmitted packets while sending data string to my peripheral can be captured all the time if I am using one peripheral running noble and the central running iOS BLE App, but with two RaspberryPi's running bleno and noble I only can see the packets at the moment of the connection request and when the characteristics will be discovered.

After some seconds the characteristics of the connected peripheral were discovered, I get the message from btlejack "connection lost", although the data string from my central device will still be sent in the loop with counter to the central device.

When sniffing the connections with btlejack –s, I still can see the access address I got from the command btlejack –c any as the connection was established, but when I then try to follow this connection with btlejack –f I also get the reply „connection lost“.

Maybe I am missing something in my implementation? Maybe you could suggest the reason why the data exchange between two devices running noble and bleno can not be followed by btlejack in this case? I also set a longer timeout with -n function but did not see the difference.

Some code and outputs from bltejack:

  1. Central device running noble to send a data string to the peripheral in short intervals:

    pi@raspberrypi:~/ble/node_modules/noble $ sudo node central_sending_string.js
    Scanning
    Connecting to 'echo' b827ebdcc4bb
    Connected to b827ebdcc4bb
    Discovered services and characteristics
    Sending:  'test string: 1'
    Subscribed for echoCharacteristic notifications
    Received: "test string: 1"
    Sending:  'test string: 2'
    Received: "test string: 2"
    Sending:  'test string: 3'
    Received: "test string: 3"
    Sending:  'test string: 4'
    Received: "test string: 4"
    ….
  2. Peripheral device running bleno accepts the data string being sent from the central device:

pi@raspberrypi:~/ble/node_modules/bleno/examples/echo $ sudo node main.js
bleno - echo
on -> stateChange: poweredOn
on -> advertisingStart: success
EchoCharacteristic - onSubscribe
EchoCharacteristic - onWriteRequest: value = 7465737420737472696e673a2031
EchoCharacteristic - onWriteRequest: notifying
EchoCharacteristic - onWriteRequest: value = 7465737420737472696e673a2032
EchoCharacteristic - onWriteRequest: notifying
….
  1. I found the access address of the connection with btlejack -c any and can see some packets still being transmitted with this access address:
pi@raspberrypi-sniffer:~ $ btlejack -s
BtleJack version 1.3
[i] Enumerating existing connections ...
[ - 53 dBm] 0x50656c18 | pkts: 1
[ - 48 dBm] 0x50656c18 | pkts: 2
[ - 47 dBm] 0x50656c18 | pkts: 3
[ - 48 dBm] 0x50656c18 | pkts: 4
[ - 47 dBm] 0x50656c18 | pkts: 5
[ - 47 dBm] 0x50656c18 | pkts: 6
[ - 46 dBm] 0x50656c18 | pkts: 7
^C[i] Quitting
  1. following the connection of my devices: connection lost:
pi@raspberrypi-sniffer:~ $ btlejack -f 0x50656c18
BtleJack version 1.3
[i] Using cached parameters (created on 2019-07-09 14:55:11)
[i] Detected sniffers:
 > Sniffer #0: fw version 1.3
 > Sniffer #1: fw version 1.3
 > Sniffer #2: fw version 1.3
[i] Synchronizing with connection 0x50656c18 ...
✓ CRCInit: 0xd9cb7e
✓ Channel Map = 0x000003ffff
✓ Hop interval = 54
✓ Hop increment = 14
[i] Synchronized, packet capture in progress ...
LL Data: 12 17 13 00 04 00 1b 0c 00 74 65 73 74 20 73 74 72 69 6e 67 3a 20 37 39 38
[!] Connection lost.
[i] Quitting

Any help or ideas would be very appreciated, thank you very much!

virtualabs commented 5 years ago

Hi,

The channel map recovered by btlejack is suspicious. I would check the recovered hop interval value computed while using the -f option against the one captured with -c any option. IMHO, these values do not match as your Raspberry Pis may use a default value greater than the one supported by default by btlejack. By the way, check if the provided channel map at connection time equals the one recovered with -f option.

JuliaChelysheva commented 5 years ago

Hello @virtualabs ,

thanks for your prompt reply. I checked the values and can confirm that the recovered hop interval had changed from the value 12 as I used the -c option to the value 54 after using -f option. The channel map value has also changed from 1fffffffff to 0x1ffffffffd.

Do you maybe know how could I change the default hop interval value of my Raspberry Pi, if it is possible and if it could solve the problem? I read some parts of the BLE Core Specification and searched for the information, but I only found out that the CONNEQ_REQ packet contains the hop increment value and still do not know how I could change it.

Some of my output snippets with the changed hop interval value and channel map:

  1. finding the new connection between two RaspberryPis:
pi@raspberrypi-sniffer:~ $ btlejack -c any
BtleJack version 1.3
[i] Detected sniffers:
 > Sniffer #0: version 1.3
 > Sniffer #1: version 1.3
 > Sniffer #2: version 1.3
LL Data: 05 22 00 8a c2 eb 27 b8 bb c4 dc eb 27 b8 62 7c 65 50 3c a5 c0 03 02 00 0c 00 00 00 c8 00 ff ff ff ff 1f 0c
[i] Got CONNECT_REQ packet from b8:27:eb:c2:8a:00 to b8:27:eb:dc:c4:bb
 |-- Access Address: 0x50657c62
 |-- CRC Init value: 0xc0a53c
 |-- Hop interval: 12
 |-- Hop increment: 12
 |-- Channel Map: 1fffffffff
 |-- Timeout: 2000 ms
LL Data: 0f 06 0c 07 0f 00 09 22
LL Data: 07 09 08 1f 00 00 00 00 00 00 00
LL Data: 0f 09 0e 1f 00 00 00 00 00 00 00
LL Data: 0b 06 ff 01 01 00 00 00
LL Data: 07 09 09 1f 00 00 00 00 00 00 00
LL Data: 0f 09 09 1f 00 00 00 00 00 00 00
LL Data: 06 07 03 00 04 00 02 00 01
LL Data: 0f 06 ff 02 01 00 00 00
LL Data: 1e 10 0c 00 05 00 12 01 08 00 28 00 38 00 00 00 c8 00
LL Data: 02 07 03 00 04 00 03 00 01
LL Data: 07 18 0f 28 00 38 00 00 00 c8 00 0c 08 00 15 00 ff ff ff ff ff ff ff ff ff ff
LL Data: 1a 0a 06 00 05 00 13 01 02 00 00 00
LL Data: 03 03 11 0f 1a
LL Data: 00 04 00 10 01 00
LL Data: 0b 0c 00 03 11 00 36 00 00 00 c8 00 11 00
LL Data: 18 06 00 09 00 01 18 0a
LL Data: 06 0b 07 00 04 00 10 0e 00 ff ff 00 28
LL Data: 02 09 05 00 04 00 01 10 0e 00 0a
LL Data: 06 0b 07 00 04 00 08 0a 00 0d 00 03 28
LL Data: 02 0d 09 00 04 00 09 07 0b 00 1a 0c 00 0e ec
LL Data: 06 0b 07 00 04 00 08 0d 00 0d 00 03 28
LL Data: 02 09 05 00 04 00 01 08 0d 00 0a
[!] Connection lost, sniffing again...
  1. recover and follow this connection:
btlejack -f 0x50657c62
BtleJack version 1.3

[i] Using cached parameters (created on 2019-07-10 13:19:07)
[i] Detected sniffers:
 > Sniffer #0: fw version 1.3
 > Sniffer #1: fw version 1.3
 > Sniffer #2: fw version 1.3

[i] Synchronizing with connection 0x50657c62 ...
✓ CRCInit: 0xc0a53c
✓ Channel Map = 0x1ffffffffd
✓ Hop interval = 54
✓ Hop increment = 12
[i] Synchronized, packet capture in progress ...
LL Data: 12 17 13 00 04 00 1b 0c 00 74 65 73 74 20 73 74 72 69 6e 67 3a 20 35 36 32
[!] Connection lost.
[i] Quitting
  1. trying to recover the connection again, channel map value has changed again, hop interval is 54:
btlejack -f 0x50657c62
BtleJack version 1.3

[i] Using cached parameters (created on 2019-07-10 13:20:09)
[i] Detected sniffers:
 > Sniffer #0: fw version 1.3
 > Sniffer #1: fw version 1.3
 > Sniffer #2: fw version 1.3

[i] Synchronizing with connection 0x50657c62 ...
✓ CRCInit: 0xc0a53c
✓ Channel Map = 0x1ff7fffffd
✓ Hop interval = 54
✓ Hop increment = 12
[i] Synchronized, packet capture in progress ...
[!] Connection lost.
[i] Quitting

Thank you in advance!

virtualabs commented 5 years ago

Okay, so I think your device changes the hop interval once a connection is established (and that's normal, most of them do so to save power). Hop interval is generally low to speed up the discovery process, and then set high to save power. I've seen some devices use a hop interval of 6 at connection time, and then switch to 20 (and sometimes more !) once the discovery is over.

You are not the only one who have experienced this behavior, this is why the -n option has been added. This option allows you to set a timeout (in milliseconds) for channel map recovery in order to make it more efficient (but it will take more time to complete). By default, btlejack spends 2 seconds max per channel, so if you increase this timeout you would be able to get a reliable channel map and then to follow this connection. Try a 4 seconds timeout first, and see if you get better results.

$ btlejack -f 11223344 -n 4000 

Another possible issue you may face is that one of your Rasps is changing regularly the channel map in use, updating it quicker than it takes you to figure out this channel map. But it is less likely IMHO.

JuliaChelysheva commented 4 years ago

Thank you @virtualabs , I managed this issue by configuring the connection intervals on my RaspberryPis by editing these values:

minimal connection interval maximal connection interval

I just edited these files on both Linux systems:

sudo nano /sys/kernel/debug/bluetooth/hci0/conn_min_interval sudo nano /sys/kernel/debug/Bluetooth/hci0/conn_max_interval

and used smaller values (for example 6 for min and 20 for max instead of bigger standart values. But these files will be overwritten on a reboot, so it is a good idea to write a small script which makes this configuration on every system start if needed.

Following the connection with smaller connection parameters seems to be easier and btlejack does not lose the connection. Sometimes the increased supervision timeout did not help with bigger connection intervals as well. But most of the time it works with standart connection parameters as well, if the microbits are positioned directly between two devices (not sure if it makes sence, but that is what I noticed in many tests). :-)

virtualabs commented 3 years ago

Issue is fixed, thank you for your feedback and the additional remarks !