有次出差去客户现场调试对方总工突然问我你们这个设备如果有人把flash读出来是不是代码就全裸奔了我愣了一下。说实话当时那个产品就是个简单的温湿度采集器stm32f103c8t6连RTOS都没上跑着超级循环。我一直觉着这种东西谁会去搞又不是什么银行加密机。但后来认真想了想这问题其实挺要命的。做嵌入式这么久安全这块儿大多数人都当耳边风——包括我自己在内踩过坑才知道疼。先说说最常见的安全防护误区很多搞嵌入式的哥们觉得产品跑得稳就行安全那是互联网的事。大错特错。这几年我见过太多离谱的事。有个同行做的智能家居网关被人直接从串口把整个文件系统dump出来了连加密都没有API key、服务器地址全明文。竞品公司拿去改了个logo就出货打官司都扯不清。还有个客户买了一批设备被人在bootloader阶段植入了挖矿程序每天半夜CPU跑满。你MCU里跑的固件在物理接触面前就是一堆明文——除非你做了防护。最简单的第一道防线读保护STM32有个RDPRead Protection功能level 1就能挡住大部分jtag读取。void check_rdp_level(void) { FLASH_OBProgramInitTypeDef ob; HAL_FLASHEx_OBGetConfig(ob); if(ob.RDPLevel OB_RDP_LEVEL_0) { // 裸奔状态赶紧锁上 ob.RDPLevel OB_RDP_LEVEL_1; HAL_FLASH_Unlock(); HAL_FLASHEx_OBProgram(ob); HAL_FLASHEx_OBLaunch(); // 注意调完会复位 } }level 1就是告诉调试器别想随便连我level 2直接焊死不能回退。但level 2得想清楚再设——设完了连你自己都debug不了只能报废换芯片。别笑我真见过有人量产前忘了改配置全贴了level 2的片子结果出厂测试发现有个bug要修一整个批次全废了。不过说实话RDP level 1也就防防脚本小子真正铁了心要搞你的人用化学腐蚀开盖探针一样能读出来。所以别以为上了RDP就万事大吉——它就是个门锁防君子不防贼。另一个坑bootloader被人当后门用有次我看一个设备的启动逻辑void bootloader_check(void) { if(button_pressed() usb_connected()) { goto_bootloader(); // 直接跳boot } jump_to_app(); }好家伙拉个gpio进boot模式串口直接就能用flashloader把整个flash读走。这跟把自家大门钥匙挂门框上有什么区别后来我改了方案——boot入口要校验签名不是随便发个指令就让你进。bool verify_boot_signature(uint8_t* sig, uint32_t len) { // 用预置的public key验证签名 // 验证通过才允许进入固件升级模式 if(hash_check(sig, len, PUBLIC_KEY)) { return true; } // 三次失败后直接锁死需要硬件恢复 return false; }也不是什么高级东西hmac-sha256算一遍的事。但就这一道坎能把九成想搞事的人挡在外面。他们需要的不是破解你而是换个目标。内存溢出你觉得没事就出事了之前有个同事写的代码char buf[64]; sprintf(buf, Sensor:%s, user_input); // 用户输入长度未知这段代码在PC上可能跑好几年也没事。但嵌入式环境里栈空间就那么几K精心构造的输入能直接把你return address改掉跳到攻击者事先埋好的shellcode上。ARM的栈溢出利用早就被研究透了网上工具链一把一把的。我后来习惯的做法char buf[64]; snprintf(buf, sizeof(buf), Sensor:%.48s, user_input); // 留够余量看着是挺无聊的改动但搞过远程利用的人都知道这就是能防和不能防的区别。通讯链路谁在跟谁说话之前一个产品被客户吐槽你们这破设备连个密码都没有后来加了个简单的配对逻辑。上位机第一次连接的时候两边交换一个随机数种子之后每次通讯数据包的前两个字节都是基于这个种子算出来的滚动校验码。static uint16_t calc_challenge(uint16_t seed, uint32_t counter) { // 简单但够用的滚动码 uint16_t code seed ^ (counter 0xFFFF); code (code 5) | (code 11); return code ^ 0xA5A5; }简单但确实挡住了几波想直接模拟上位机发包的人。对方发现每包数据都对不上也就放弃了。说到底安全是成本和风险的博弈不用一上来就上全套TPM安全芯片加密协处理器。又不是做航天军工。但基本的几条得守住生产阶段把RDP配置进初始化代码里。bootloader入口不能裸着。所有外部输入进来第一件事就是做长度检查和格式化。OTA升级包至少做个hash校验。通讯链路别完全裸奔对称加密也好滚动码也好总得有一层。做嵌入式安全就是个不断抬高门槛的过程。你不需要做到攻不破——只要做到你的设备比隔壁那家难搞黑客就会去找隔壁。最后说一句你现在用的产品RDP开了没