Mar 11, 2026 • Damien Cauquil
A Nerd's Life: Weeks of Firmware Teardown to Prove We Were Right
In a blog post published last December, we demonstrated how we managed to extract the firmware from a smartwatch by exploiting an out-of-bounds read...
Summary
In a blog post published last December, we demonstrated how we managed to extract the firmware from a smartwatch by exploiting an out-of-bounds read vulnerability and spying on its screen interface. Follow us on our long and unexpected journey to figure out how this smartwatch can measure heart rate or blood pressure with no visible sensor, the problems we encountered while analyzing its firmware, and how we solved them to uncover The Truth about this device.
Published Analysis
In a blog post published last December, we demonstrated how we managed to extract the firmware from a smartwatch by exploiting an out-of-bounds read vulnerability and spying on its screen interface. Follow us on our long and unexpected journey to figure out how this smartwatch can measure heart rate or blood pressure with no visible sensor, the problems we encountered while analyzing its firmware, and how we solved them to uncover The Truth about this device. Introduction This blog post is a follow-up to our previous post describing how we managed to extract the firmware of a smartwatch . It contains many references and details introduced in our previous post, readers are therefore advised to read it first. Soon after our successful firmware extraction stunt, we started analyzing the recovered binary blob to search for our watch's main application code. It quickly became clear that what initially looked like an easy task would definitely be harder to achieve, to say the least. But we were not expecting to spend weeks to make our way into the extracted data only to prove that this smartwatch's vital measurements cannot be trusted. Follow us deep into the White Rabbit's hole to discover why this watch is just a lie. Firmware teardown We managed to extract a 2-MB firmware from the target smartwatch and a quick analysis of its first bytes revealed it may contain some binary data related to the watch's main application through the presence of an app.bin text string. That was promising. Grigoryev's documentation describes various flash memory layouts and one of them seemed to particularly fit the structure of our extracted binary blob, JieLi's new firmware format 1 : Overview of JieLi's new firmware format. Our binary blob is a bit different but its header matches the documented structure composed of a finite number of file header structures: Offset Size in bytes Field name 0x00 2 Header CRC 0x02 2 Data CRC 0x04 4 Data offset 0x08 4 Data size (in bytes) 0x0C 1 File attributes (bits) 0x0D 1 RFU 0x0E 2 File index 0x10 16 File name We wrote a small Python script to parse this series of file headers, check CRC values, and display each file header. The results were as follows: JLFS.FileHeader(hcrc=0xf869, dcrc=0xb1b6, offset=0x01e00120, size=806828, name='app_area_head') JLFS.FileHeader(hcrc=0x20c3, dcrc=0x2d89, offset=0x00000120, size=805628, name='app.bin') JLFS.FileHeader(hcrc=0xb1c7, dcrc=0x16d3, offset=0x000c4c1c, size=912, name='cfg_tool.bin') JLFS.FileHeader(hcrc=0xf9c9, dcrc=0xff01, offset=0x000d7000, size=73728, name='VM') JLFS.FileHeader(hcrc=0x6821, dcrc=0xffff, offset=0x00000000, size=880640, name='PRCT') JLFS.FileHeader(hcrc=0x6e8c, dcrc=0xffff, offset=0x000e9000, size=4096, name='BTIF') JLFS.FileHeader(hcrc=0x7027, dcrc=0xffff, offset=0x000ea000, size=4096, name='EXIF') JLFS.FileHeader(hcrc=0xfcfe, dcrc=0xffff, offset=0x000eb000, size=753664, name='FATFSI') JLFS.FileHeader(hcrc=0x143d, dcrc=0xffff, offset=0x001a3000, size=375068, name='USERIF') Based on this output, we determined the following firmware image map: Offset Size in bytes Attributes File name 0x01E00120 806828 0x83 app_area_head 0x00000120 805628 0x82 app.bin 0x000c4c1c 912 0x82 cfg_tool.bin 0x000d7000 73728 0x12 VM 0x00000000 880640 0x92 PRCT 0x000e9000 4096 0x92 BTIF 0x000ea000 4096 0x92 EXIF 0x000eb000 753664 0x92 FATFSI 0x001a3000 375068 0x92 USERIF Splitting our firmware into sections Based on the recovered information, we only had to extract each file based on its file offset and size in a dedicated folder for further analysis. We did not extract the app_area_head special file as it simply defines the memory region where the data is stored, skipping the 0x120 bytes corresponding to its header (9 files x 32-byte header = 0x120 bytes). A first look at the app.bin file revealed that it does not seem to be encrypted, based on a Shannon entropy graph generated with binwalk , as shown below. Evolution of Shannon entropy in the app.bin file, per file offset. We were able to extract meaningful text strings from the app.bin file, which proved it was not encrypted. We observed the same behavior for the cfg_tool.bin file, but this was not the case for the remaining files. They looked compressed or encrypted, but their entropy was oscillating while one could expect it to stay close to 1 all along, maybe because some weak compression or encryption algorithm was used. Evolution of Shannon entropy of the FATFSI file, per file offset. Breaking JieLi's "encryption" The extracted FATFSI file was very intriguing because its name mentions "FAT", which usually stands for File Allocation Table . This is a quite old file system originally designed by Microsoft , and as many file systems, it may contain valuable data. Unfortunately, this file could not be read as-is as it seemed to be encrypted and/or compressed. Based on the amazing reverse-engineering work previously done by Grigoryev, we were able to figure out how these files were encrypted or more...