Reading and Writing Firmware on an STM32 using SWD

STMicroelectronics STM32 processors are some of the most common ARM microcontrollers we see in IoT devices. We often want to read the firmware from these so we can examine it and find any vulnerabilities or hidden functionality. We will use the simple software utility stlink to do this.

Target Device

We will be looking at the Nucleo-F030R8. This is a small development board that is available for under £10 from many sources. The manual is here and the schematic is here.

Why a development board, instead of a real target? They are cheap, consistent and documented. Whilst you are learning how things work

The main microcontroller on it is an STM32F030R8. The datasheet is here. This is an ARM Cortex-M0, the smallest of the ARM cores. There are 64Kbytes of Flash and 8 Kbytes of RAM, and it can run at 48Mhz. As this is a microcontroller, they are inside the same package as the processor itself.

The top part of the PCB has another microcontroller, which is acting as an STLink SWD programmer for the main microcontroller. SWD (Serial Wire Debug) is a debug interface that provides very similar functionality to JTAG. We can read and write memory and interact with the processor.

This STlink be separated from the lower board entirely by snapping cutting across where the break is. Strangely, the physically smaller programmer microcontroller is more capable than the lower one.

We will use this STLink hardware with the stlink software to interact with the device and read and write the flash.

Interacting with STLink

As with the tutorial on using USB Ethernet, we want to pass the STMicroelectronics STM32 STLink through to our Ubuntu VM. VM->Removable Devices->STMicroelectronics STM32 STLink->Connect (Disconnect from Host).

You can then type:

dmesg

And you should see multiple USB devices being enumerated – this is not just an STLink!

Let’s examine what we have by running:

lsusb

You can see the STMicroelectronics device here. It’s on USB bus 003, and is device 003.

Running:

lsusb -t

Will show us a break down of the device. We can see it’s made up of 4 different interfaces:

  • Vendor Specific  – the STLink part
  • Mass Storage – this is for the built-in Mbed functionality
  • Two cdc_acm – this is a USB serial port

We will just be working with the STLink today.

In an earlier post, we built and installed a tool called st-link. These are the Linux tools for interacting with the STLink programmer.

Run:

st-info --probe

And you should receive back information about the development board, including the size of flash and SRAM. Communications are working.

Reading the flash using stlink software

Now we want to read back the flash – this is the non-volatile storage where the firmware is stored. The flash this device is directly memory-mapped – we don’t need to initialise a flash controller before reading it.

The first thing we need to do is work out what address to read and how many bytes. For this, the memory map from the datasheet is of use.

The specific part of that diagram is in the middle. Flash memory is at 0x08000000.

We know this chip has 64KByte of flash – 0x10000. The command we want to write is:

st-flash read firmware.bin 0x08000000 0x10000

You can be lazy and input a large length – st-flash queries the chip and only reads back what is expected.

We now have firmware.bin, the contents of which can he checked with hexdump:

hexdump -C firmware.bin | less

If the data here is all 0xFF or 0x00, then something has likely gone wrong! The default state of erased flash is 0xFF.

Writing the flash using stlink software

There are times when we want to write to the flash memory in a device, say if we have patched the firmware.

The command here takes the flash address and infers the length from the file.

st-flash write firmware.bin 0x080000000

You will notice how much longer this takes than reading. Writing to flash is not trivial – it needs to be erased in blocks first, then specific commands issued to write it. To do this, a “flash loader” is injected by st-flash into the SRAM of the device. This then carries out the programming.

You can see the assembly for the STM32F0 flash loader here. If the flash is more complex – say external SPI flash that is not memory mapped – sometimes you need to do the same simply to read the flash.

Alternatives

OpenOCD can also be used to read and write flash in devices. It’s not a one-liner however, so for now we’ll use stlink.

There is also a utility provided by STMicroelectronics. Unfortunately it is Windows only and requires registration to download.

 

 

 

 

 

 

 

 

 

 

Reading and Writing Firmware on an STM32 using SWD