BeLE - Hardwear.io 2022
BeLE - Hardwear.io CTF 2022
The challenge is named “BeLE” and says there are several BLE devices + provides a Bluetooth PCAP file.
PCAP file
The PCAP file is small with only 5 packets.
- The first packet is a BLE Read Request to read the BLE characteristic with handle 0x2a
02 10 00 07 00 03 00 04 00 0a 2a 00
- The second packet is a BLE Read Response. The characteristic has value
f3 dd 42 04 de ed c3 fc
|
|
- The third packet is a BLE Write Command on handle 0x48. We wrote value
05 55 d7 37 b7 ad 8a 17 a1 a8 b1 be c4 70 f9 fe
|
|
- The fourth packet is a BLE Read Request to read handle 0x39
02 10 00 07 00 03 00 04 00 0a 39 00
- The fifth packet is the BLE Read Response. It apparently contained the flag, but was redacted. The answer is
Flag_Here!
.
|
|
Investigating BLE devices
To discover BLE devices, there are many tools like bluetoothctl
, gatttool
or simply a Bluetooth scanner on smartphone.
We quickly spot the 2 BLE devices for the challenges, for example with bluetoothctl
and command scan on
|
|
We pick one of the devices, pair (pair 58:BF:25:9F:B9:36
) and connect (connect 58:BF:25:9F:B9:36
). Then, we list the services and characteristics.
The first few services (and their characteristics) are standard, and hold the device’s name. They are not interesting to solve the challenge.
|
|
The services which are specific to the devices hold characteristics at handle 0x29, 0x38 and 0x47. This always 1 less than the handles to actually read/write to. This is because in BLE the value of a characteristic is held in its own handle.
|
|
Note we can get the same results gatttool
or a smartphone BLE scanner. Actually, the results are often easier to read.
|
|
Attempts
We can read on handle 0x2a and 0x39, but can only write on handle 0x48. We attempt to replay the value of the pcap.
|
|
In handle 0x39, we read 4e 6f 70 20 21
which is ASCII for Nop !
. So, our input is incorrect and does not yield the flag.
We quickly notice that each time we write to 0x48, a new value is generated in 0x2a. So, probably this is a challenge / response mechanism:
- We are expected to read a challenge nonce on handle 0x2a
- We are expected to write the corresponding challenge response on handle 0x48
- If our response is correct, handle 0x39 will probably yield the flag.
Relation between challenge and response
The nonce is 8 bytes long. Too big to brute force and attempt numerous connections and hope to fall back on the nonce of the PCAP for which we have the correct answer.
The expected answers is 16 bytes long.
At this point, we went to have a look at the BLE devices. They are ESP32 devices. So, how could an ESP32 generate easily a 16-byte response? Encryption… Hash… SHA1? too long. MD5 produces the right output length.
|
|
The output is fef970c4beb1a8a1178aadb737d75505
.
This is exactly bytes 05 55 d7 37 b7 ad 8a 17 a1 a8 b1 be c4 70 f9 fe
but in the reverse order!
Flag
We connect once again to a BLE device and read the nonce:
|
|
Then we compute its MD5 value
|
|
The output is df5e543a2cbc43508be6d23dc06fa213
. If we reverse the order, it is 13a26fc03dd2e68b5043bc2c3a545edf
.
We write this response to the device:
|
|
Then we read the result on handle 0x39:
|
|
|
|
The answer is : FLAG{My_Ch4r_s3nd_4_ch4r_4rr4y!}
. We’ve got the flag :)
Troubles I didn’t mention
This challenge was relatively simple but took me more time than expected for several reasons:
At first, I wrongly extracted the payload of the BLE Write Command and thought we were sending
52 48 00 05 55 d7 37 b7 ad 8a 17 a1 a8 b1 be c4 70 f9 fe
. This is 19 bytes, and does not correspond to any known hash or encryption result length. I realized then my mistake, removed the 3 heading bytes (which actually contain the reference to handle 0x48) and kept the remaining 16 bytes.I didn’t immediately recognize the MD5 digest. Maybe it took me 5 minutes to see it was reversed. Although it was pretty obvious.
In the end, I was sure I had understood the correct challenge/response mechanism but faced many problems to connect back to the BLE device. Fortunately, I have worked with BLE before and know they are touchy, so I patiently tried again and again, checked I was not paired, asked the organizers to reboot the devices. At some point, I was able to connect with my smartphone, but it’s not easy to enter 16 bytes and I did it wrong and did not flag. I was still unable to connect from my laptop. I finally decided to reboot it, and it worked straight away afterwards: connect, get nonce, send response, collect flag :)