Full Report
The debug interface of the STM32F1 chip cannot have the debugger attachment disabled. Instead, there is a Flash Memory Read Out Protection (RDP) instead; this will block all data access via the debug interface. This article is about bypassing RDP. While playing around with a development board with RDP turned on, the authors ran the reset halt command. When doing this, they get the following output: xPSR: 0x01000000 pc: 0x08000268 msp: 0x20005000. Why is this interesting? Raw register values are sent back, which we shouldn't have access to. Why does this happen? A reset is a special kind of exception. When an exception is called, the processor loads the exception entry address from the vector table to know what to do - vector fetch. Since this is stored in flash memory, how can that vector be accessed? The reset vector is fetched via the ICode bus. So, the fetching of the reset information is done via the instruction fetch line instead of the standard data line. The bus being used in the reason why the read out protection doesn't work in this case! In ARMv7-M there is a Vector Table Offset Register (VTOR) that determines the location of the vector table in the address space. This is normally used to relocate the VTOR when going between applications but can be abused. By changing the VTOR, we can relocate the vector table within the flash memory region! Since the ICode bus passes back information via the PC and returns the address, with interrupts, we can abuse the trust mentioned above to slowly read out information we shouldn't have access to. Again, we can control everything besides flash via the debugging interface. Several items in the VTOR are inaccessible for functional reasons. However, we can wrap around the values (max is 32) to still access the vectors! For instance, the normally inaccessible 1 and be accessed by using the interrupt 33 but there are some limitations to it. Now, for the moment of truth - extracting the information. This is done by doing the following steps: Perform a device reset to put the microcontroller into a well-defined state. Configure the microcontroller to trigger an exception of our choosing. Only a handful can be truly triggered via this method though. Single step in order to make the exception active. At this point, we can extract the data we would like. Overall, this method, even with its shortcomings, was able to extract around 90% of the code in less than an hour on all of the chips. This is a pretty incredible feat by a small oversight on the part of the developers. Amazing blog post!
Analysis Summary
# Vulnerability: STM32F1 Flash Read-Out Protection (RDP) Bypass via Exception Handling
## CVE Details
- **CVE ID:** CVE-2020-8004
- **CVSS Score:** Not explicitly listed in the text (NVD currently rates this at 4.6 Medium; however, the impact on confidentiality is high).
- **CWE:** CWE-284: Improper Access Control / CWE-1256: Improper Restriction of Software Interfaces
## Affected Systems
- **Products:** STMicroelectronics STM32F1 Series Microcontrollers.
- **Versions:** All STM32F1 family chips (e.g., STM32F103) utilizing Read-Out Protection (RDP) Level 1.
- **Configurations:** Devices where the debug interface (SWD/JTAG) is physically accessible and RDP is enabled to prevent firmware extraction.
## Vulnerability Description
The vulnerability stems from an architectural oversight in how the ARMv7-M core handles exceptions versus how the STM32F1 implements memory protection. While the STM32F1's RDP blocks standard **data bus** (DCode) access to Flash memory via the debugger, it fails to block **instruction bus** (ICode) fetches triggered by the CPU's exception entry mechanism.
When an exception occurs, the processor fetches the entry address from the Vector Table located in Flash. By manipulating the **Vector Table Offset Register (VTOR)** via the debugger, an attacker can relocate the "vector table" to any address in Flash. When an exception is subsequently triggered and stepped through, the processor fetches "instructions" (which are actually the protected data) from the targeted Flash address and loads them into PC/registers. Because these fetches occur over the ICode bus, the RDP mechanism does not trigger a block.
## Exploitation
- **Status:** PoC available. A firmware extractor tool has been released by the researchers.
- **Complexity:** Low (Requires standard debugging tools like OpenOCD).
- **Attack Vector:** Physical (Requires access to the SWD/JTAG debug pins).
## Impact
- **Confidentiality:** High. Researchers demonstrated the ability to extract ~90% of the protected Flash memory in under one hour.
- **Integrity:** None directly from this flaw (RDP Level 1 allows some writes, but this flaw is a read-bypass).
- **Availability:** None.
## Remediation
### Patches
- **No hardware patch available:** This is a hardware-level design flaw in the STM32F1 series that cannot be fixed via firmware updates.
- **Recommendation:** Newer STM32 series (e.g., STM32F0, F4, L4) feature more robust protection mechanisms (like RDP Level 2) that can "hard-lock" the debug interface entirely.
### Workarounds
- **Physical Security:** The only definitive mitigation is to prevent physical access to the debug interface (e.g., potting the PCB, removing debug headers, or disabling pins via software/GPIO configuration if applicable).
- **Firmware Level:** Implement software-based protections to disable debug pins early in the boot process (though this is often circumvented by hardware reset-halt timing).
## Detection
- **Indicators of compromise:** Physical tampering with the device casing or evidence of soldering/clamping onto the SWD/JTAG pins.
- **Detection methods:** This is a non-invasive side-channel/architectural attack; it leaves no digital logs on the device itself.
## References
- **Vendor Advisory:** [STMicroelectronics ST - Product Security - hxxps://www.st.com/content/st_com/en/support/resources/product-security-advisories.html]
- **PoC Source Code:** hxxps://gitlab.zapb.de/zapb/stm32f1-firmware-extractor
- **Original Research:** hxxps://blog.zapb.de/stm32f1-exceptional-failure/