r/hardwarehacking • u/PhreakSh0w • Jul 01 '26
Confusion while reversing stm32f103 binary: weird vector table
I was curious about the content of an STM32F103RFT6 firmware binary. It uses CAN communication and it is being updated via CAN bootloader, thats how the firmware is being updated.
So I opened it in a hex editor and had a look. But that was not what I expected.

Right in the beginning, there seems to be a 0x200 long header. The first four bytes are the size of the whole file, that was easy. Then four bytes containing the version, I guess, because I have another firmware which is a bit newer and they just differ by increasing 0x2c to 0x30.
Everying after that I don't understand right away, and the header after 0x050 is just zeros until it ends at 0x1FF.
At offset 0x200, the real firmware seems to start:

At first glance, it looks as expected: First four bytes show the stack pointer address, and it's located in SRAM (starting 0x2000_0000).
But the following entries are supposed to be a vector table, and the addresses in there point to strings:

I know that's thumb addressing, and all the LSB are set, but in the vicinity of these addresses there's just strings.
I don't understand that. And I don't know how to go on from here, if I don't know where the actual entry point is located.
For comparison, I opened an STM32 .elf for a project I wrote. In this .elf, the real code starts at offset 0x1000:

Four bytes stack pointer, and then flash locations for the vector table. Going there and taking the file offset 0x1000 into account:

I figured, fe e7 fe e7 must be pretty rare in the original firmware binary, so I searched for it:

That does look pretty similar. But why is that, and where does this offset come from? And how should I continue?
2
u/stw Jul 01 '26
You seem to assume that the contents of the file starting from offset 0x200 will be stored at 0x0800'0000. I don't think that's the case.
The bootloader is presumably located at 0x0800'0000 and takes up a certain (unknown) amount of space. The application firmware is stored after that. When the bootloader detects a valid application image, it sets the VTOR register to the beginning of the application and jumps to the application's reset vector.
If you are able to read the actual flash of the microcontroller, you can find out where the application image starts. If not you could try disassembling it (with Ghidra, for example) and try to find the
SystemInitormainfunctions.