MCU(微控制器單元)的加密方法可以從硬件、軟件和通信協議三個層面來理解。以下是常見的MCU加密手段,按類型分類說明:
針對目前 STM32 系列微控制器在程序加密保護方面手段單一、保護效果有限的問題,本文介紹并分析了四種常用的程序保護方法:
-
閃存讀寫保護
-
芯片唯一 ID 驗證
-
外接加密芯片
-
引導程序加密(Bootloader 加密)
實際在 STM32 開發板上的測試表明,合理組合多種保護機制,能顯著增強芯片程序與數據的安全性,有效防止閃存程序被讀取、拷貝或篡改,為嵌入式系統提供更可靠的安全保障。?
1 閃存讀寫保護法
STM32 微控制器提供了閃存讀寫保護的功能,
用來防止對閃存的非法訪問。 閃存讀寫保護功能概述:
讀保護(RDP)
-
通過修改 Option Bytes 中的 RDP 位來啟用。
-
啟用后,Flash 只能被內部正常執行的程序讀取,無法通過 JTAG/SWD 調試接口或從 RAM 啟動的程序讀取。
-
解除讀保護會觸發整片 Flash 擦除,防止逆向工程與調試工具破解。
-
以 STM32L1 系列為例,RDP 分為 3 個等級,不同等級對應不同的安全強度。
等級 | 描述 |
---|---|
0 | 無保護(默認)。可以通過 JTAG/SWD 或從 RAM 啟動的程序任意讀取 Flash。 |
1 | Flash 受保護,防止由調試器(JTAG/SWD)直接讀取,也不能通過在 RAM 中加載執行程序來讀取。 解除 Level 1 保護將觸發全片擦除。 |
2 | 最嚴格保護——禁用所有調試功能。 一旦設為 Level 2,不可復原,需謹慎使用。 |
寫保護(WRP)
-
通過在 Option Bytes 中設置 WRP 位來啟用。
-
啟用后,對被保護頁的任何寫或擦除操作都會被硬件阻止,并在狀態寄存器中產生錯誤標志。
-
可以防止惡意修改中斷向量表或關鍵代碼區域。
優缺點對比:
優點:
由硬件層面直接提供,成本為零,易于配置。
能有效防止通過調試接口的非法讀寫。
缺點:
單一的讀/寫保護難以抵抗高級物理攻擊或側信道分析。
需要與軟件層面的校驗(如 CRC、HASH)或更高級的加密方法(如外部加密芯片、Bootloader 加密)組合,才能構建更完善的防護體系。
實施的方法如下,下面以 STM32G4 系列為例,分別介紹如何通過 ST-Link/CubeProgrammer 工具以及 運行時(HAL)編程 兩種方式來啟用 Flash 的讀寫保護(RDP 和 WRP)。
方法一:通過 STM32CubeProgrammer 界面設置
打開 CubeProgrammer
啟動 STM32CubeProgrammer,選擇 “ST-Link” 連接。
讀取當前 Option Bytes
在左側菜單選擇 “Option Bytes”。
點擊 “Read”,查看當前 RDP(Read Protection)和 WRP(Write Protection) 配置。
配置讀保護(RDP)
在 “Read protection” 下拉框中選擇:
Level 0:無保護
Level 1:Flash 只允許內部執行讀取
Level 2:全部調試接口禁用(不可逆)
推薦一般項目選 Level 1。
配置寫保護(WRP)
在 “Write protection” 區域,勾選你要保護的 Flash 扇區(Page)。
比如要保護第 0~3 扇區,就勾選對應頁號。
寫入并重啟
點擊 “Apply”,CubeProgrammer 會提示需要復位芯片以生效。
確認后,設備重啟,Option Bytes 即更新完畢。
方法二:在用戶代碼中動態配置(HAL 庫示例)
如果希望在程序首次運行時,或通過 Bootloader 進行保護設置,可以在固件內部調用 HAL API 來修改 Option Bytes。
/*** @brief 啟用 RDP Level1 并對指定扇區啟用寫保護* @note 必須在系統啟動早期執行,且芯片復位后才生效*/
void Protect_Flash(void)
{HAL_FLASH_Unlock();HAL_FLASH_OB_Unlock();/* 1) 讀保護 → Level1 */FLASH_OBProgramInitTypeDef OBInit = {0};OBInit.OptionType = OPTIONBYTE_RDP;OBInit.RDPLevel = OB_RDP_LEVEL_1;if (HAL_FLASHEx_OBProgram(&OBInit) != HAL_OK) {/* 錯誤處理 */}/* 2) 寫保護 → 保護第 0~15 KB(頁 0~15) */memset(&OBInit, 0, sizeof(OBInit));OBInit.OptionType = OPTIONBYTE_WRP;OBInit.WRPState = OB_WRPSTATE_ENABLE;OBInit.WRPPage = OB_WRP_PAGES0TO3 | OB_WRP_PAGES4TO7 | OB_WRP_PAGES8TO11 | OB_WRP_PAGES12TO15;if (HAL_FLASHEx_OBProgram(&OBInit) != HAL_OK) {/* 錯誤處理 */}HAL_FLASH_OB_Lock();HAL_FLASH_Lock();// /* 復位生效 */
// NVIC_SystemReset();
}
?其次你會發現程序也燒寫不進去。此時目標也達成。
我們說了加密,那如何解密呢?問題在于每次切換RDPLevel 1到0的過程中的時候,會將flash的內容全部擦除。因此這是解密的難點之一。
我們引入思考點一,針對閃存讀寫保護法這類內容也就是寄存器置位,如果你要切換RDP1到RDP0?的過程伴隨著一個問題,STM32 上的 Read-Out Protection(RDP)并不是真正的“加密”,而是一種硬件級的“只讀保護”機制——它保證 任何 試圖“解開”這層保護的操作(也就是把 RDP 從 Level 1 降回 Level 0),都會觸發一次整片 Flash 的 不可逆擦除,從而根本不可能在芯片上恢復出原來的固件!!!
一旦啟用 RDP Level 1,就不可能在器件內“解密”或“讀取” Flash 內容;任何試圖取消保護的行為都會把所有數據抹掉。
為什么不能“解密”現有固件???
STM32 的 RDP 設計上就是「不可逆保護」:降級就擦除。
Flash 中的代碼以明文形式存儲,Option Bytes 保護只是阻止「直接」訪問,但并不做真實的加密。
一旦需要「訪問明文」,只能通過內部執行(CPU 跳轉),而不是通過調試器或外部讀口。
因此問題點來了!!!我們要做的是,在啟用了 RDP Level 1 以后,所有基于 JTAG/SWD 或 外部調試器 的直接讀 Flash 操作都會被阻止——硬件層面上不可能再通過外部工具把 Flash 整片“拷”出來。不過,RDP Level 1 并不影響 MCU 自身程序對 Flash 的正常讀取;換句話說,你只要在芯片內跑一段用戶代碼,通過 UART/CAN/USB 等總線把 Flash 內容“轉發”出去,就能獲得完整的二進制鏡像。
首先我們要將程序運行在SRAM中,根據自己的芯片主控觀察大小,筆者這邊是20KB的如下所示:
因此我們的環境在keil,如何配置呢,跟著筆者一步一步來吧。
第一步就是新建立一個模板了 如上所示,我們進行切換。
其次就是宏定義了,加上下述內容!
這邊就是改配置內容了
接下來就是這個內容的更改了,配置文件具體如何寫如下所示:
LR_IROM1 0x20000000 0x00005000 { ; Total 20KB SRAM regionER_IROM1 0x20000000 0x00003000 { ; Code section: 12KB*.o (RESET, +First)*(InRoot$$Sections).ANY (+RO).ANY (+XO)}RW_IRAM1 0x20003000 0x00002000 { ; Data section: 8KB.ANY (+RW +ZI)}
}
其次就是這個仿真器命令文件了,如下所示:
具體內容如下所示:
/***********************************************************/
/* Debug_RAM.ini: Initialization File for Debugging from Internal RAM */
/******************************************************/
/* This file is part of the uVision/ARM development tools. */
/* Copyright (c) 2005-2014 Keil Software. All rights reserved. */
/* This software may only be used under the terms of a valid, current, */
/* end user licence from KEIL for a compatible version of KEIL software */
/*development tools. Nothing else gives you the right to use this software */
/***************************************************/FUNC void Setup (void) {
SP = _RDWORD(0x20000000); // 設置棧指針SP,把0x20000000地址中的內容賦值到SP。
PC = _RDWORD(0x20000004); // 設置程序指針PC,把0x20000004地址中的內容賦值到PC。
_WDWORD(0xE000ED08, 0x20000000); // Setup Vector Table Offset Register
}LOAD %L INCREMENTAL // 下載axf文件到RAM
Setup(); //調用上面定義的setup函數設置運行環境//g, main //跳轉到main函數,本示例調試時不需要從main函數執行,注釋掉了,程序從啟動代碼開始執行
最后就是debug處了。
之后進入調試你會發現程序在SRAM的運行處。觀察匯編代碼。
因此,程序成功在SRAM處運行。
都要重新點擊“Debug”按鈕下載SRAM程序,再全速運行才能正常查看輸出。
接著就是寫拷貝flash的內容到SRAM處通過UART轉發出來。
這是原本的程序地址所示如下了。
如下是通過SRAM來拷貝Flash轉發到uart的內容
void dump_flash_via_uart(void)
{char hex_str[8];for (uint32_t addr = FLASH_START_ADDR; addr < (FLASH_START_ADDR + FLASH_SIZE_BYTES); addr++) {uint8_t byte = *(volatile uint8_t*)addr;sprintf(hex_str, "%02X ", byte); // 格式化成十六進制字符串HAL_UART_Transmit(&huart1, (uint8_t*)hex_str, strlen(hex_str), HAL_MAX_DELAY);}const char* end_msg = "\r\n[FLASH DUMP DONE]\r\n";HAL_UART_Transmit(&huart1, (uint8_t*)end_msg, strlen(end_msg), HAL_MAX_DELAY);
}
含義 | 十六進制值 | 小端轉換(實際值) |
---|---|---|
初始棧地址 MSP | F8 04 00 20 | 0x200004F8 ? |
Reset_Handler | 05 01 00 08 | 0x08000105 ? |
NMI_Handler? | 5B 13 00 08 | 0x0800135B ? |
HardFault_Handler? | C9 11 00 08 | 0x080011C9 ? |
這些值完全一致!
但是在WDP與DRP設置了之后。。
📌 根本原因:
? 你能正常讀取 Flash,是因為:
-
STM32 默認 RDP 是 Level 0(無保護);
-
此時,即便運行在 SRAM,也能直接訪問
0x08000000
地址處的 Flash 內容;
? 設置 RDP Level 1 后:
-
Cortex-M3 核心(STM32F1)硬件禁止訪問 Flash 內容;
-
這是芯片的硬件安全特性,即使代碼跑在 SRAM,依然無法讀取 Flash 數據,目的就是為了防止“SRAM 下載程序+讀取 Flash 代碼”這種逆向手段;
因此上述破解方案無效,無法再從芯片內部獲取任何 Flash 數據了,數據已經從訪問層面徹底封鎖。如果想切回回0,flash內容也會全部擦除!
方法 | 原理 | 是否可行 | 備注 |
---|---|---|---|
芯片解封/酸蝕 + 顯微探測 | 打開芯片封裝,用電子顯微鏡直接讀 Flash 電荷狀態 | ??理論可行 | 需要實驗室級別設備、極高技術 |
功耗分析(側信道攻擊) | 用高精度設備分析芯片運行時功耗波動,推測程序數據 | 理論可行,但難度極高 | 適用于破解算法或加密密鑰,不適合整段程序恢復 |
激光/聚焦掃描干擾 | 用激光打干擾點,欺騙 Flash 控制器讀取受保護數據 | ??高端實驗室可能可行 | 用于芯片逆向取證等高價值目標 |
IC 解封 + Flash 直接讀出 | 拆解裸片,對 Flash 數字結構逐位掃描 | ??有可能,但需要芯片內部結構圖 | 這屬于“物理攻擊”范疇 |
?? 這些都需要 IC 物理逆向實驗室、百萬級設備成本,不具備民用可行性。
手段 | 原理 | 應用場景 |
---|---|---|
X-Ray(X 射線掃描) | 非破壞式探測芯片內部結構,識別 layout,理論可判斷 Flash 存儲 | 逆向分析芯片、找 ROM Mask |
開蓋 + 紫外線(UV)曝光 | 對芯片裸露的 silicon 層曝光,激發電荷或使 EEPROM 狀態改變 | 用于清除 EEPROM 或恢復舊鎖定狀態 |
補充:
STM32 跟一些 MCU(比如 AVR、ESP32)那種通過 熔絲(fuse)位 永久寫死不同。
STM32 的 Option Bytes 是可擦除/可重寫的 Flash 區域;
只不過 RDP Level 2 一旦寫入,就不可降級、無法還原;
RDP Level 1 還可以通過 全芯片擦除 恢復成 Level 0(但數據沒了)。