Reverse Engineering Notes: Accu-Chek Mobile

A couple of years ago, upon suggestion by a reader of this blog, I switched my glucometer to an Accu-Chek Mobile by Roche. I have not even looked into reverse engineering it at the time, as the killer application of that meter was not needing software at all. Indeed all the data is made available over a USB Mass Storage interface as CSV and graphs.

While there is a secondary interface available on the device to connect to software on PC, you had to order a copy of the download software online and receive it physically to be able to download the data to a computer, which I still find kind of silly for a device that is designed to have a standard USB connector.

Things changed recently, as Roche joined Abbott (and probably more to come) on the bandwagon of “show us yours”: upload your blood glucose reading to their cloud systems, and they will help you managing diabetes. I guess this is what happens when people are not waiting. I’m not particularly fond of uploading my health information to the cloud, but signing up for this service also meant being able to grab a proper chatter of the protocol over USB.

The software I’m using right now for snooping over the USB connection is USBlyzer which is proprietary and closed source — I’m not proud, but it gets its job done. I have been thinking of switching of a hardware snooping solution, and I bought a BeagleBone Black to use for that, but I have not started working on that due to time.

So instead, I have collected over time a set of libraries and utilities that operate on the CSV files that the software export (particularly as with version 2.2 they are actually quite well written, the older version was messier to post-process). I should look into publishing this collection, and I promise I’ll give it a try to publish before end of this year.

One of the tools I have prints out the “chatter”, coded hexdumps with include direction information to make it easier for me to read the stream. The first run of it was a bit noisy, but a quick check told me that what I’m interested in is bulk transfers (rather than control transfers, which are the most basic), so I filtered for those only, and then the first thing became obvious very quickly.

The maximum length of the bulk transfers in the trace is 64 bytes, which corresponds to the maximum size of bulk transfers for full speed endpoints. But the chatter shows the device sending multiple packets back from a single command, which is not unusual, as you can’t fit much blood sugar data in 64 bytes. And as usual when there is fragmentation, the actual data transfer size is coded somewhere at the beginning of the message.

0023 >>>> 00000000: E3 00 00 2C 00 03 50 79  00 26 80 00 00 00 80 00  ...,..Py.&......
0023 >>>> 00000010: 80 00 00 00 00 00 00 00  80 00 00 00 00 08 00 60  ...............`
0023 >>>> 00000020: 19 00 01 08 00 00 00 00  00 01 01 01 00 00 00 00  ................

0025 <<<< 00000000: E7 00 01 0A 01 08 00 00  01 01 01 02 00 00 FF FF  ................
0025 <<<< 00000010: FF FF 0D 1C 00 F8 50 00  00 05 00 F2 00 06 00 01  ......P.........
0025 <<<< 00000020: 00 04 00 24 09 2F 00 04  00 02 71 BC 0A 46 00 02  ...$./....q..F..
0025 <<<< 00000030: F0 40 09 96 00 02 08 52  0A 55 00 0C 00 02 00 08  .@.....R.U......
0025 <<<< 00000040: 09 90 00 08 0A 4C 00 02  00 06 00 02 00 04 00 24  .....L.........$
0025 <<<< 00000050: 09 2F 00 04 00 02 71 D0  0A 46 00 02 F0 40 09 96  ./....q..F...@..
0025 <<<< 00000060: 00 02 08 52 0A 55 00 0C  00 02 00 08 09 90 00 08  ...R.U..........
0025 <<<< 00000070: 0A 4C 00 02 00 05 00 03  00 03 00 1E 09 2F 00 04  .L.........../..
0025 <<<< 00000080: 00 80 71 D8 0A 46 00 02  F0 40 0A 55 00 0C 00 02  ..q..F...@.U....
0025 <<<< 00000090: 00 08 09 90 00 08 0A 66  00 02 00 05 00 04 00 03  .......f........
0025 <<<< 000000A0: 00 1E 09 2F 00 04 00 80  72 48 0A 46 00 02 F0 48  .../....rH.F...H
0025 <<<< 000000B0: 0A 55 00 0C 00 02 00 08  09 90 00 08 0A 49 00 02  .U...........I..
0025 <<<< 000000C0: 00 3D 00 05 00 08 00 46  0A 4D 00 02 98 20 09 43  .=.....F.M... .C
0025 <<<< 000000D0: 00 02 00 00 09 41 00 04  00 00 17 70 09 44 00 04  .....A.....p.D..
0025 <<<< 000000E0: 00 00 01 E5 09 53 00 02  00 00 0A 57 00 12 00 10  .....S.....W....
0025 <<<< 000000F0: 50 61 74 69 65 6E 74 20  52 65 73 75 6C 74 73 00  Patient Results.
0025 <<<>>> 00000000: E7 00 00 0E 00 0C 00 01  01 03 00 06 00 00 00 00  ................
0047 >>>> 00000010: 00 00                                             ..

0049 <<<< 00000000: E7 00 00 F6 00 F4 00 01  02 03 00 EE 00 00 00 08  ................
0049 <<<< 00000010: 00 E8 09 28 00 0E 00 06  52 6F 63 68 65 00 00 04  ...(....Roche...
0049 <<<< 00000020: 31 32 30 35 09 84 00 0A  00 08 00 60 19 04 B5 1B  1205.......`....
0049 <<<< 00000030: DF 5C 0A 44 00 02 40 00  09 2D 00 78 00 04 00 74  ..D..@..-.x...t
0049 <<<< 00000040: 00 01 00 00 00 18 73 65  72 69 61 6C 2D 6E 75 6D  ......serial-num
0049 <<<< 00000050: 62 65 72 3A 20 30 30 31  38 32 36 36 35 32 00 04  ber: 001826652..
0049 <<<< 00000060: 00 00 00 14 73 77 2D 72  65 76 20 4D 45 3A 20 56  ....sw-rev ME: V
0049 <<<< 00000070: 30 33 2E 31 33 20 20 20  00 05 00 00 00 16 66 77  03.13   ......fw
0049 <<<< 00000080: 2D 72 65 76 69 73 69 6F  6E 3A 20 56 30 33 2E 39  -revision: V03.9
0049 <<<< 00000090: 30 20 20 20 00 06 00 00  00 1A 70 72 6F 74 6F 63  0   ......protoc
0049 <<<< 000000A0: 6F 6C 2D 72 65 76 69 73  69 6F 6E 3A 20 52 50 43  ol-revision: RPC
0049 <<<< 000000B0: 20 31 2E 30 09 87 00 08  20 17 02 24 21 07 00 00   1.0.... ..$!...
0049 <<<< 000000C0: 0A 45 00 10 C0 00 1F 00  FF FF FF FF 00 64 00 00  .E...........d..
0049 <<<< 000000D0: 00 00 00 00 0A 4B 00 16  00 02 00 12 02 01 00 08  .....K..........
0049 <<<< 000000E0: 01 05 00 01 00 02 20 11  02 02 00 02 00 00 0A 5A  ...... ........Z
0049 <<<< 000000F0: 00 08 00 01 00 04 10 11  00 01                    ..........

As you can see in this particular exchange, bytes at offset 2-3 represent a (big-endian) length for the whole transfer. You just keep reading until that is complete.

While I have not (yet at the time of writing) figured out what the command and response actually convey, one thing that is kind of obvious is that there is some kind of (type-)length-value encoding at play, although in a bit of a funny way.

All records with type 0xE700 appear to have two-level lengths, as you can see on the two responses and the second command: in red it’s the length of the packet, in magenta the same length minus two (which matches the size of the length itself). There are also a number of strings, some zero terminated (Roche) and some not (1205), but still encoded with a 16-bit length in front of them.

The next thing to figure out in these cases is whether there is a checksum or not. For effectively all the meters I have reverse engineered up to now, except for maybe the cheap Korean one, include a checksum somewhere. I checked the chatter and found that there are a number of packets that appear to include the same information, but adding a checksum to the packet showed them different.

Once I dumped the (recomposed) packets to binary files, I noticed a number of packets with the same sizes. hexdump, wdiff and colordiff make it very easy to tell what changed between them. It didn’t quite look like a cryptographic checksum, as changing one byte would replace it with a very different number, but it didn’t quite match up with a “dumb” checksum of all the bytes values.

A couple of diff later, it become obvious.

[flameeyes@saladin Accu-Chek]$ wdiff <(hexdump -C 0039-0034-in) <(hexdump -C 0049-0046-in) | colordiff
00000000  e7 00 00 f6 00 f4 00 [-2d-] {+01+}  02 03 00 ee 00 00 00 08  [-|.......-........|-]  {+|................|+}
00000010  00 e8 09 28 00 0e 00 06  52 6f 63 68 65 00 00 04  |...(....Roche...|
00000020  31 32 30 35 09 84 00 0a  00 08 00 60 19 04 b5 1b  |1205.......`....|
00000030  df 5c 0a 44 00 02 40 00  09 2d 00 78 00 04 00 74  |..D..@..-.x...t|
00000040  00 01 00 00 00 18 73 65  72 69 61 6c 2d 6e 75 6d  |......serial-num|
00000050  62 65 72 3a 20 30 30 31  38 32 36 36 35 32 00 04  |ber: 001826652..|
00000060  00 00 00 14 73 77 2d 72  65 76 20 4d 45 3a 20 56  |....sw-rev ME: V|
00000070  30 33 2e 31 33 20 20 20  00 05 00 00 00 16 66 77  |03.13   ......fw|
00000080  2d 72 65 76 69 73 69 6f  6e 3a 20 56 30 33 2e 39  |-revision: V03.9|
00000090  30 20 20 20 00 06 00 00  00 1a 70 72 6f 74 6f 63  |0   ......protoc|
000000a0  6f 6c 2d 72 65 76 69 73  69 6f 6e 3a 20 52 50 43  |ol-revision: RPC|
000000b0  20 31 2e 30 09 87 00 08  20 17 02 24 21 [-06 53-] {+07 00+} 00  | 1.0.... [-..$!.S.|-] {+..$!...|+}
000000c0  0a 45 00 10 c0 00 1f 00  ff ff ff ff 00 64 00 00  |.E...........d..|
000000d0  00 00 00 00 0a 4b 00 16  00 02 00 12 02 01 00 08  |.....K..........|
000000e0  01 05 00 01 00 02 20 11  02 02 00 02 00 00 0a 5a  |...... ........Z|
000000f0  00 08 00 01 00 04 10 11  00 01                    |..........|
000000fa
[flameeyes@saladin Accu-Chek]$ wdiff <(hexdump -C 0039-0034-in) <(hexdump -C 0073-0068-in) | colordiff
00000000  e7 00 00 f6 00 f4 00 [-2d-] {+02+}  02 03 00 ee 00 00 00 08  [-|.......-........|-]  {+|................|+}
00000010  00 e8 09 28 00 0e 00 06  52 6f 63 68 65 00 00 04  |...(....Roche...|
00000020  31 32 30 35 09 84 00 0a  00 08 00 60 19 04 b5 1b  |1205.......`....|
00000030  df 5c 0a 44 00 02 40 00  09 2d 00 78 00 04 00 74  |..D..@..-.x...t|
00000040  00 01 00 00 00 18 73 65  72 69 61 6c 2d 6e 75 6d  |......serial-num|
00000050  62 65 72 3a 20 30 30 31  38 32 36 36 35 32 00 04  |ber: 001826652..|
00000060  00 00 00 14 73 77 2d 72  65 76 20 4d 45 3a 20 56  |....sw-rev ME: V|
00000070  30 33 2e 31 33 20 20 20  00 05 00 00 00 16 66 77  |03.13   ......fw|
00000080  2d 72 65 76 69 73 69 6f  6e 3a 20 56 30 33 2e 39  |-revision: V03.9|
00000090  30 20 20 20 00 06 00 00  00 1a 70 72 6f 74 6f 63  |0   ......protoc|
000000a0  6f 6c 2d 72 65 76 69 73  69 6f 6e 3a 20 52 50 43  |ol-revision: RPC|
000000b0  20 31 2e 30 09 87 00 08  20 17 02 24 21 [-06 53-] {+07 02+} 00  | 1.0.... [-..$!.S.|-] {+..$!...|+}
000000c0  0a 45 00 10 c0 00 1f 00  ff ff ff ff 00 64 00 00  |.E...........d..|
000000d0  00 00 00 00 0a 4b 00 16  00 02 00 12 02 01 00 08  |.....K..........|
000000e0  01 05 00 01 00 02 20 11  02 02 00 02 00 00 0a 5a  |...... ........Z|
000000f0  00 08 00 01 00 04 10 11  00 01                    |..........|
000000fa
[flameeyes@saladin Accu-Chek]$ wdiff <(hexdump -C 0039-0034-in) <(hexdump -C 0087-0084-in) | colordiff
00000000  e7 00 00 f6 00 f4 00 [-2d-] {+04+}  02 03 00 ee 00 00 00 08  [-|.......-........|-]  {+|................|+}
00000010  00 e8 09 28 00 0e 00 06  52 6f 63 68 65 00 00 04  |...(....Roche...|
00000020  31 32 30 35 09 84 00 0a  00 08 00 60 19 04 b5 1b  |1205.......`....|
00000030  df 5c 0a 44 00 02 40 00  09 2d 00 78 00 04 00 74  |..D..@..-.x...t|
00000040  00 01 00 00 00 18 73 65  72 69 61 6c 2d 6e 75 6d  |......serial-num|
00000050  62 65 72 3a 20 30 30 31  38 32 36 36 35 32 00 04  |ber: 001826652..|
00000060  00 00 00 14 73 77 2d 72  65 76 20 4d 45 3a 20 56  |....sw-rev ME: V|
00000070  30 33 2e 31 33 20 20 20  00 05 00 00 00 16 66 77  |03.13   ......fw|
00000080  2d 72 65 76 69 73 69 6f  6e 3a 20 56 30 33 2e 39  |-revision: V03.9|
00000090  30 20 20 20 00 06 00 00  00 1a 70 72 6f 74 6f 63  |0   ......protoc|
000000a0  6f 6c 2d 72 65 76 69 73  69 6f 6e 3a 20 52 50 43  |ol-revision: RPC|
000000b0  20 31 2e 30 09 87 00 08  20 17 02 24 [-21 06 53-] {+20 55 15+} 00  | 1.0.... [-..$!.S.|-] {+..$ U..|+}
000000c0  0a 45 00 10 c0 00 1f 00  ff ff ff ff 00 64 00 00  |.E...........d..|
000000d0  00 00 00 00 0a 4b 00 16  00 02 00 12 02 01 00 08  |.....K..........|
000000e0  01 05 00 01 00 02 20 11  02 02 00 02 00 00 0a 5a  |...... ........Z|
000000f0  00 08 00 01 00 04 10 11  00 01                    |..........|
000000fa

It may become much clearer if you go back at the first dump and observe the part highlighted in blue: it’s 8 bytes that represent 20 17 02 24 21 07 00 00. To help understanding this, you should know that I was looking at this around 9pm on February 24th, 2017. Indeed, these bytes effectively represent the date and time in binary-coded decimal, which is not something I was expecting to see, but make sense.

Once you know this, it’s easy to tell that there is no checksum in the messages, and that is one less problem to worry about. Indeed, when looking for the “big” packets, I could find the telltale representation of fixed-size records with what looked like (and I confirmed being) glucometer readings (in mg/dL, even though the device is mmol/l based).

If you’re wondering why the peculiar change in time on the last part of the diff, the reason is quite simple: the software noted that the time on the device didn’t match the time on the computer, and asked me to sync it. Which means I also know the command to set the time now.

Looking at the commands, there are a few more things that are interesting to see:

0037 >>>> 00000000: E7 00 00 0E 00 0C 00 2D  01 03 00 06 00 00 00 00  .......-........
0037 >>>> 00000010: 00 00                                             ..

0047 >>>> 00000000: E7 00 00 0E 00 0C 00 01  01 03 00 06 00 00 00 00  ................
0047 >>>> 00000010: 00 00                                             ..

0071 >>>> 00000000: E7 00 00 0E 00 0C 00 02  01 03 00 06 00 00 00 00  ................
0071 >>>> 00000010: 00 00                                             ..

0081 >>>> 00000000: E7 00 00 1A 00 18 00 03  01 07 00 12 00 00 0C 17  ................
0081 >>>> 00000010: 00 0C 20 17 02 24 20 54  57 00 00 00 00 00        .. ..$ TW.....

0085 >>>> 00000000: E7 00 00 0E 00 0C 00 04  01 03 00 06 00 00 00 00  ................
0085 >>>> 00000010: 00 00                                             ..

0095 >>>> 00000000: E7 00 00 14 00 12 00 05  01 07 00 0C 00 05 0C 0D  ................
0095 >>>> 00000010: 00 06 00 01 00 02 00 00                           ........
      

The time change command is 0081 (and I highlighted in green the new time, also provided as BCD). The remaining commands appear to be querying some information about the device. Commands 0037, 0047, 0071 and 0085 are exactly the same, except as I found out initially, no packet was identical. In blue I highlighted what appears to be a packet counter of sorts. I’m not sure why it starts at 0x2D, but after that it appears to increment normally, although only after 0xE7 commands (there appear to be a handful more).

Unfortunately this does not cover enough of the protocol yet, but it’s a good starting point for a few hours spent trying to prod things around on a Friday night (what an exciting life I live). I also managed to find how the device is reporting the readings, in blocks of less than 1KB records, but I have not figure out how the software knows when to stop asking for them. In this case it definitely is handy that I have so many readings on the device — this is probably the glucometer I used the most, and I still think is the best blood-reading glucometer, for handiness and results.

Stay tuned for more details, and hopefully to see a spec for the protocol soon, too.

Glucometer review: Accu-Chek Mobile by Roche

This past summer I posted a review of the OneTouch Verio glucometer – a device to measure your blood sugar, for those who don’t know – and in the comments of the same, Daniel suggested me to look into the Accu-Chek Mobile meter as an alternative, which I did.

Before venturing in the actual review, I would like to take a moment to explain to people who might not have experience with glucometers, or that may be reading me during their early experience with them, on why the review of that particular meter is a good time to suggest a different one. Before the Verio, I have been using other OneTouch devices. The previous devices all shared the same strips (the most consumable part of the device), so moving from one to the other was painless and obvious. The Verio by design replaced the strips with a new technology, and the lack of compatibility means it’s the same as changing to a different meter brand. So Daniel was right at suggesting me to look into alternatives before stocking up on Verio consumables.

The Accu-Chek Mobile by Roche (UK link) is advertised as a “strip free.” This was one of the main reasons for me to consider this meter. While it still uses the same process (and the same finger blood sacrifice), it loads the reactive material on a winding tape on a cassette good for 50 tests. The end result is that you don’t have to do the whole dance of opening the bottle of strips, taking one out (which is not trivial sometimes), use it, then find a place to discard it. There’s no bottle, no strip, and no discard on a test-by-test basis.

To give you an idea of how much of a difference this makes, I have definitely improved my daily routine from 3-4 tests a day on two different meters (one kept at the office and one at home) to 4-6 on a single meter, and that has actually made for better decisions. I have not forgotten to resupply my office meter, or near-lost my strip bottle at an airport lounge (real story.) Believe me it’s much less embarrassing to test your blood in a restaurant with this device than with a good old strip meter.

Furthermore the lancing device is latched to the meter itself, which means you only have one piece of kit that you have to bring around daily. There are of course supplies to keep, but the fully stocked device is good for 50 strip-equivalents and six needles.

But this is not the only advantage of this device over the previous meters I used. If you remember, to be able to download data off the OneTouch devices I wrote a Python tool to do that. You can notice that I have no support for that device there, and the reason is that the device exposes itself as a (read-only) USB Mass Storage device, essentially a thumbdrive. And within that device you’ll find an HTML file with the interpreted data, broken down by time of the day, and day of the week, and even access to the raw data. All I need to do is to open the HTML file, export as PDF and send it to my doctor.

Moving on to the practicalities, once the cartridge is loaded in the device, you just need to open the door at the bottom of the device for it to load a new “strip”, then it signals you to provide blood. At first I had a bit of trouble timing it correctly: the notice on display to provide blood takes about two seconds to appear, because it first warns you to wash your hands. The trick is to wait for a red LED flashing through the strip instead. The amount of blood needed is bigger than the Verio but about the same as the old OneTouch models.

As I mentioned in passing earlier, the lancing device also has a cartridge system that includes six needles — you can discard one needle to move to the next by using the switch on the device itself, but this is of course a one-way system. Once the cartridge is removed from the lancing device it also can’t be put back, so you’ll have to discard it. Here’s where things got bothersome for me when I started using this meter: with the meter they gave me only two cartridges (twelve needles total), and while figuring out the device I removed the needles cartridge, so I had to discard an empty one right away. I went to the pharmacy the next day to pick up supplies and they gave me a box of needles cartridges too… which I did not try at that point, afraid I’d have to discard more. So I brought all of them with me to Paris on my following trip, only to figure out after removing the used needles that the box I was given is for a different model.

Accu-Chek Mobile meters exist in two models, the older and discontinued one used a lancing device called Multiclix, while the one I have is the newer one and has a lancing device called Fastclix. The only place on the device where that is written down (beside instruction manual and box, which I didn’t bring with me to the pharmacy) is on the side of the device, where it latches to the meter. So you have to take it out to read it.

Luckily for me, the FastClix supplies are easy to find in France too (and with even a bit more luck, the pharmacist I asked Pardonnez moi, je ne parle pas français, parlez-vous italien, s’il vous plait? happily told me she spoke Italian), so I got a new box of needles there. But it is a bothersome thing to realize that late in a trip.

Similarly to the Verio, the Accu-Chek Mobile uses two AAA batteries, which again are very easy to source; unlike the LifeScan meter, this does not make it bulky as the battery compartment is tiny and on the side of it, with a camera-like battery door on the top. While the actual volume might be about the same as the Verio, all in all the device is more compact and handier to travel with.

There are of course some snags with this system as well. The first one is that unlike LifeScan and Abbott meters, it was not obvious how to get the meter itself. I had a OneTouch back in Italy (through my sister who used it temporarily when pregnant) and I upgraded to an UK version (mmol/L) when I moved over here by just calling them up. From that to the Mini, and from the Mini to the Verio it was just an online form because I already had a previous version. The Abbott meter I have was given to me by my doctor’s local pharmacy, for free since Abbott makes the money on supplies as everyone else. But neither that pharmacy nor my local pharmacy stock Accu-Chek meters.

To get a hold of a meter I ended up signing up for a waitlist on Accu-Chek’s website. A few weeks later they sent me an email offering me to try the meter for free, and once I sent that out I received my device in the mail, which was cool. It came with a full cassette of fifty tests and two drums of lancets – as mentioned earlier I thrown out one of the drums right away unfortunately – which is a better “trial” than the other meters I had, that came with about a dozen tests, and I think a replacement lancet each.

Interestingly, the meter does not come with a case — every other meter I got came with its own soft case with a plastic holder inside shaped to hold only the device. In this case there is no such case, although arguably you don’t need one, as the meter is fully self contained: no need for a separate lancing device, no bottle of strips to carry around, no spare lancet. Instead, Roche gives you an option between a soft case (similar to the other meters) or a faux-leather hard case, similar to old Blackberry cases. But to get the case for free, you have to register the actual meter online, including serial number, and a few more tidbits, including the important question: “have you switched your prescription to Accu-Chek supply?” While all this kind of market research tends to be heavily flawed it does give them if not some feedback a way to suggest that to their new customers.

At the end I’m very happy with this new meter and I can recommend it for convenience. It seems reliable and consistent with the readings from the other devices (I ran them in parallel for a while.) And it’s quite nice to travel with. Plus it does not need a special software to download the data which is the killer for me.