这里讨论一种软件加密方式,无需修改Option Byte,无需二次烧写序列号,只要按照普通流程一样,烧写HEX文件进去,整个加密就起效了.别人读出你的HEX文件,重新烧写到他的片子上,也无法使用.当然修改Option Byte会更好啦.组合一起就最好啦,比如读保护,开机就执行禁止Flash写,哪怕别人读出了你的Flash,也会因为写不了而...
首先要对96位UID动手,因为有了唯一UID,才能满足以下的情况.比如把UID通过一种运算组合,变成一个新的序列,或者低级一些,直接用UID加密,比如我这里用的就比较低级,如果上电发现UID和我指定位置的数据比对,如果不对,程序就不执行.比对如图两个红箭头处信息是否是对的.
其中0x1FFFF7AC位置有UID,ST出厂烧写了,0x0801F800下有我们的UID加密序列,正常来说,我们应该自己烧写,然后比对这两个地方对不对.UID的存放示意图.
好了,我们假设我们加密UID(其实就是UID拷贝)放到了0x0801F800,那么我们如此比对.
if( *(__IO uint32_t *)(0x0801F800) == *(__IO uint32_t *)(0x1FFFF7AC)) { if( *(__IO uint32_t *)(0x0801F804) == *(__IO uint32_t *)(0x1FFFF7B0)) { if( *(__IO uint32_t *)(0x0801F808) == *(__IO uint32_t *)(0x1FFFF7B4)) { while (1) { LL_GPIO_TogglePin(GPIOC, LL_GPIO_PIN_6); LL_mDelay(25); } } } }
如果比对完全一样,LED就狂闪,25ms间隔啊.问题来了,谁给0x0801F800编程啊.是二次烧写,还是程序内嵌,肯定是前者靠谱啊.烧写方法特别简单,如此一气呵成.
HAL_FLASH_Unlock(); { if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x0801F800, *(__IO uint32_t *)(0x1FFFF7AC)) == HAL_OK) { if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x0801F804, *(__IO uint32_t *)(0x1FFFF7B0)) == HAL_OK) { if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x0801F808, *(__IO uint32_t *)(0x1FFFF7B4)) == HAL_OK) { } } } } HAL_FLASH_Lock();
等等,为什么Flash可以不擦就写么,肯定不行啊,但是烧写时候,我们可以全片擦除嘛.但是还有一个新的BUG,如果是全片擦除,那么,如果是别人拷贝我们的Flash内容会怎样,明显就是一开机,0x0801F800位置就不可能是0xFFFFFFFF,因为我们的Flash内容上这部分肯定有内容的,我们一开机就编程了.所以整个逻辑变成了这样.
if( *(__IO uint32_t *)(0x0801F800) == 0xFFFFFFFF) { HAL_FLASH_Unlock(); { if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x0801F800, *(__IO uint32_t *)(0x1FFFF7AC)) == HAL_OK) { if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x0801F804, *(__IO uint32_t *)(0x1FFFF7B0)) == HAL_OK) { if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x0801F808, *(__IO uint32_t *)(0x1FFFF7B4)) == HAL_OK) { } } } } HAL_FLASH_Lock(); } if( *(__IO uint32_t *)(0x0801F800) == *(__IO uint32_t *)(0x1FFFF7AC)) { if( *(__IO uint32_t *)(0x0801F804) == *(__IO uint32_t *)(0x1FFFF7B0)) { if( *(__IO uint32_t *)(0x0801F808) == *(__IO uint32_t *)(0x1FFFF7B4)) { while (1) { LL_GPIO_TogglePin(GPIOC, LL_GPIO_PIN_6); LL_mDelay(25); } } } }
也有人疑问,不是直接执行HAL_FLASH_Program,然后返回FAIL不就知道了吗,确实没错,但是这样会浪费更多的时间,因为Flash编程失败是基于Flash的总线超时来做的.一点都不划算.我们把编程的程序烧写进去,发现狂闪,确实没错了.
打开ST-Link工具,查看对应位置,果然有内容了.
比对一下,发现跟序列号真的一样哦.
模拟一下情况,把Flash存的序列号写错.
断开仿真器,然后重新上电,发现执行不到快闪了.那批量时候怎么办呢,这好解决了.先把0x0801F800填FF.
然后看看程序实际大小.
提取到0x538那么长的程序就满足了.
然后来个全片擦.
然后再写刚才保存的.
LED就可以正常快闪了.当然,STLink的擦除是部分擦除,如果Flash本身不是空的,他也只擦掉需要编程的位置的数据.比如下面说一个极端情况.UID位置被写了其他内容.这时候烧写精简就没用了.
这时候需要烧写全片,或者执行一次全片擦除.问题解决.备份全片就是把SIZE调大一点,其实后面也是全0,但是告诉烧写工具,我要全片擦掉.
另一个方法就是调整设置.比如STLink的自动模式,就可以这么干.要来全片擦.
好好利用这个自动模式,还是非常好用的.加密程序主要参考代码,下面还有OB的代码,记住哦,保护2的意思是ST都没办法解除哦.
int main(void) { SystemClock_Config(); if( *(__IO uint32_t *)(0x0801F800) == 0xFFFFFFFF) { static FLASH_OBProgramInitTypeDef FLASH_OBProgramInitStruct; HAL_FLASH_Unlock(); { if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x0801F800, *(__IO uint32_t *)(0x1FFFF7AC)) == HAL_OK) { if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x0801F804, *(__IO uint32_t *)(0x1FFFF7B0)) == HAL_OK) { if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, 0x0801F808, *(__IO uint32_t *)(0x1FFFF7B4)) == HAL_OK) { } } } } HAL_FLASH_OB_Unlock(); HAL_FLASHEx_OBErase(); FLASH_OBProgramInitStruct.WRPPage = OB_WRP_ALLPAGES; FLASH_OBProgramInitStruct.WRPState = OB_WRPSTATE_ENABLE; FLASH_OBProgramInitStruct.RDPLevel = OB_RDP_LEVEL_1; FLASH_OBProgramInitStruct.OptionType = OPTIONBYTE_WRP | OPTIONBYTE_RDP; HAL_FLASHEx_OBProgram(&FLASH_OBProgramInitStruct); HAL_FLASH_OB_Launch(); HAL_FLASH_OB_Lock(); HAL_FLASH_Lock(); } if( *(__IO uint32_t *)(0x0801F800) == *(__IO uint32_t *)(0x1FFFF7AC)) { if( *(__IO uint32_t *)(0x0801F804) == *(__IO uint32_t *)(0x1FFFF7B0)) { if( *(__IO uint32_t *)(0x0801F808) == *(__IO uint32_t *)(0x1FFFF7B4)) { while (1) { LL_GPIO_TogglePin(GPIOC, LL_GPIO_PIN_6); LL_mDelay(25); } } } } while (1) { LL_GPIO_TogglePin(GPIOC, LL_GPIO_PIN_6); LL_mDelay(1000); } }
方法确实不错,
在程序中不要直接出现1ffff7e8,另外最好程序进行校验,可以加q聊聊,5225016
三、利用id做软件加密
1,如果板子上有外部存储器,可以先编写一个程序,利用算法把id计算得到一些值存入外部存储器,然后再烧写真正的程序,真正的程序去校验外部存储器的数据是否合法即可
2,利用板子上按键组合,或是上电按住某些键,程序在这个时候利用算法把id计算得到一些值存入程序区(stm8为EE区),程序运行时去验证程序区数据是否正确
3,轩微编程器有软件加密的功能,编程器会读芯片id,根据算法直接改写缓冲区,达到软件加密的作用
4,读出的id通过一定算法,例如异或加上一个数,得到的数据存入flash(只运行一次,运行后标志位也存入flash),下次读到这个标志位,就不运行这个程序。//Q9272078
四、做软件加密时注意
1,不要在程序中直接出现id地址,例如STM32:1FFFF7E8 1FFFF7EC 1FFFF7F0 STM8: 0x4865~0x4870
2, 利用校验和或是crc对程序区进行校验,防止改程序