How to bypass Debug Disabling on SM32F103
Notice - This was originally hosted on Medium, but their pricing decisions are really off putting. So, now I'm migrating content to here. Former location of this content is here.
Tl;Dr — How difficult is this? Well, it’s really quite easy. Providing CRP has not been activated, re-enabling debug on these ICs is just a matter of editing two bytes in a firmware.
Overview
There
is a good case to state that modern devices are moving towards a very
slightly more homogenised ecosystem. This is signalled by the number of
cheap, easily available ARM-based microcontrollers and microprocessors
available on the market.
ARM
offers many features ‘as standard’ across various applications, and
with low-price IC’s on the market, there is a good chance that the
uptake of ARM architecture will continue. The STM32 series of
microcontrollers are quite popular with developers owing to good
physical/performance properties, as well as a low price point.
We
will take a quick look at the STM32F103 (specifically the STM32F103C8T6
IC) — and how you can disable debug protections and CRP. These are
nifty little Cortex-M3 based chips with 64kb Flash, 20kb RAM, and
clocked at up to 72MHz. You can see why they might be popular.
The Problem
Implementations
of ARM can vary wildly. There are some standard features that are
either missed out or reconfigured completely — each IC manufacturer is
left to their own devices (←pun) for how they produce ARM chips.
There are two protection mechanisms that are usually recommended by hardware/embedded/IoT security people:
- Disable Debug ports — JTAG and SWD disable
- Enable firmware protections e.g. Code Readout Protection
We want to look to see if we can disable these protections on the target IC — the STM32F103.
Disabling Debug
The first is quite straightforward — for STM32F103 you simply set
__HAL_AFIO_REMAP_SWJ_DISABLE();
in the standard file stm32f1xx_hal_msp.c (if you are using STCubeMX
generated output — you can do something similar with libopencm3, too).
This
is the default configuration of STCubeMX-generated firmware source
projects. Meanwhile, the IC’s themselves ship with SWD Enabled but the
flash being locked — but this is trivial to unlock over SWD.
But once such a firmware with SWD/JTAG debugging disabled is applied, then this device can no longer be debugged. At least, that is the idea.
So, our initial scenario is an STM32F103 device with Debug Disabled.
Bypassing Disabled Debug
All
this said, there are two pins that should be brought to attention — the
BOOT0 and BOOT1 pins. These are designed to be used to trigger
fallback/default modes on the IC — and as usual, this can spell disaster
if you’re trying to hide some IP.
Specifically, we first want to use BOOT0, which is pin 44 on the LQFP48/UFQFP48 packages. Here is the attack for this:
Attack:
- We need to raise this BOOT0 pin to 3.3V and then power cycle the IC
- Acquire a copy of the firmware
- Patch the firmware to enable SWD debugging
- Re-flash the new firmware to have the device with debugging enabled
So,
first, we raise the voltage of pin 44 to 3.3V. If you’re playing along
at home with a Blue Pill development board, you’ll note that this is one
of the two jumper pin options on the top of the board.
Here is the board before and after we apply the change to BOOT0:
Detail showing the config of BOOT0/1 pins for this 'attack' |
We
will now see that we can debug the IC, and dump firmware using SWD.
That’s it. That’s the first part of the attack. Having issues? You can
just use
mbr
to cycle through all
the addresses on the flash using a script, or dump the image, both using
the openOCD client, an STLink-V2 USB-to-SWD interface, and a little bit
of time/SSD space.
Once you have acquired the firmware, how can we enable debugging on the code? Well, first, we reassemble the firmware into some
firmware.bin
file.
With
this done, we need to do some binary editing. Here is the diff between
two otherwise identical firmware files — the first has debug disabled,
and the second (lower) has SWD Enabled.
vbindiff — look at the bits in RED |
As
you can see, at 0x00000F18, the 2-byte word there is the only thing
that is different. So, search for 0x8062 at the same address in our
target firmware and patch it to be 0x0072, and then re-flash the
firmware onto the STM32F103 chip.
We
can then lower the BOOT0 pin voltage, power cycle the IC, and then we
should have (possibly with a little more hacking) SWD enabled on our
target firmware.
…and now for something CRP
Code
Readout Protection (CRP) is fairly standard on many ARM-based IC’s. On
STM32 IC’s it is referred to PCROP (Proprietary Code ReadOut Protection)
if we want to protect a block of flash ROM, or generically RDP (Read
Protection) if we want to prevent memory dumping on the devices.
(STM
have a habit of doing this slightly askew renaming… ARM tech specs call
the first UART port UART0, whereas STM call it USART1 because why the
hell not?…)
In theory, with CRP enabled, we cannot read out the firmware in order to carry out the above attack.
Can you bypass PRCOP on STM32F103?
Easily — mainly because it’s not implemented. Yeah, anticlimax, I know.
RDP
is on these F1 series IC’s, according to some documents like the line
above the red box in the screenshot, but in slide 7 of this (http://www.emcu.it/SILICA-STDay-2016/X/Presentazioni/2_STM32&SecureElements.pd) it is not shown as being present.
It
transpires that RDP is indeed enabled, and is active on the STM32F103,
however, a preliminary test shows that it should be vulnerable to this
attack: https://www.aisec.fraunhofer.de/content/dam/aisec/ResearchExcellence/woot17-paper-obermaier.pdf — will try this out and update this article accordingly.
PCROP
is only available on the STM32 lines F4, L0, L1, and L4, whilst RDP is
only available on IC’s from the F0, F2, F3, F4, F7, L0, L1, and L4
lines, but with the STM32F405 nor STM32F407 (see p.12 of this: http://www.st.com/content/ccc/resource/technical/document/application_note/89/12/c5/e2/0d/0e/45/7f/DM00186528.pdf/files/DM00186528.pdf/jcr:content/translations/en.DM00186528.pdf) series IC’s as exceptions without PCROP. As you can see, this is a bit of a mess… You can get some details from documents like this (http://www.emcu.it/SILICA-STDay-2016/X/Presentazioni/2_STM32&SecureElements.pdf), but by and large, specific details are quite hard to come by.
The differentiation between the two is rather strange, and is a current topic of interest for me. More news as it happens :)
Further Attacks
There
are other attacks possible — if you raise both BOOT0 and BOOT1 pins,
you can use the SRAM bootloader to upload/download firmware using USART
ports on the STM32F103, but this requires the second BOOT1 pin, and this
isn’t always available on all packages.
For details, see here: https://bin.jvnv.net/f/Qjbxx
Conclusion
Many hardware hackers have said, again and again, that Kerckhoff’s Principle should be assumed when building firmware for devices, explicitly;
The device should have a level of security across its ecosystem, even if the firmware, but not all of the individual device secrets, are known.
Disabling debug is a good idea, as is turning on CRP, but the key takeaway is do not rely on these things! Someone with enough time, determination, and Red Bull is all that will stand between a researcher and your device IP. You have to operate on the assumption that your firmware is going to be extracted, read, and mitigate issues accordingly.
Too often I find that when hacking a device, there are common secrets/encryption keys/passwords that are hardcoded, and thereby universal for a whole class of in production devices. Compromise of one firmware should not lead to compromise of other devices.
Too often I find that when hacking a device, there are common secrets/encryption keys/passwords that are hardcoded, and thereby universal for a whole class of in production devices. Compromise of one firmware should not lead to compromise of other devices.
Interested in more? See this talk from Cybergibbons at BSides Leeds in 2018: https://www.youtube.com/watch?v=DTuzuaiQL_Q
and see this work from the SeeMoo group at TU Darmstadt: https://nexmon.org
Watch this space for more on this kind of topic. The battle against debug disabling is on, and the game is afoot!!
Comments
Post a Comment