nRF51/52 ROM Protection : Prevent Someone Else From Dumping the Hex File

本文介绍了一种在nRF51822和nRF52832平台上通过利用UICR寄存器来阻止固件被非法读取的方法。通过修改特定地址的数据并启用读保护功能,可以有效避免固件被盗版。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


   To avoid piracy is very important for software and firmware development. Of course, you should protect your source code would not be spread out. But from firmware prospect, it is a way to piracy your intelligence: he might clone your WHOLE device, including the mechanism, circuit and firmware. It is not necessary to get your source code.
  In nRF51822 and 52832, There is a mechanism to prevent that happens. I will demonstrate that:
 My SDK versions are 10 for nRF51, and 11 for nRF52.

  To Simplify the demonstration. I copy the peripheral\uicr_config\uicr_config.h to my project folder, and the main.c include the file.
    Open the uicr_config.h, you could read that there is many address listed, you could modify the values on those addresses. The values I changing be :

// const uint32_t UICR_CLENR0    __attribute__((at(0x10001000))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_RBPCONF   __attribute__((at(0x10001004))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_XTALFREQ  __attribute__((at(0x10001008))) __attribute__((used)) = 0xFFFFFFFF;

const uint32_t UICR_ADDR_0x80 __attribute__((at(0x10001080))) __attribute__((used)) = 0x12345678;
// const uint32_t UICR_ADDR_0x84 __attribute__((at(0x10001084))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0x88 __attribute__((at(0x10001088))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0x8C __attribute__((at(0x1000108C))) __attribute__((used)) = 0xFFFFFFFF;
 const uint32_t UICR_ADDR_0x90 __attribute__((at(0x10001090))) __attribute__((used)) = 0x11223344;
 const uint32_t UICR_ADDR_0x94 __attribute__((at(0x10001094))) __attribute__((used)) = 0x55667788;
// const uint32_t UICR_ADDR_0x98 __attribute__((at(0x10001098))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0x9C __attribute__((at(0x1000109C))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xA0 __attribute__((at(0x100010A0))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xA4 __attribute__((at(0x100010A4))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xA8 __attribute__((at(0x100010A8))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xAC __attribute__((at(0x100010AC))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xB0 __attribute__((at(0x100010B0))) __attribute__((used)) = 0xFFFFFFFF;
 const uint32_t UICR_ADDR_0xB4 __attribute__((at(0x100010B4))) __attribute__((used)) = 0xAABBCCDD;
// const uint32_t UICR_ADDR_0xB8 __attribute__((at(0x100010B8))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xBC __attribute__((at(0x100010BC))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xC0 __attribute__((at(0x100010C0))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xC4 __attribute__((at(0x100010C4))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xC8 __attribute__((at(0x100010C8))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xCC __attribute__((at(0x100010CC))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xD0 __attribute__((at(0x100010D0))) __attribute__((used)) = 0xFFFFFFFF;
// const uint32_t UICR_ADDR_0xD4 __attribute__((at(0x100010D4))) __attribute__((used)) = 0xFFFFFFFF;

  By the way,  What is UICR ? UICR is the short for User Information Configuration Registers, where the values are non-alterable. The purpose for UICR is to make a space for manufacturer signing.


Build and download the hex to your device, and type the command line (I use nRF52832 as my target device):


> nrfjprog --family NRF52 --memrd 0x10001080 --n 128
0x10001080: 12345678 FFFFFFFF FFFFFFFF FFFFFFFF   |xV4.............|
0x10001090: 11223344 55667788 FFFFFFFF FFFFFFFF   |D3"..wfU........|
0x100010A0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF   |................|
0x100010B0: FFFFFFFF AABBCCDD FFFFFFFF FFFFFFFF   |................|
0x100010C0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF   |................|
0x100010D0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF   |................|
0x100010E0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF   |................|
0x100010F0: FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF   |................|

 The address values have been changed.

You could use the command the dump the whole hex :


> nrfjprog --family NRF52 --readcode output.hex

That is what I prevent from.


To avoid the dumping, Add below code in the beginning of main function :


#include "ble_flash.h"

/**@brief Function for application main entry.
 */
int main(void)
{
#if(1)
 if(UICR_RBPCONF_PALL_Enabled !=
  (uint32_t)((NRF_UICR->RBPCONF & UICR_RBPCONF_PALL_Msk) >> UICR_RBPCONF_PALL_Pos)) 
 {
  ble_flash_word_write((uint32_t *)&NRF_UICR->RBPCONF, 
   (NRF_UICR->RBPCONF & ~UICR_RBPCONF_PALL_Msk));
 }/*if */
#endif 
    uint32_t err_code;
    bool erase_bonds;

and you should include folder SDK_ROOT\components\drivers_nrf\ble_flash and the file SDK_ROOT\components\drivers_nrf\ble_flash\ble_flash.c in your working porject.

Take Keil C as the project modification example:




After download to the device, you could find the readback command would not work:


> nrfjprog --family NRF52 --memrd 0x10001080 --n 128
ERROR: The operation attempted is unavailable due to readback protection in
ERROR: your device. Please use --recover to unlock the device.

  That is, the SWD (Serial Wired Debug) function has been forbidden, the SWD could accept recover request from now.

NOTE :If you use Keil C, the IDE would not reset the device after the downloading. but you could press the download button twice to make sure the SWD has been disabled:

* JLink Info: Found SWD-DP with ID 0x2BA01477
* JLink Info: Found Cortex-M4 r0p1, Little endian.
* JLink Info: FPUnit: 6 code (BP) slots and 2 literal slots
* JLink Info: CoreSight components:
* JLink Info: ROMTbl 0 @ E00FF000
* JLink Info: ROMTbl 0 [0]: FFF0F000, CID: B105E00D, PID: 000BB00C SCS
* JLink Info: ROMTbl 0 [1]: FFF02000, CID: B105E00D, PID: 003BB002 DWT
* JLink Info: ROMTbl 0 [2]: FFF03000, CID: B105E00D, PID: 002BB003 FPB
* JLink Info: ROMTbl 0 [3]: FFF01000, CID: B105E00D, PID: 003BB001 ITM
* JLink Info: ROMTbl 0 [4]: FFF41000, CID: B105900D, PID: 000BB9A1 TPIU
* JLink Info: ROMTbl 0 [5]: FFF42000, CID: B105900D, PID: 000BB925 ETM
ROMTableAddr = 0xE00FF000
* JLink Info: SYSRESETREQ has confused core. Trying to reconnect and use VECTRESET.
* JLink Info: Found SWD-DP with ID 0x2BA01477
**JLink Warning: Failed to reset CPU. VECTRESET has confused core.
* JLink Info: Core is locked-up, trying to disable WDT.
**JLink Warning: Could not set S_RESET_ST
* JLink Info: Found SWD-DP with ID 0x2BA01477
* JLink Info: SYSRESETREQ has confused core. Trying to reconnect and use VECTRESET.
* JLink Info: Found SWD-DP with ID 0x2BA01477
**JLink Warning: Failed to reset CPU. VECTRESET has confused core.
* JLink Info: Core is locked-up, trying to disable WDT.
**JLink Warning: Could not set S_RESET_ST


Now you could see, the dumping has not been permitted, the only way to manipulate the storage (ROM) is to recover whole space: it is, erase all.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值