Having been trying to make sense of the broadcast packets from the heaters and controllers for a few days it became apparent that I wasn't making much progress. Some small pieces made sense and seemed to point to a structure, but there just wasn't enough to progress my understanding.

Firmware?

When I opened the controller to find the RF chip being used, I noticed a series of 6 through hole pads, marked as X1. Conventionally the X prefix suggests a socket.

Controller PCB with X1 socket highlighted.

There were 6 pins, the 3rd from the top appears to be GND if we assume a ground plane has been used. Given the STMicroelectronics SPIRIT1 being used, would they have also used an STM32? It would have obvious benefits from a development standpoint.

SWD?

The Nucleo development board that I have has an attached ST-LINK with a 6 pin header, labelled CN4.

CN4 SWD Header pin details

Pin #3 is GND so this looks like a possible match?

After downloading the ST-LINK software and fashioning a cable to connect the CN4 header to X1 on the PCB it was time to power up the PCB and see what I got.

Bytes

Sure enough, as soon as the controller was powered up and I clicked the connect button in the software, I had access. The flash contents appeared. What I don't know is which of the STM32 family of chips the controller uses as it's hidden beneath the soldered on LCD screen. I can't simply look at the chip for inspiration and the ST-LINK software didn't offer any suggestions.

Before copying the data I experimented with the length to read until I had all the available data included. With that settled I downloaded to a file.

$ hd dump.bin | more
00000000  00 40 00 20 5d f5 00 08  cd f5 00 08 cf f5 00 08  |.@. ]...........|
00000010  d5 f5 00 08 db f5 00 08  e1 f5 00 08 00 00 00 00  |................|
00000020  00 00 00 00 00 00 00 00  00 00 00 00 e7 f5 00 08  |................|
00000030  e9 f5 00 08 00 00 00 00  eb f5 00 08 ed f5 00 08  |................|
00000040  a5 f5 00 08 a5 f5 00 08  a5 f5 00 08 a5 f6 00 08  |................|
00000050  a5 f5 00 08 15 f6 00 08  a5 f5 00 08 29 f6 00 08  |............)...|
00000060  a5 f5 00 08 a5 f5 00 08  51 f6 00 08 a5 f5 00 08  |........Q.......|
00000070  a5 f5 00 08 a5 f5 00 08  a5 f5 00 08 a5 f5 00 08  |................|
00000080  a5 f5 00 08 a5 f5 00 08  19 f6 00 08 a5 f5 00 08  |................|
00000090  a5 f5 00 08 a5 f5 00 08  a5 f5 00 08 5f f6 00 08  |............_...|
000000a0  a5 f5 00 08 a5 f5 00 08  a5 f5 00 08 a5 f5 00 08  |................|
000000b0  a5 f5 00 08 b5 f6 00 08  c9 f6 00 08 a5 f5 00 08  |................|
000000c0  a5 f5 00 08 a5 f5 00 08  a5 f5 00 08 95 f6 00 08  |................|
000000d0  a5 f5 00 08 a5 f5 00 08  a5 f5 00 08 a5 f5 00 08  |................|
000000e0  83 f6 00 08 a5 f5 00 08  a5 f5 00 08 a5 f5 00 08  |................|
000000f0  a5 f5 00 08 00 00 00 00  00 00 00 00 a5 f5 00 08  |................|
00000100  00 00 00 00 00 00 00 00  a5 f5 00 08 a5 f5 00 08  |................|
Display of first bytes from dumped memory.
 % file ./dump.bin                                         
./dump.bin: data
File type from the file app.

Not much help. Maybe binwalk can help?

% binwalk ./dump.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
117308        0x1CA3C         PEM RSA private key
117372        0x1CA7C         PEM DSA private key
117552        0x1CB30         PEM EC private key
117616        0x1CB70         PEM certificate
119580        0x1D31C         AES S-Box
119836        0x1D41C         AES Inverse S-Box
122248        0x1DD88         SHA256 hash constants, little endian

This looks more promising. Maybe looking at the strings will reveal more?

-----BEGIN DH PARAMETERS-----MBYCEQC80RK35an+lEkPBY+TKIDzAgEC-----END DH PARAMETERS-----
DH parameters from the dumped data.

However they all appear to be empty except for the DH parameter value. They are possibly just standard additions from the STM framework? While looking at the strings output I did find this,

..\\src\\Hal\\src\\HAL_CubeMx.c

which appears to confirm that they used the STM framework to write the firmware.

Can it be disassembled?

% binwalk -Y ./dump.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
226           0xE2            ARM executable code, 16-bit (Thumb), little endian, at least 1587 valid instructions

Running the command again with verbose output gives a lot more detail.

% binwalk -Y -v ./dump.bin

Scan Time:     2023-02-17 12:34:23
Target File:   dump.bin
MD5 Checksum:  da346f005d15ba3cf4769877e8f2e92e

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
226           0xE2            ARM executable code, 16-bit (Thumb), little endian, at least 1587 valid instructions
226           0xE2            lsrs r0, r0, #0x20
228           0xE4            sub.w r8, r5, #0x800000
232           0xE8            sub.w r8, r5, #0x800000
236           0xEC            sub.w r8, r5, #0x800000
240           0xF0            sub.w r8, r5, #0x800000
244           0xF4            movs r0, r0
246           0xF6            movs r0, r0
248           0xF8            movs r0, r0
250           0xFA            movs r0, r0
252           0xFC            sub.w r8, r5, #0x800000

Now What?

Several articles I have read suggested using IDA to decompile the file contents, but as I'm not planning on using it for more than this project the price is far too high. I did find Binary Ninja which has proven useful and managed to extract the compiler code.

Binary Ninja decompilation as pseudo_c

I'm not convinced that the extractions are correct but have very little experience of such things. The controller has been available for a number of years, so it could be that the firmware is similarly older than the tools have been assuming?

Think I need to try and identify the chip I am working with and then track down the datasheet for it. This should help me dump the entrire flash contents and also find the SPI memory addresses that I imagine it uses for communicating with the SPIRIT1.

If anyone with more experince of doing this sort of reverse engineering has any thoughts, I'd be grateful to hear them!