Obtaining and Modifying Firmware for the Striiv Fusion

A poor decision was made and I am now the owner of five Striiv Fusion fitness trackers. With a few spares to brick, I wanted to see how far I could get meddling with the tracker’s firmware.

First, I needed to obtain the firmware image. The companion smartphone app is capable of performing an over-the-air update of the tracker, so I tried to learn how the app obtains these updates.

Sniffing the iOS app’s traffic, I could see the tracker’s firmware version being sent during a software update check, but the server answered with a 204 No Content response—the software is already the latest version.

After a few failures modifying the update check request to include an out-of-date version number to see if the server would send me new firmware, I discovered I needed to use one of the earlier version numbers from the release notes. Then:

{
  "forced_update": true,
  "binary": "UEsDBBQAAAAAAFGL...",
  "zipped": true
}

The update check API responds with a Base64-encoded Zip file containing a binary file called MCU.bin.

Binwalk was not able to identify any part of the binary, but after a lot of sleuthing and an extraordinarily clumsy teardown, I was able to identify the Nordic Semiconductor nRF51422-QFAAE0 system-on-chip I had previously misidentifed the SoC which has an ARM Cortex-M0 core. Given the correct architecture, Ghidra’s aggressive instruction finder analysis is able to locate executable code within the plain binary format file.

I have identified a few C standard library routines and toyed, unsuccessfully, with using Ghidra’s Function ID to attribute symbol names to some of the interesting functionality. Still, I wanted to try sending a modified firmware image to the tracker to see if firmware validation would be an obstacle. So I made a small change to one of the strings.

To send the patched firmware to the tracker, I wrote an add-on script for mitmproxy that intercepts the app’s software update check and responds with my own binary.