📜 ⬆️ ⬇️

As a team of schoolchildren on the hackathon, NASA performed a reverse-engineering of the fitness bracelet to control the drone



A year ago, I purchased a SONY SmartBand SWR10 fitness tracker. Like most other fitness trackers, the gadget did not play a big role in my life, its main occupation was to lie on my desk. However, this is an interesting electronic device, and when a friend invited me to join his team in the NASA Space Apps hackathon, I decided to use the tracker. We chose the section "Do not break my drone", where it was required to create a solution to control the drone. It was decided to use this tracker to control the drone.



As soon as the hackathon started, I began to search for my bracelet API or developer tools, but nothing was found. Some forum users said that SONY has a proprietary SDK, which is given to developers who have decided to cooperate with the company, but under the terms of the hackathon, only open-source solutions could be used. So I decided it was time to create my own drone management interface. I launched the tracker application, and turned on the “Bluetooth HCI snoop log” feature. This feature allowed you to sniff traffic and save a dump to an SD card.
')
I found a log:
~ adb shell echo $ EXTERNAL_STORAGE
/ sdcard
~ adb pull /sdcard/btsnoop_hci.log

And opened it in WireShark:



It seems that data transmission was carried out via the Bluetooth Low Energy protocol, or more precisely, via the GATT protocol. This is a two-way data transfer, where the phone acts as a server, the “GATT Server”, and the peripheral devices receive “GATT characteristics”, which can contain any binary data.

I chose the first UUID (00000208–37cb-11e3–8682–0002a5d5c51b), and searched it on Google. I expected to find the usual standardized GATT service, but found something more interesting .

I decided that we discovered someone's Git-repository, created by a man who carried out reverse-engineering of the protocol. And it was partly like this: the project contained several working functions, including connection, response to hand movement, reading battery status and keeping the connection active. But the implementation of the accelerometer was strange. I added accelerometer data to MPAndroidChart , and got this:



Although the slope information was correct, the values ​​were not displayed. After studying the function code, it turned out that the 32-bit single-precision number contained three 10-bit values. This makes sense, since most accelerometers work with 10-bit precision (like most ADC, analog-to-digital converters). Here are the initial data, pay attention to the first two bits:

acc data: 0b00101110 0b10110101 0b10111100 0b10111000
acc data: 0b00111010 0b11110001 0b00011101 0b11101011
acc data: 0b00111110 0b01110110 0b10100110 0b10011001
acc data: 0b00001011 0b11011101 0b10111101 0b00111001

But parsing the data as three 10-bit values ​​was rather strange, every few degrees of inclination changed the value from 511 to -512, and the offset did not change it (and there were no integer overflow problems here). So I decided that SONY could use some kind of proprietary binary packaging method, or the company uses arithmetic coding and compression.

I tried Protobuf, MsgPack, Thrift, and several parsers, but nothing worked. I had only a day to connect my device to the Wi-Fi drone. Already in despair, I tried the dex-decompilation of the company's application, and after half an hour, this was what happened:

// rough
1: iconst_0 512 iconst_1 1023
2: r1 xor iconst_0
3: istore_0
4: iload_0
5: ifneq 8
6: r1 xor iconst_1
7: istore_0

if ((data & 0x200)! = 0) {
data = - ((data ^ 1023) + 1);
}
return (((float) (-data)) * 15.625f) / GRAVITY_FACTOR;

The first half [0, 512] was inverted, so the situation described above arose. I fixed it using normal XOR, and everything worked out. I added the gravity factor, with the result [-1,1] for ± 1 g, and all I had to do next was to use the accelerometer data to control the drone.

Source: https://habr.com/ru/post/394095/


All Articles