I've been trying to get ahold of the firmware for a Fitbit Charge that I got recently. Since the device is sealed, I've been trying to see if I can get it to update its firmware and then analyze that.

Using mitmproxy, I was able to capture two "check for updated firmware" requests from the Mac desktop app. The requests are made by sending base64 encoded blob to the URL:


(Note: you can only access this after being authenticated)

The two requests I've seen so far:

Request #1:



0000000: 3102 0000 0100 3b0a 0000 d1c9 8430 1a08  1.....;......0..
0000010: 8876 c53f 4e07 5276 1a9a 8de5 2acd b0a7  .v.?N.Rv....*...
0000020: b276 7382 8031 b4d0 74dd d114 812c 1b11  .vs..1..t....,..
0000030: b5cb c9be 3af0 91e9 6053 431c c8aa ecc0  ....:...`SC.....
0000040: 6528 dc92 72b7 03d3 b06d f307 bddb 03d9  e(..r....m......
0000050: 45a2 63f0 acc2 9985 703e 5eab ec61 8214  E.c.....p>^..a..
0000060: 2e2f 366d 9245 13f5 b71f 95ae e653 6293  ./6m.E.......Sb.
0000070: 0d8b c88a 9438 8d43 d72c 179d 1403 740c  .....8.C.,....t.
0000080: 6f76 87c5 8b1f 18d3 7e00 00              ov......~..

Request #2:



0000000: 3102 0000 0100 490a 0000 d1c9 8430 1a08  1.....I......0..
0000010: 69bb 39ee 7a8c d98b 43af b9bc d76f 0b5e  i.9.z...C....o.^
0000020: d368 519e ff14 3361 837d fa76 63c3 1bca  .hQ...3a.}.vc...
0000030: 14b2 a97f 2238 e2d6 3d3f 1b78 8e9a a4cd  ...."8..=?.x....
0000040: b68d e41f 3c97 12e1 31b7 ac17 192e 2968  ....<...1.....)h
0000050: 16ed d178 4001 fe89 ef2c 336b 3327 8ac8  ...x@....,3k3'..
0000060: 8ee0 9f7e 9df2 2e93 007a 2232 7219 10d2  ...~.....z"2r...
0000070: 1be2 ca36 2788 f1b0 d97f 2701 550c 2970  ...6'.....'.U.)p
0000080: e9d4 4790 32e3 f631 7e00 00              ..G.2..1~..

Unfortunately, the body of these requests seems to be encrypted somehow (relatively uniform byte distribution aside from the first 16 bytes and the last 3).

I also tried using mitmproxy to send slightly modified versions of the base64 data (flipping a bit in the body, changing some of the header data, etc.), but any changes cause the server to respond that the data is invalid.

So, any ideas how I can trick the server into sending me a firmware update?

2 Answers 2


So, any ideas how I can trick the server into sending me a firmware update?

Reverse engineer the desktop app, find where it's pulling your device's firmware number (probably 80 since that's the current firmware version), and change it to a lower number before it encrypts that data and sends the query to the server.

  • 1
    You'll probably have to reverse the desktop app anyway, since, if the request is encrypted, it's reasonable to assume the reply will be encrypted as well. So, just waiting for the next firmware update won't help you much. Commented Feb 27, 2015 at 7:59
  • Having done some more RE on the apps, it appears that the data is encrypted on the device itself and then sent to the server without decryption. I still need to verify that this is really the case, but if so it may be very difficult to get a copy of the firmware without taking the device apart. Commented Mar 2, 2015 at 19:32

this is not really an answer but some more info on the topic someone may find usefull...

i decompiled the fitbit apk for android and found this:


I thought i was getting somewhere, possibly a way to decode the bytes sent by the server you posted above:

        byte[] b(byte abyte0[])
            char ac[] = (new String(abyte0)).toCharArray();
            ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();
            int i1 = ac.length;
            for (int j1 = 0; j1 < i1; j1 += 2)
                Object aobj[] = new Object[2];
                aobj[0] = Character.valueOf(ac[j1]);
                aobj[1] = Character.valueOf(ac[j1 + 1]);
                bytearrayoutputstream.write(Integer.parseInt(String.format("%c%c", aobj), 16));

            return bytearrayoutputstream.toByteArray();

But it doesn't seem to make any sense, or at least i don't see how this part can possibly make a valid hex and then a byte out of those two char:

bytearrayoutputstream.write(Integer.parseInt(String.format("%c%c", aobj), 16));

I put some code that can be run online in here: http://ideone.com/UaOzpI

If somebody can make sense out of it please answer!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.