当前位置: 首页 > news >正文

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 云平台&#xff0c;并通过 MQTT 协议上传 DHT11 获取的温湿度值。 二、项目框图 三、DHT11工作原理 参考于良许嵌入式手把手教你玩转DHT11&#xff08;原理驱动&#xff09; | 良许嵌入式 3.1 正常工作验证 #​ 上电后&#xff…...

前端面试-JavaScript 数据类型详解

目录 一、数据类型分类 二、核心区别对比 1. 存储方式 2. 比较方式 3. 类型检测方法 三、特殊类型详解 1. Symbol 2. BigInt 3. null vs undefined 四、常见面试扩展问题 五、总结 一、数据类型分类 JavaScript 数据类型分为 基本数据类型&#xff08;原始类型&…...

【进程 】

【进程】 目录1. ELF格式程序与进程2. 进程的组织方式3. 进程的复刻&#xff08;fork&#xff09;4. 进程的状态 目录 1. ELF格式程序与进程 在Linux系统里&#xff0c;程序文件普遍采用ELF&#xff08;Executable and Linkable Format&#xff09;格式。这种格式的程序文件存…...

深入HBase——数据结构与算法

引入 通过前面的文章&#xff0c;我们对HBase已经有了基本认识&#xff0c;下面我们从HBase最核心的算法和数据结构进一步深入HBase。 HBase的一个列簇&#xff08;Column Family&#xff09;本质上就是一棵LSM树&#xff08;Log-Structured Merge-Tree&#xff09;​。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年…...

全链路优化:如何让单点登录认证接口并发性能翻倍?

背景 最近针对一个单点登录认证项目进行性能优化&#xff0c;在 8核 16G 环境下的认证并发能力从每秒800次提升至每秒1600次&#xff0c;性能提升一倍&#xff0c;整理此次优化过程中的相关性能优化操作总结和大家分享一下。 Nginx配置优化 在并发认证场景下&#xff0c;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证书密码&#xff0c;如果需要设置密码&#xff0c;需要再配置给elasticsearch 在之前的步骤中&#xff0c;如果我们对elastic-certificates.p12 文件配置了密码…...

个人简历html网页模板,科技感炫酷html简历模板

炫酷动效登录页 引言 在网页设计中,按钮是用户交互的重要元素之一。这样一款黑色个人简历html网页模板,科技感炫酷html简历模板,设计效果类似科技看板图,可帮您展示技能、任职经历、作品等,喜欢这种风格的小伙伴不要犹豫哦。该素材呈现了数据符号排版显示出人形的动画效…...

在LangFlow中集成OpenAI Compatible API类型的大语言模型

一、背景与核心价值 从Dify换到这个langflow真的时各种的不适应啊。 就比如这个OpenAI Compatible API,这不应该是基本操作嘛? 算了,服了,习惯了就好了。咱闲言少叙,正片开始: LangFlow作为LangChain的可视化开发工具,其最大优势在于无需编写代码即可构建复杂的大模型…...

Qt开发中有关内存管理方面常见的问题分析与解决方案

在Qt开发中&#xff0c;内存管理是一个既基础又关键的一部分知识。尽管Qt提供了自动化的父子对象管理机制&#xff0c;但在复杂的应用场景中&#xff08;如多线程、动态UI、异步操作等&#xff09;&#xff0c;我们在开发过程中&#xff0c;仍可能遇到内存泄漏、野指针、重复释…...

【outOfMemoryError】排查思路与解决方案

前言 不好啦❗ 天塌了❗ 系统崩了❗ 快看啊&#xff0c;程序outOfMemoryError了&#x1f648; 我的心里活动&#xff1a;“哈哈哈&#x1f600;哈哈哈&#x1f600;终于给我碰上了&#xff0c;这个问题可很少发生啊&#xff0c;又积累一个问题。虽然我昨天发了版本&#xff0…...

Python蓝桥杯刷题-小数第n位详解

题目描述 我们知道&#xff0c;整数做除法时&#xff0c;有时得到有限小数&#xff0c;有时得到无限循环小数。 如果我们把有限小数的末尾加上无限多个 0&#xff0c;它们就有了统一的形式。 本题的任务是&#xff1a;在上面的约定下&#xff0c;求整数除法小数点后的第 n 位开…...

Ubuntu服务器 /data 盘需要手动挂载的解决方案

服务器 /data 盘需要手动挂载的解决方案 如果重启服务器后&#xff0c;发现 /data 盘 没有自动挂载&#xff0c;通常是因为&#xff1a; /etc/fstab 配置文件 没有正确设置 自动挂载。该磁盘 没有被正确识别&#xff0c;需要手动挂载。文件系统错误 导致挂载失败。 下面是解…...

无法打开包括文件: “crtdbg.h”: No such file or directory

目录 无效解决措施(重装WindowsSDK) 有效解决措施 创建环境变量 添加环境变量INCLUDE 添加环境变量LIB RC无法运行 问题现象描述 复制以下文件至Error路径 无效解决措施(重装WindowsSDK) 参考文献&#xff1a;94176676/227706449-a5222d7d-d8d2-4a19-addb-8f546e69786f…...

番茄工作法html实现

对比了deepseek-r1-online和本地部署的14b的版本&#xff0c;输出的输出的html页面。 在线满血版的功能比较强大&#xff0c;可以一次完成所有要求。14b版本的功能有一些欠缺&#xff0c;但是基本功能也是写了出来了。 input write a html named Pomodoro-clock which “hel…...

多源 BFS 算法详解:从原理到实现,高效解决多源最短路问题

多源 BFS 是一种解决 边权为 1 的多源最短路问题 的高效算法。其核心思想是将所有源点视为一个“超级源点”&#xff0c;通过一次 BFS 遍历即可计算所有节点到最近源点的最短距离。以下从原理、实现和代码示例三个方面深入讲解&#xff1a; 目录 一、原理分析 1. 单源 BFS vs…...

使用IDEA提交SpringBoot项目到Gitee上

登录Gitee并新建仓库 创建本地仓库 提交本地代码到本地仓库 提交本地代码到远程仓库...

简单三步:Ollama选择phi3:mini模型,开启你的AI对话初体验

简单三步&#xff1a;Ollama选择phi3:mini模型&#xff0c;开启你的AI对话初体验 1. 引言&#xff1a;为什么选择Phi-3-mini开启AI之旅&#xff1f; 如果你对AI对话模型感兴趣&#xff0c;但又被复杂的部署、庞大的模型和昂贵的硬件要求吓退&#xff0c;那么今天这篇文章就是…...

深入浅出:从硬件原理图到DTS节点,图解RK3588外挂WiFi/蓝牙模块的驱动适配流程

从电路图到内核配置&#xff1a;RK3588外设驱动的硬件映射实战 当我们拿到一块RK3588开发板时&#xff0c;那些密密麻麻的电路图符号和内核中的设备树配置之间&#xff0c;到底存在着怎样的联系&#xff1f;这个问题困扰着许多从软件转向硬件开发的工程师。本文将以WiFi/蓝牙模…...

告别样式打架!用CSS Modules和:global()搞定React组件样式隔离(附实战代码)

告别样式打架&#xff01;用CSS Modules和:global()搞定React组件样式隔离&#xff08;附实战代码&#xff09; 在构建现代React应用时&#xff0c;样式管理往往成为开发者的"阿喀琉斯之踵"。想象这样一个场景&#xff1a;你正在开发一个企业级后台管理系统&#xff…...

不止于仿真:如何用Simulink ABS模型优化PID参数,让制动距离更短?

从曲线解读到参数优化&#xff1a;Simulink ABS模型PID调参实战指南 当ABS系统的仿真模型初步搭建完成后&#xff0c;真正的挑战才刚刚开始。面对屏幕上跳动的速度曲线和滑移率数据&#xff0c;许多工程师会陷入这样的困境&#xff1a;模型能跑通&#xff0c;但性能总差那么一点…...

如何实现Android音频无线转发:sndcpy完整指南与实战技巧

如何实现Android音频无线转发&#xff1a;sndcpy完整指南与实战技巧 【免费下载链接】sndcpy Android audio forwarding PoC (scrcpy, but for audio) 项目地址: https://gitcode.com/gh_mirrors/sn/sndcpy 你是否曾经想过将手机上的音频实时传输到电脑上播放&#xff1…...

MASA全家桶汉化包:7个核心模组的中文界面终极解决方案

MASA全家桶汉化包&#xff1a;7个核心模组的中文界面终极解决方案 【免费下载链接】masa-mods-chinese 一个masa mods的汉化资源包 项目地址: https://gitcode.com/gh_mirrors/ma/masa-mods-chinese 你是否在Minecraft中面对Masa Mods复杂的英文界面感到困惑&#xff1f…...

GitHub 6.6k 星!让 Claude 瞬间读懂整个代码库的神器

在 AI 辅助编程日益普及的今天&#xff0c;我们似乎正处于一个矛盾的时刻&#xff1a;大模型越来越聪明&#xff0c;能写出的代码越来越复杂&#xff0c;但作为开发者&#xff0c;我们却常常感到一种“无力感”。这种无力感&#xff0c;往往源于 AI 的“失忆”。 今天&#xff…...

基于深度学习yolo+关键点的仪器仪表识别 水表识别 电表自动读数 yolo pose指针仪表读数工业检测

指针仪表检测项目的深入研究与实现 最近&#xff0c;我接手了一个指针仪表检测项目&#xff0c;该项目对实时性和检测精度有极高的要求。为了满足这些需求&#xff0c;我投入了大量的时间研究指针仪表的检测和识别算法&#xff0c;并探索了不同的技术路径来优化检测效果。 初…...

RISC-V汇编避坑指南:新手常犯的5个错误及如何用QEMU调试

RISC-V汇编避坑指南&#xff1a;新手常犯的5个错误及如何用QEMU调试 刚接触RISC-V汇编时&#xff0c;很多开发者都会遇到程序运行结果不符合预期的情况。这些错误往往源于对指令细节的理解不足或调试方法不当。本文将剖析五个最常见的陷阱&#xff0c;并演示如何利用QEMU的调试…...

2025届学术党必备的降重复率神器推荐

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 知网AIGC检测服务会对学术文本里被人工智能生成的那部分内容展开识别&#xff0c;这个系统是…...