Since the bootloader discussed on the previous post is distributed as a binary blob I choose to begin the analysis with a static analysis tool instead of blindingly flashing the thing attaching a debugger and hopping for the best. For years I have been using IDA Pro but was curious about the “recent” public available Ghidra since it is free and works on Linux.
Ghidra and STM32 binaries
Ghidra requires no installation, just download, chmod, and you are done.
To start the analyzing go to File->Import File and import the binary. Then choose “cortex little endian” as language.
Press “Options” and choose 0x8000000 as the load address.
After that double click the binary to open and choose “Yes” when asked if you want Ghidra to analyse the binary now.
If you look at the assembly listing you will notice that Ghidra knows nothing about the reset vectors, peripherals, etc.
Even finding main is hard as it is. No worries we just have to use SVD Loader for Ghidra (read more about SVD files). Download it, place it on one of your Ghidra-Scripts search paths. Then you need to download the SVD file for the STM32F103. Now go to Ghidra script manager, run SVD Loader, and choose the SVD file you just downloaded.
If you define some structures the code gets cleaner. You can define it in Ghidra or import a file with the definition.
After some cleaning work I got:
The reset handler point to main, double clicking it will takes there..
QEmu and GDB
Some of the functions of the binary were hard for me to understand so some dynamic analysis was needed. Again I wasn’t willing to flash this unknown thing on real hardware so I looked into QEmu.
I had used QEmu in the past for some pi stuff but I had never used it to simulate bare metal. Unfortunately there are several forks of QEmu which with pros and cons but all lacking proper documentation. I ended up using Beckus fork because despite of being very old compared with mainstream it appears that it is the most complete regarding STM32F103 peripheral implementation. I did encounter several bugs which I had to patch but in the end it served the purpose.
Reverse Engineering begins
The above setup allowed me to reverse engineer the code and understand how the bootloader could modify the main firmware behavior. This will be described in the next post.