Jailbreaking the Microsoft fitness band

This semester I got a Microsoft fitness band for a project. The original goal was not hard: understand the client communication. So I decided to pwn it for fun. Thanks to my friends in OSIRIS lab who supported me a lot, thank you mates. And also my mentor, mongo, inspired me so much and taught me a lot, thanks man!

So first, we need to figure out some of the basic behaviours of the fitness band, like how it upgrades firmware, uploads user status etc. Luckily the client is just a windows binary, so we don’t need to set up environment to reverse the Android app or IOS app. The Windows client is available here. Since the client was written in c#, we can use tools like ILSpy, JustDecompile, dnSpy and dotPeek to debug & decompile it easily!

After reversing the client a bit, I found that the client downloads FirmwareUpdate.bin from the cloud and stores it into folder:

Now that I know where the firmware update will be, my next step was to try and get the binary itself. My device was already fully updated, so I needed to figure out a way to get it. Unfortunately, since our fitness band’s firmware is updated, I couldn’t download new firmware update anymore! Maybe I could cheat the sever?

modified version number
modified version number

I used Burp to modify the request’s version number to an older one and got it to download FirmwareUpdate.bin successfully, which allowed me to continue on to the more interesting stuff. First I needed to analyze the FirmwareUpdate.bin a bit.

After searching online for formats similar to what binwalk shows, I found nothing interesting, so I decided to reverse the FirmwareUpdate.bin format and make guesses on what the different sections of the binary were for. I noticed that the FirmwareUpdate.bin size, 0x16D67E bytes, was stored in the header at offset 0x13:

Since binwalk said there was a CRC32 polynomial table, I decided to look for the 4 byte CRC checksum that would be included in the header for integrity checking. You can see in the header that there are four “random” bytes of data at 0x17,  0x431E23C3. After replacing those 4 bytes with ‘\0’ and calculating the CRC for the rest of the data, we got the exactly same value:

So it seems that the binary might be using the CRC checksum to check the FirmwareUpdate.bin’s integrity! My next step was to try pushing modified firmware to the fitness band. I modified version number stored in FirmwareUpdate.bin as a test, to see if the fitness band would accept an arbitrarily modify FirmwareUpdate.bin. The version number was an easy way to see if the fitness band accepted the modified update, as you could easily check it on the band itself.

Unfortunately I realized that any time you start the updating process, the client would check to ensure that the firmware update has not been corrupted/tampered with. To bypass this, I used Dnspy to set break points and modify the binary right before the client sent it to the fitness band.

C# function that sends the firmware update to the fitness band

However after finishing the process, I didn’t see the firmware installing screen on the fitness band’s screen, which meant it failed. It seemed like they had other mechanisms to check the firmware update’s integrity. This meant that I had to go back to reversing the firmware update, which seemed to have some code in the chunks that binwalk identified as LZMA data. The first issue was that I didn’t know the loading address of the file. After reading up a bit about Reversing Embedded ARM of Cortex M Series, I luckily found a table that contains the correct loading address of 0x05c8bf!

Finally I was able to drop the binary into IDA. By searching for uses of immediate value 0x17(offset of CRC position), I found the main CRC checking function, and by getting cross references to it I found the IntegrityCheck function, as well as other checking functions. The whole Integrity checking procedure is:

    1.check main CRC

MainCRCCheck at 000633AE
MainCRCCheck at 000633AE

    2.check section CRC

SectionCRCCheck at 00061934
SectionCRCCheck at 00061934

    3.check if update’s version number bigger than original one

VersionCheck at 00061906
VersionCheck at 00061906

So all I had to do was patch the version number to be bigger than the one currently on the fitness band, patch the firmware update with whatever else I wanted, and recalculate the section CRCs, which I found the locations of based on the reversed code, and the main CRC.

For convenience, I wrote a parser for some of the binary format of the bin,

Next I wrote a simple patcher to patch the version number first, and then search for & patch the string I want to modify.

You can find the scripts on my github.

After patching the update, I used the same method as above to push the patched update to the device,

 

push patched FirmwareUpdate
pushing the patched update

After the device receives the file, it checks its integrity, and if the new update passes all the checks, you will see the installing sign like this:

installing
installing

And then the fitness band will reboot and you can check the version number and anything else that was patched.

version number
version number
pwned
pwned

With this you can then modify any of the code and data in the update to whatever you like!

I have not bought a Microsoft fitness band 2 to test if the jailbreak will work on it yet. For people who are interested in looking into this further, there is an interesting function in the fitness band windows client, but you need to unblock it first!

If you see any mistakes in my article, please let me know, thanks!

17 thoughts on “Jailbreaking the Microsoft fitness band

Do you think it’d be possible to make the band play movies? I don’t it’d be kinda pointless since the band doesn’t play sound but it’d still be cool
Thanks

Leave a Reply

Your email address will not be published. Required fields are marked *