论单片机程序固件保护的重要性和方法

说在前面的话

首先说一下为什么要发这个博客,前段时间在论坛里偶然看到很多人在讨论单片机如何加密,之前有过这种保护意识,公司的产品也在使用一些加密和读写保护方法。看了大家的讨论来了兴趣,于是在百度和谷歌到处搜索关于单片机加解密的文章,有的是工程师同行发的,有的是为了吸引流量的破解公司发的,当然也只是只言片语,大家都知道的方法。先谈谈感受吧,第一点,大多数工程师的保护意识太弱了,甚至根本就没这个意识,但是大家都集思广益,确实让不少人知道了很多关于单片机加密的重要性和手段。第二点就是大家提出的各种方法如果单一的使用显得太薄弱了。写博客之前我一直在犹豫这篇博客发出来到底是帮助工程师同行呢还是最终帮了破解公司那帮偷盗者呢,转念一想,可能利大于弊,毕竟保护了总比没保护的好。

现有的固件保护方法

防止抄袭和抄袭本身本来就是一对对立的阵营,正如细菌和抗生素一样,我们抵抗细菌的手段在不断更新,细菌也没闲着啊,在忙着进化。随着开发成本的提高,电子产品抄板市场也变得很大,坛子里有人说深圳解密拷贝出STM32固件只需要五千元,不知道是不是真的。

大致总结了一下目前很多网友和工程师朋友都提到的方法
1、使用J-Flash烧录完程序点secure chip设置保护。
2、代码里对Flash加锁。
3、代码里映射Jtag和SWD相关的引脚为别的功能,甚至直接从物理上剪断调试引脚或者烧毁调试口
4、使用单片机唯一ID号进行判断,相当于绑定硬件,再高级点的做法是利用ID加密,密文存储到一个位置,程序中再解密出来和明文的ID号比较。
5、对程序全部或者关键位置进行CRC校验。
6、自己开发具有bin文件加解密的上位机升级或烧录程序,或者使用专用的加解密烧录器,这个办法主要是针对需要外发bin文件给客户进行升级的情况。

现有的固件破解方法

再说破解:先表明一个观点,我觉得这也是几乎所有同行的共识,就是世上没有不能破解的,只是时间与成本的问题。
针对以上保护方法阐述一下可能的破解方法:
首先第一类读出程序类:
1、对于第1点、第3点:据说有漏洞可以解除限制,你让我读不出来是吧,好,据说有非常有效的读出办法,那就是磨开芯片给存储器拍照,然后用专门的识图软件读出各个位置的0和1。我想说当初想到这个的真是个狠人。
2、对于第2点:就更简单了,你以为代码起作用了,JTAG口不能用了,你想少了,本人亲测可以利用单片机复位间隙进入SWD模式可以读固件,猜想原因可能是单片机内部还有一段不可擦写的bootloader在运行,这个空档SWD还是可用的。
第二类就是读出数据以后:
3、对于第4点:我在下面已经说的很明白了,像判断语句,死循环,用明文进行判断比较之类的太容易看出来位置了,破解者可以方便的定位到这个位置,然后修改bin文件,跳过这里。
4、对于第5点:对程序校验可以知道程序是否被修改过,这个安全性可能稍微高些,但是如果校验算法简单,别人修改了程序以后,同样的方法可以把正确的校验值填充好。
5、对于非联网产品,不具备OTA能力,需要客户自己升级bin文件这种情况没有办法,我们总不可能叫客户从全国各地邮寄回来升级。这种情况下破解者知道了加密原理也是容易破解的,最好使用非常规的加密方式或者有更好的手段。

稍微靠谱点的固件保护方法

1、尽可能的综合上面提到的所有方法对最终发布的固件进行保护,增加破解的难度,当然也可以根据代价或者方便维护性进行选择,多多益善,尤其是对于软件高附加值的产品,比如你的软件具有行业先进性,先进的某些算法或者数据。

1、在程序代码中植入混淆一段公司的logo,最好经过AES加密的或者经过特殊编码的,比如BASE64,放到某个大的数组里,这个数组会被程序里用到,但是里面又混淆了这些看似无关的数据。为什么要这么做呢,这样太有用了,到时候你要说别人盗版你的固件,你得有证据啊,可以当着专门的鉴定机构的面,大大方方的还原这个logo。

2、不要在判断程序合法性的关键代码上使用立即数或者直接能看出来的字符串,比如以下程序,另外大家都知道单片机的唯一ID号存放在什么地址,这个地址也不要用立即数,用各种混淆的方法计算得到这个数,加减乘除,按位操作,最好让自己看着代码摸不着头脑,更不要说看着二进制的破解者了。

if( 0xFE != flag)
{
   //代码进入死循环或者故意设置错误的参数,让系统不正常运行
}
//改进以后
unsigned char temp = 0;
unsigned char temp1 = get_value(addr1 + addr2);        //混淆地址
unsigned char temp2 = get_value(addr4 - addr5);         //混淆地址
unsigned char flag = get_value(addr3 * 2);                     //混淆地址
temp = temp1*2  + temp2 + 1;            //混淆值
if( temp != flag)             //其实用if这种方式也不太好,最好有更加精巧的判断方式,比如A?B:C这样的
{
   //代码进入死循环或者故意设置错误的参数,让系统不正常运行
}
if( 0 == strcmp(str , "hello"))
{
   //代码继续执行
}
//改进
//把hello这个字符串进行MD5校验存放,并且最好分开存在不同地方,用的时候再RAM中拼接而成

3、不要在一个地方对固件合法性进行验证,而且验证不通过最好不要用while(1)之类的停止程序运行,因为破解者也容易找出这个位置,最好是让程序继续运行,但是参数不对,或者胡乱运行。

4、如果设备会上网,或者设备会不定期的上网,这个就好办了,第一:网络数据可以直接用加密算法或者直接使用MbedTLS加密,就算抓到数据也不知道是啥,最好是动态秘钥,隔一段时间变更,具体可以参考HOTP和TOTP算法,再此不多讲。第二:服务器最好能通过唯一ID号对设备进行数据库匹配,拒绝未登记过的设备。

5、真正的高手是设置一段门槛,让程序似乎是破解了,似乎又没被破解,让你千辛万苦历经磨难终于读出了固件,烧录进新的单片机,居然可以运行,并且运行的好好的,还做了老化都没问题,满心以为终于可以了OK量产吧,大批量出货,结果发现过了半个月或者一个月,机关发作了,潘多拉的盒子关不住了,陆陆续续客户都来退货了,说产品不稳定,不可靠,然后你忙着出差解决问题,退款,结果有人找上门说你侵犯了知识产权,并提供了你产品涉嫌抄袭的证据。其实都是预设的陷阱,等着你钻进去套牢。

结束

随着技术不断发展,嵌入式软件开发成本和门槛的降低,我相信已经越来越少的人去破解别人的固件,抄板仿造,毕竟如果破解的成本大于或者几乎等于去研发这款产品的成本了,肯定是没人愿意干这个事情的。最后本文能提高各位同行对智力成果的保护意识,以及对固件的保护提供一点思路,欢迎大家留言提出更多更好的办法。
在这里插入图片描述

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值