Dumping Encrypted-At-Rest Firmware Of Xiaomi Smart Kettle [Hackaday]

View Article on Hackaday

The microcontroller described in the article, on the PCB taken out of the kettle

[aleaksah] got himself a Mi Smart Kettle Pro, a kettle with Bluetooth connectivity, and a smartphone app to go with it. Despite all the smarts, it couldn’t be turned on remotely. Energized with his vision of an ideal smart home where he can turn the kettle on in the morning right as he wakes up, he set out to right this injustice. (Russian, translated) First, he tore the kettle down, intending to dump the firmware, modify it, and flash it back. Sounds simple enough — where’s the catch?

This kettle is built around the QN9022 controller, from the fairly open QN902X family of chips. QN9022 requires an external SPI flash chip for code, as opposed to its siblings QN9020 and QN9021 which have internal flash akin to ESP8285. You’d think dumping the firmware would just be a matter of reading that flash, but the firmware is encrypted at rest, with a key unique to each MCU and stored internally. As microcontroller reads the flash chip contents, they’re decrypted transparently before being executed. So, some other way had to be found, involving the MCU itself as the only entity with access to the decryption key.

The board from the kettle, with a USB-UART connected to it[aleaksah] considered the SWD interface, a powerful debug interface and a fairly common go-to for internal data access of many MCUs. Sadly, this microcontroller has lock bits for blocking SWD, intended to be set as your product leaves the factory floor. Of course, not every manufacturer sets those bits, but after checking the SWD interface anyway, it wouldn’t respond, and he decided to go the other way. He rejoiced, finding documentation on the MCU’s internal bootloader, and decided to load his own code into RAM that would dump the flash contents from the inside. However, the read command seems to have triggered the bootloader to either scramble or erase the flash, leaving him with a dead unit.

He persevered, and decided to study the bootloader code itself, loading yet another RAM stub that would dump the bootloader code. After decompiling the bootloader, apart from a few undocumented but uninteresting commands, he found out that loading any kind of program, indeed, sends the flash chip a command to perform a flash erase. From here, he could theoretically do a tweezer hack, write-protecting the flash by short-circuiting its data pins – yet, he decided to find a proper dumping method that would extend to the chips with built-in flash, should one of those appear on our desks.

Section of the datasheet, showing the flash command structure where it's possible to substitute your own flash chip commands, including the erase commandsHis key discovery came soon thereafter. Different SPI flash chip families have different commands for read/write/erase and other operations, and the bootloader exposes a structure you can modify to use different commands for the kind of flash chip you have connected. Simply substituting the flash erase command in that structure with something harmless resulted in the flash contents staying intact even after new code was loaded externally into RAM. As a result, [aleaksah] has discovered a method for dumping encrypted-at-rest firmware from any QN902X series MCU, using nothing but a USB-UART, the chip’s built-in bootloader and a small code dumping stub (GitHub).

Another day, another firmware readout protection mechanism circumvented! Finding such exploits is beneficial for a lot of fun journeys, like the recent hack that helps us tap into myriads of STM32-powered devices out there. You can even use the abundant ST-Link programmers as your training ground! If the SWD interface isn’t unlocked on your device, check out this educational journey about modding a third-party Xbox controller using SWD. Wonder how to modify the firmware you dumped? We’ve just covered a hacker modding their Kurzweil synthesizer’s firmware with Ghidra!