在MCU固件加密这件事上,作为开发者的我最怕的就是自己熬夜写的代码被人白**或恶意篡改。毕竟,固件里藏着技术核心,一旦泄露,轻则损失很严重,重则被竞争对手抄个底朝天。今天聊一下从硬件、算法、策略三个角度聊聊怎么给固件上锁,顺便吐槽几个案例。
首先是硬件防护,从芯片到电路板,堵住物理漏洞,不让人家知道是用的什么芯片或者锁死Flash,硬件是固件安全的第一道防线,但别以为锁死Flash就万事大吉,攻击者的手段比你想得更野。
芯片级读保护,防君子不防小人?
很多MCU自带读保护功能像STM32的RDP、NXP的Secure Boot),原理是烧断芯片内部的熔丝或设置寄存器,禁止外部工具JTAG/SWD读取Flash。
其实还是有不好的地方,RDP Level 2虽然能彻底锁死Flash,但会永久擦除数据,升级固件时得重新烧录,风险极高。有些芯片的读保护可能被物理攻击**,用激光切割熔丝,或用电压毛刺触发芯片漏洞。
不过读保护必须搭配其他手段,加密算法,否则就很不安全。
很多开发者图省事,把AES密钥直接写在代码里,结果被逆向工程一扒就露馅。
有的是用芯片的OTP一次性可编程区域存储密钥,烧录后无法修改。
或者用独立的安全芯片SE芯片存储密钥,MCU通过加密通道调用。
在一些IoT设备被曝出AES密钥硬编码,攻击者直接提取密钥解密固件,厂商连夜发补丁。
还有在防调试电路,别让攻击者偷窥,有些MCU支持调试接口密码保护像芯源提到的调整代码需要密码,但更稳妥的做法是,在电路板上设计防调试电路,检测调试接口的电压/电流异常,触发自毁机制擦除敏感数据。
或者用物理手段环氧树脂灌封直接封死调试接口,但会牺牲可维护性。
加密算法,但别自己挖坑,加密算法是固件安全的第二道防线,但用错了比不用更危险。
常见做法是对固件分段加密,运行时由MCU解密。为什么说是自己挖坑,密钥存储在Flash中,等于把钥匙和锁一起交给攻击者。解密算法太简单(异或加密,被逆向工具秒破。
我一般是用AES等标准加密算法,密钥存储在安全区域,解密过程在RAM中完成避免被Dump。
混淆能增加逆向难度,变量名替换、插入冗余代码、控制流扁平化。结合虚拟化技术,把代码翻译成虚拟机指令。有的厂商用简单混淆工具,结果被攻击者用IDA Pro自动去混淆,代码逻辑一览无余。
把关键代码存储在外部Flash或EEPROM中,运行时动态加载到RAM并解密。加载过程需校验完整性,防止被篡改。避免在RAM中留下解密后的代码痕迹。
多重防护,单一防护手段容易被攻破,必须组合出击。安全启动从源头验证Bootloader需校验应用固件的签名或哈希值,确保固件未被篡改。
公钥需存储在安全区域,私钥千万别泄露。在有些厂商的Bootloader未校验固件版本号,被攻击者替换为旧版漏洞固件。
防回滚机制,别让旧版本出现安全问题,防止攻击者降级固件版本,绕过新版本的安全补丁。在Flash中记录当前版本号,Bootloader拒绝加载低版本固件。
定期更新与漏洞修复,修复已知漏洞。升级加密算法。
安全芯片的钱不能省,否则可能赔上整个项目。
读保护+加密+校验,缺一不可。
密钥存储、调试接口、版本回滚,每个环节都可能成为突破口。
|