单片机防破解,近几年专门针对于产品设计,最终在产品程序加密这一块,发现是一个非常实际的问题,公司研发产品几十万,竞争对手花几万破解复制你的产品,而其他竞争对手能够使用更低的成本复制已经被破解的产品,让你的产品在短短1个月内成为烂大街的货;在这种市场风气下非常阻碍具备创新能力公司的发展;因此在3个月各种询问以及沟通过程中,从如何破解单片机系统到如何防止破解进行说明,希望能够帮助具有相同需求的朋友;在此利用市场上破解率最高的STM32单片机来说明。
一、破解单片机系统,分为两步:
1、从单片机中将二进制文件读出;虽然单片机有各种所谓的读/写保护机制;防止bin文件被读出,读出的方法起始也很简单,将单片机的晶元漏出,在晶元上跳线,将读保护从硬件上跳过,再用设备读取Bin文件,(不同的单片机这一块的难度也有不同,例如目前绝大部分的STM32F1系列单片机晶元破解技术已经成熟,而STM32F4系列只有少部分的系列可以进行此破解,并不是不能晶元操作只是市场占有率比较低破解需求小,破解行业还不愿意花费大量成本来拓展这一块);本质上这些都是成本的问题,愿意花巨额破解也是可以的。
2、二进制文件破解,能够独立运行;说明白一点就是将Bin文件中和单片机标志相关的或者和外部硬件设备相关而导致Bin文件不能通用(就是能够直接复制使用)的部分进行屏蔽,能够让Bin文件独立的在任何一个相同的平台上运行;这个部分属于软件破解,破解人员拿到bin文件后会将其进行反汇编成为汇编代码,直接使用汇编代码在在破解的平台上仿真运行观察文件执行流程(这点需要消耗大量的人力和时间);软件加密大体分为两部分,密文加密、硬件加密;密文加密一般都是将单片机内部的标志性密文,例如STM32的UID或者相同单片机具备不同硬件数据的部分在软件层面上进行绑定,最最简单的就是STM32在上电的时候读取UID比对,如果错误就怎么处理等,破解密文加密实际上就是通过仿真跟踪的手段,找到密文加密地点,改写此段的汇编代码,通过多种方式绕过密文对比,或者更改密文对比结果,从而屏蔽密文对比对程序的作用,目前用的最多的就是转移读取密文的位置,破解者将相同的UID密文数据写在FLASH内部的某个地方(也就是Bin文件的某一个地址),并且在STM32读取UID时不读取硬件UID而是读取破解者存在在FLASH内部的UID,将程序蒙骗过去,破解完密文加密后,此时的Bin文件就和单片机内部的密文一点关系都没有,读密文的时候都是程序自己读自己bin的某一个数据和硬件平台没有关系了,如果没有硬件加密此时就可以在任意相同的平台上运行了;硬件加密一般用的比较多的就是加密芯片,这种方式加密方法会强一些,破解方法一般会建立在密文加密之后,硬件解密也是两种方法:第一就是在单片机内部找到和外部加密芯片通信的程序观察发出哪些数据和接收哪些数据,同时在外部硬件设备上通过逻辑分析仪进行同时观察,记录结果,由于通过密文解密之后,设备已经成为通用设备,并且密文也是一个假的固定密文,通过这个固定密文算出的加密运算符也是固定的,从设备发给加密芯片的加密码也就是固定的,加密芯片通过固定的加密算法返回的密文也是固定的,所以这个时候程序内部可以将这个读取的部分跳过,或者在外部仿制一个固定的通信过程,取代加密芯片即可,这一步做完硬件加密就完事了。
实际上破解加密就是把单片机有特异性的部分全部屏蔽掉,从实际上说在不差钱和时间的情况下没有破解不了的系统;作为加密者能做的就是极大的增加其解密的成本和周期,拖住对方;
加密方法:
1、大量使用内联验证函数;
验证函数是用来检测本系统是否被破解的功能函数,内部应该包含加密的正反解算法,在此特别说明一定要用内联函数 inline,普通函数作为一个反复调用的模块编译时被存储在bin文件的固定地点,每次调用时会跳转到这个地点运行,如果验证函数使用普通函数,那么破解人员只用搞定存储验证函数在bin文件的这个区域就万事大吉了,那么系统中所有验证功能都被破解了;而内联函数在系统编译时会将函数复制在调用的部分成为一个分身,是一块独立部分,如果系统在不同的地方调用了10次内联函数,那么就有10个功能相同的函数在bin内,互不影响,这样可以有效的增加破解的时间成本,狡兔N窟;验证函数最好放在一些不经常运行到的程序中,在程序体积与性能允许的情况下,×××;
2、读取密文绝对不使用直接寻址;
由于Bin文件被反汇编之后成为汇编代码,如果只直接寻址(例如寻址到UID密文0X11111111地址上的数据)那么被寻址的地址是直接在汇编代码上可以看到的,直接通过查找功能就可以锁定读取密文的位置,所以一定要用间接寻址,例如我们要寻址0x11111111,可以制定一个32位数据指针,先让其等于0x11110000,再加上0x00001111,最后等于0x11111111再进行寻址,这样的方法破解人员只能在仿真时严格跟踪R0-R3寄存器,才能发现在哪读取了密文,增加其破解时间成本和难度;
3、尽量增加外部功能硬件的密文数量,获取密文后进行算法运算增加其复杂性;此处实际上是增加其余的密文,避免破解人员观察加密程序读取UID的代码位置,防止被锁定;
4、全文加密,针对于单片机系统的程序区code进行全文计算算出MD5,计算出MD5存储到某一个位置,如果bin文件中程序区段被修改,那么在检测函数针对全文进行二次MD5验证是得到的密文会和之前不同,这种方法可以查看出代码区是否被动过手脚;
5、程序中发现被破解或者动过手脚不要卡死,或者不要有任何实时的处决动作,而是尽可能的延后处决;这个很重要,因为在破解人员自认为破解成功后,会自行测试设备是否能够正常运行,如果防破解此时发现被破解直接自毁程序或者卡死,那么就是告诉破解人员还有地方没有破解完成,需要继续,这个时候需要用户做的就是设置一个延迟处决的代码,当发现系统被动过手脚,先要按兵不动,程序能够正常运行,当系统重新启动500次或者通电时间超过1000个小时,系统再自毁,增加足够的测试周期,极大地延缓测试频率,拖慢脚步,如果此时被误认为已经破解成功,并量产产品,往往会对破解用户造成足够大的经济损失;更绝的是在自毁之后再FLASH中写入当前代码的原作者以及公司,通过bin读取出提取信息,可以告发对方侵权!
原文地址:http://blog.51cto.com/13690049/2094999