STM32的“Unique device ID“能否修改?
STM32F1系列的"Unique device ID"寄存器的地址为0x1FFFF7E8。

这个寄存器是只读的。
"Unique device ID"寄存器位于“System memory”中。“System memory”地址范围为“0x1FFF F000- 0x1FFF F7FF”。

所有STM32 MCU上都存在系统引导加载程序。顾名思义,它位于MCU的系统内存(ROM)区域。系统 bootloader 位于存储器的只读部分,并在制造阶段进行编程。在流行文献中,系统 bootloader 可能被称为 ROM bootloader。
“引导加载程序”存储在STM32设备的内部引导ROM(系统内存)中,并在生产过程中由ST编程。其主要任务是通过一种可用的串行外设(如USART、CAN、USB、I2C、SPI)将应用程序下载到内部闪存中。为每个串行接口定义了一个通信协议,具有兼容的命令集和序列。
结论:
通过查看各种资料,发现STM32的"Unique device ID"只读,不能修改,它只能由ST在生产时进行编程 。
CPU内部的"Unique device ID"是唯一的,且不可修改,因此,我们可对这ID进行加密,然后将加密结果保存到FLASH中。这样每次启动都会去比较加密数据是否匹配。正确,则运行;不正确则进入死循环。
STM32不同系列的ID起始地址不同,如下所示:
1. 0x1FFFF7AC, 是STM32F0系列"Unique device ID"的起始地址
2. 0x1FFFF7E8, 是STM32F1系列"Unique device ID"的起始地址
3. 0x1FFF7A10, 是STM32F2系列"Unique device ID"的起始地址
4. 0x1FFFF7AC, 是STM32F3系列"Unique device ID"的起始地址
5. 0x1FFF7A10, 是STM32F4系列"Unique device ID"的起始地址
6. 0x1FF0F420, 是STM32F7系列"Unique device ID"的起始地址
7. 0x1FF80050, 是STM32L0系列"Unique device ID"的起始地址
8. 0x1FF80050, 是STM32L1系列"Unique device ID"的起始地址
9. 0x1FFF7590, 是STM32L4系列"Unique device ID"的起始地址
10. 0x1FF0F420, 是STM32H7系列"Unique device ID"的起始地址
编程时,注意不要在程序中出现上述的"Unique device ID"寄存器的地址,否则,很容易被盗版。

例如下面这个加密就会被破解:
#include "stm32f10x.h" //使能uint8_t,uint16_t,uint32_t,uint64_t,int8_t,int16_t,int32_t,int64_t
#include "stdio.h" //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "USART1.h"
//注意:"USART1.h"要放在 "stdio.h" 包含文件之后,如果这个位置颠倒了,业不能打印浮点数。/*
CPU内部的“unique ID”是唯一的,且不可修改,因此,我们可对这ID进行加密,
然后将加密结果保存到FLASH中。这样每次启动都会去比较加密数据是否匹配。正
确,则运行;不正确则进入死循环。
STM32不同系列的ID起始地址不同,如下所示:
1. 0x1FFFF7AC, /STM32F0唯一ID起始地址
2. 0x1FFFF7E8, /STM32F1唯一ID起始地址
3. 0x1FFF7A10, /STM32F2唯一ID起始地址
4. 0x1FFFF7AC, /STM32F3唯一ID起始地址
5. 0x1FFF7A10, /STM32F4唯一ID起始地址
6. 0x1FF0F420, /STM32F7唯一ID起始地址
7. 0x1FF80050, /STM32L0唯一ID起始地址
8. 0x1FF80050, /STM32L1唯一ID起始地址
9. 0x1FFF7590, /STM32L4唯一ID起始地址
10. 0x1FF0F420; /STM32H7唯一ID起始地址
*/
#define SYSID 0X1FFFF7E8 //stm32f1系列单片机id起始地址
//直接使用0X1FFFF7E8地址,它会出现在FLASH中,还是可以改到的;
//使用RAM中的数据通过加减来得到ID起始地址,比较安全;#define SYSID1 0X1FFFF7E8
#define SYSID2 0X1FFFF7E9
#define SYSID3 0X1FFFF7EA
#define SYSID4 0X1FFFF7EB
#define SYSID5 0X1FFFF7EC
#define SYSID6 0X1FFFF7ED
#define SYSID7 0X1FFFF7EF
#define SYSID8 0X1FFFF7F0
#define SYSID9 0X1FFFF7F1
#define SYSID10 0X1FFFF7F2
#define SYSID11 0X1FFFF7F3
#define SYSID12 0X1FFFF7F4u8 FLASHIDbuf[12];//保存加密数据
void Save_SystemID(void)
{uint8_t i;u8 id[12]; //12*8 = 96u8 *dfu;//读ID数据并保存加密数据///printf("\r\n\r\nEncryptionID: ");id[0] = *(u8*)(SYSID1);id[1] = *(u8*)(SYSID2);id[2] = *(u8*)(SYSID3);id[3] = *(u8*)(SYSID4);id[4] = *(u8*)(SYSID5);id[5] = *(u8*)(SYSID6);id[6] = *(u8*)(SYSID7);id[7] = *(u8*)(SYSID8);id[8] = *(u8*)(SYSID9);id[9] = *(u8*)(SYSID10);id[10] = *(u8*)(SYSID11);id[11] = *(u8*)(SYSID12);for(i =0;i < 12;i++) //读取ID{printf("%#X,",id[i]);}dfu=FLASHIDbuf;for(i=0;i<12;i++){*dfu=id[i];dfu++;}
}//解密
void CheckSystemID(void)
{uint8_t i;u8 id[12]; //12*8 = 96u8 *dfu;u8 d;printf("\r\n\r\nCheckSystemID");
//读ID数据并比较加密数据///id[0] = *(u8*)(SYSID1);id[1] = *(u8*)(SYSID2);id[2] = *(u8*)(SYSID3);id[3] = *(u8*)(SYSID4);id[4] = *(u8*)(SYSID5);id[5] = *(u8*)(SYSID6);id[6] = *(u8*)(SYSID7);id[7] = *(u8*)(SYSID8);id[8] = *(u8*)(SYSID9);id[9] = *(u8*)(SYSID10);id[10] = *(u8*)(SYSID11);id[11] = *(u8*)(SYSID12);dfu=FLASHIDbuf;for(i=0;i<12;i++){d=*dfu;if(d==id[i])printf("\r\nOK%u",i);//比对正确,则打印else //ID校验失败{printf("\r\n\r\nError");while(1)//死循环{;}}dfu++;}
}int main(void)
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4USART1_Serial_Interface_Enable(115200);printf("\r\nCPU reset\r\n");while(1){Save_SystemID();//保存加密数据CheckSystemID();//检查加密数据}
}
要想解决不容易被破解,就将"Unique device ID"寄存器的地址为0x1FFFF7E8放到RAM中,通过计算得到。
#include "stm32f10x.h" //使能uint8_t,uint16_t,uint32_t,uint64_t,int8_t,int16_t,int32_t,int64_t
#include "stdio.h" //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
#include "USART1.h"
//注意:"USART1.h"要放在 "stdio.h" 包含文件之后,如果这个位置颠倒了,业不能打印浮点数。/*
CPU内部的“unique ID”是唯一的,且不可修改,因此,我们可对这ID进行加密,
然后将加密结果保存到FLASH中。这样每次启动都会去比较加密数据是否匹配。正
确,则运行;不正确则进入死循环。
STM32不同系列的ID起始地址不同,如下所示:
1. 0x1FFFF7AC, /STM32F0唯一ID起始地址
2. 0x1FFFF7E8, /STM32F1唯一ID起始地址
3. 0x1FFF7A10, /STM32F2唯一ID起始地址
4. 0x1FFFF7AC, /STM32F3唯一ID起始地址
5. 0x1FFF7A10, /STM32F4唯一ID起始地址
6. 0x1FF0F420, /STM32F7唯一ID起始地址
7. 0x1FF80050, /STM32L0唯一ID起始地址
8. 0x1FF80050, /STM32L1唯一ID起始地址
9. 0x1FFF7590, /STM32L4唯一ID起始地址
10. 0x1FF0F420; /STM32H7唯一ID起始地址
*/
#define SYSID 0X1FFFF7E8 //stm32f1系列单片机id起始地址
//直接使用0X1FFFF7E8地址,它会出现在FLASH中,还是可以改到的;
//使用RAM中的数据通过加减来得到ID起始地址,比较安全;u8 FLASHIDbuf[12];//保存加密数据
void Save_SystemID(void)
{uint8_t i;u8 id[12]; //12*8 = 96volatile u32 UID_BASE;UID_BASE = 0x20000007; //让逆向的人误以为是ram变量UID_BASE -= 0x800; UID_BASE -= 0x1F; //等于id的基地址0x1FFFF7E8//读ID数据并保存加密数据///printf("\r\n\r\nEncryptionID: ");for(i =0;i < 12;i++) //读取ID{id[i] = *(u8*)(UID_BASE+i);FLASHIDbuf[i]=id[i];printf("%#X,",id[i]);}
}//解密
void CheckSystemID(void)
{uint8_t i;u8 id[12]; //12*8 = 96u8 *dfu;u8 d;volatile u32 UID_BASE;UID_BASE = 0x20000007; //让逆向的人误以为是ram变量UID_BASE -= 0x800; UID_BASE -= 0x1F; //等于id的基地址0x1FFFF7E8printf("\r\n\r\nCheckSystemID");
//读ID数据并比较加密数据///dfu=FLASHIDbuf;for(i=0;i<12;i++){id[i] = *(u8*)(UID_BASE+i);d=*dfu;if(d==id[i])printf("\r\nOK%u",i);//比对正确,则打印else //ID校验失败{printf("\r\n\r\nError");while(1)//死循环{;}}dfu++;}
}int main(void)
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4USART1_Serial_Interface_Enable(115200);printf("\r\nCPU reset\r\n");while(1){Save_SystemID();//保存加密数据CheckSystemID();//检查加密数据}
}
这样,在FLASH中找不到"Unique device ID"寄存器的地址,如:0x1FFFF7E8。
为了保险起见,我们可以将ID读出后按照某个算法得到另外一个数值保存到FLASH中,就会更加安全。
只要盗版者无法修改的"Unique device ID"寄存器的内容,程序就不会被盗版。
如果你有好的破解方法或者是工具,请留言。
相关文章:
STM32的“Unique device ID“能否修改?
STM32F1系列的"Unique device ID"寄存器的地址为0x1FFFF7E8。 这个寄存器是只读的。 "Unique device ID"寄存器位于“System memory”中。“System memory”地址范围为“0x1FFF F000- 0x1FFF F7FF”。 所有STM32 MCU上都存在系统引导加载程序。顾名思义&a…...
STM32-温湿度上传OneNET项目
一、项目需求 使用 ESP8266 连接 OneNET 云平台,并通过 MQTT 协议上传 DHT11 获取的温湿度值。 二、项目框图 三、DHT11工作原理 参考于良许嵌入式手把手教你玩转DHT11(原理驱动) | 良许嵌入式 3.1 正常工作验证 # 上电后ÿ…...
前端面试-JavaScript 数据类型详解
目录 一、数据类型分类 二、核心区别对比 1. 存储方式 2. 比较方式 3. 类型检测方法 三、特殊类型详解 1. Symbol 2. BigInt 3. null vs undefined 四、常见面试扩展问题 五、总结 一、数据类型分类 JavaScript 数据类型分为 基本数据类型(原始类型&…...
【进程 】
【进程】 目录1. ELF格式程序与进程2. 进程的组织方式3. 进程的复刻(fork)4. 进程的状态 目录 1. ELF格式程序与进程 在Linux系统里,程序文件普遍采用ELF(Executable and Linkable Format)格式。这种格式的程序文件存…...
深入HBase——数据结构与算法
引入 通过前面的文章,我们对HBase已经有了基本认识,下面我们从HBase最核心的算法和数据结构进一步深入HBase。 HBase的一个列簇(Column Family)本质上就是一棵LSM树(Log-Structured Merge-Tree)。LSM树…...
Python爬虫实战:获取六图网漫画图
注意:以下内容仅供技术研究,请遵守目标网站的robots.txt规定,控制请求频率避免对目标服务器造成过大压力! 一、引言 Python 作为一种广泛应用于数据处理和网络爬虫领域的编程语言,拥有丰富的库和框架。其中,Scrapy 框架以其高效、灵活、可扩展等特点,成为构建爬虫程序的…...
HAProxy介绍与编译安装
目录 1、HAProxy介绍 2、HAProxy编译安装 Centos 基础环境 Ubuntu 基础环境 编译安装HAProxy 验证HAProxy版本 HAProxy启动脚本 配置文件 启动haproxy 验证haproxy状态 查看haproxy的状态页面 1、HAProxy介绍 HAProxy是法国开发者 威利塔罗(Willy Tarreau) 在2000年…...
全链路优化:如何让单点登录认证接口并发性能翻倍?
背景 最近针对一个单点登录认证项目进行性能优化,在 8核 16G 环境下的认证并发能力从每秒800次提升至每秒1600次,性能提升一倍,整理此次优化过程中的相关性能优化操作总结和大家分享一下。 Nginx配置优化 在并发认证场景下,Ngi…...
在Spring Boot中如何使用Freemaker模板引擎
在 Spring Boot 中使用 FreeMarker 模板引擎可以帮助你创建动态的 Web 页面。以下是详细的步骤和示例代码,介绍如何在 Spring Boot 项目里集成和使用 FreeMarker。 1. 添加依赖 如果你使用的是 Maven 项目,需要在 pom.xml 文件中添加 FreeMarker 相关依赖。Spring Boot 提供…...
Elasticsearch7.1.1 配置密码和SSL证书
生成SSL证书 ./elasticsearch-certutil ca -out config/certs/elastic-certificates.p12 -pass 我这里没有设置ssl证书密码,如果需要设置密码,需要再配置给elasticsearch 在之前的步骤中,如果我们对elastic-certificates.p12 文件配置了密码…...
个人简历html网页模板,科技感炫酷html简历模板
炫酷动效登录页 引言 在网页设计中,按钮是用户交互的重要元素之一。这样一款黑色个人简历html网页模板,科技感炫酷html简历模板,设计效果类似科技看板图,可帮您展示技能、任职经历、作品等,喜欢这种风格的小伙伴不要犹豫哦。该素材呈现了数据符号排版显示出人形的动画效…...
在LangFlow中集成OpenAI Compatible API类型的大语言模型
一、背景与核心价值 从Dify换到这个langflow真的时各种的不适应啊。 就比如这个OpenAI Compatible API,这不应该是基本操作嘛? 算了,服了,习惯了就好了。咱闲言少叙,正片开始: LangFlow作为LangChain的可视化开发工具,其最大优势在于无需编写代码即可构建复杂的大模型…...
Qt开发中有关内存管理方面常见的问题分析与解决方案
在Qt开发中,内存管理是一个既基础又关键的一部分知识。尽管Qt提供了自动化的父子对象管理机制,但在复杂的应用场景中(如多线程、动态UI、异步操作等),我们在开发过程中,仍可能遇到内存泄漏、野指针、重复释…...
【outOfMemoryError】排查思路与解决方案
前言 不好啦❗ 天塌了❗ 系统崩了❗ 快看啊,程序outOfMemoryError了🙈 我的心里活动:“哈哈哈😀哈哈哈😀终于给我碰上了,这个问题可很少发生啊,又积累一个问题。虽然我昨天发了版本࿰…...
Python蓝桥杯刷题-小数第n位详解
题目描述 我们知道,整数做除法时,有时得到有限小数,有时得到无限循环小数。 如果我们把有限小数的末尾加上无限多个 0,它们就有了统一的形式。 本题的任务是:在上面的约定下,求整数除法小数点后的第 n 位开…...
Ubuntu服务器 /data 盘需要手动挂载的解决方案
服务器 /data 盘需要手动挂载的解决方案 如果重启服务器后,发现 /data 盘 没有自动挂载,通常是因为: /etc/fstab 配置文件 没有正确设置 自动挂载。该磁盘 没有被正确识别,需要手动挂载。文件系统错误 导致挂载失败。 下面是解…...
无法打开包括文件: “crtdbg.h”: No such file or directory
目录 无效解决措施(重装WindowsSDK) 有效解决措施 创建环境变量 添加环境变量INCLUDE 添加环境变量LIB RC无法运行 问题现象描述 复制以下文件至Error路径 无效解决措施(重装WindowsSDK) 参考文献:94176676/227706449-a5222d7d-d8d2-4a19-addb-8f546e69786f…...
番茄工作法html实现
对比了deepseek-r1-online和本地部署的14b的版本,输出的输出的html页面。 在线满血版的功能比较强大,可以一次完成所有要求。14b版本的功能有一些欠缺,但是基本功能也是写了出来了。 input write a html named Pomodoro-clock which “hel…...
多源 BFS 算法详解:从原理到实现,高效解决多源最短路问题
多源 BFS 是一种解决 边权为 1 的多源最短路问题 的高效算法。其核心思想是将所有源点视为一个“超级源点”,通过一次 BFS 遍历即可计算所有节点到最近源点的最短距离。以下从原理、实现和代码示例三个方面深入讲解: 目录 一、原理分析 1. 单源 BFS vs…...
使用IDEA提交SpringBoot项目到Gitee上
登录Gitee并新建仓库 创建本地仓库 提交本地代码到本地仓库 提交本地代码到远程仓库...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...
dedecms 织梦自定义表单留言增加ajax验证码功能
增加ajax功能模块,用户不点击提交按钮,只要输入框失去焦点,就会提前提示验证码是否正确。 一,模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...
NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
算法—栈系列
一:删除字符串中的所有相邻重复项 class Solution { public:string removeDuplicates(string s) {stack<char> st;for(int i 0; i < s.size(); i){char target s[i];if(!st.empty() && target st.top())st.pop();elsest.push(s[i]);}string ret…...
