大家都知道,单片机应用系统由硬件电路与控制程序两部分组成,尽管硬件电路部分同样凝聚了设计者的心血,也体现了设计者创造性劳动成果,但却无密可守,惟一有保密可能的就是控制程序部分。如何完善控制程序的加密功能,防止他人破解、盗取、复制单片机应用系统中的控制程序代码成了单片机应用系统开发人员和生产厂家保护自己知识产权不被侵犯的关键措施之一。

我们在分析传统单片机控制程序软件加密技术和硬件加密技术的基础上,探索如何充分利用单片机芯片新增的硬件功能,提出了基于单片机芯片身份识别码(即芯片惟一 ID号)、片内RC振荡器频率离散性、上电标志等多种单片机控制程序的加密策略。

一、新型MCU芯片特征与传统软件加密方式的局限性

1、新型MCIJ芯片特征

近年来,单片机技术有了长足的进步,实现了真正意义上的单片化,主要体现在:支持ISP、ICP、IAP编程方式的Flash ROM存储器已逐渐成为单片机芯片内部程序存储器的主流,对于MCS-51兼容芯片来说,也无须通过总线方式扩展外部程序存储器:内置了1一2个RC振荡器(作看门狗计数器时钟或系统主时钟)。为保护片内控制程序代码的安全,除了进一步强化加密锁定位功能外,部分厂家的MCU芯片,如STC的MCS-51兼容芯片、ST公司Cortex-M3内核的STM32系列芯片还增加了芯片身份识别码。

2、传统软件加密原理及其局限性

传统软件加密方式归纳起来主要有以下几种;

(1)指令伪装法

指令伪装法叫的策略是在不影响控制程序运行条件下,改变汇编语言源程序中个别指令的形态来增大反汇编代码阅读的难度,归纳起来主要有以下几种方式:

a、对采用CISC指令系统的MCU芯片,用DB伪指令在两模块间插入多字节指令(双字节或3字节)的操作码,使反汇编后插入的操作码字节与下一模块第一条指令机器码组合形成新的指令(甚至会继续拆分源程序中第二条指令),使反汇编后看不到真实的汇编指令。

b、将长跳转指令中的目标地址压入堆栈,然后用RET指令代替无条件长跳转指令LJMP。

c、将长跳转指令中的目标地址送DPTR,然后用散转指令JMP @A+DPTR代替无条件长跳转指令LJMP。

不过,以上指令伪装方式最多只能增加反汇编程序的阅读难度,对破解后直接复制的盗取方式没有任何防范作用,严格地说指令伪装法并不属于软件加密范畴。

(2)破坏单片机芯片特定硬件资源加密法

破坏单片机芯片特定硬件资源加密法洲归纳起来主要有以下几种:

a、故意烧坏数据总线。对于MCS-51兼容芯片,程序代码总是从数据总线(PO口)读出,因此人为地将12V高压引到PO口某一I/O引脚,使其下拉N沟MOS管击穿——对地短路。

这一方法对防止片内代码被非法读出是有效的,但其局限性也非常明显:一方面无法通过总线方式扩展并行I/O口(破坏了芯片内部数据总线接口电路);另一方面,不能再通过并行编程方式更新片内程序代码;三是占用了芯片I/O引脚资源。

b、破坏芯片的加密锁定位。由于Flasb ROM擦写次数仅为10K左右,因此在运行中通过IAP编程方式对芯片加密位进行多次擦写,使Flash ROM不能再擦除。这种方式的潜在危险是万一加密位擦除失效后不能再写入,则片内代码就很容易被读出;再就是该方法也不能阻止探针攻击法。此外,软件设计者也不能更新片内程序代码。

c、破坏MCS.51的EA引脚。对于MCS-51兼容芯片来说,当EA引脚为低电平时,将从外部ROM执行程序。于是有设计者试flj破坏E引脚,使MCS-51芯片复位后总是从片内执行程序,但这一方法并不能阻止通过擦除芯片加密琐定位方式读取片内代码。

(3)总线加密法

早期MCS-51芯片内部程序存储器容量小,甚至没有内部ROM,一般均需要通过总线方式扩展外部程序存储器,于是出现了所谓的总线加密法。

总线加密法主要有地址总线乱序法、数据总线乱序法,或在MCU芯片地址总线与存储器地址总线间增加可编程芯片(如GAL、FPGA等)俐,使MCU芯片地址与存储器地址之间形成新的映射关系。这些加密方式对采用外设程序存储器的早期的MCS-51应用系统来说也许有一定的作用,但目前几乎所有的单片机应用系统都不再采用外部程序存储器。

经过长期实践,针对目前主流单片机芯片硬件特征,本文提出了基于芯片身份识别码、片内RC振荡器频率离散性、上电标志等3种实用的单片机控制程序加密方式。

二、基于芯片身份识别码的加密方法

为提高片内程序代码的安全性,最近上市的某些MCU芯片,如STC公司2009年后推出MCS-51兼容芯片、ST公司的STM32系列芯片等每一芯片内部均具有惟一的芯片ID号。因此,在控制程序中可充分利用这一功能完善控制程序代码的保护,该加密方式的加密步骤可按图1所示进行。

单片机控制程序加密方法
设置首次上电标志的目的是为了便于判别编程后是否开机过,第一次上电时读出并保存芯片的ID号。为防止攻击者通过仿真方式找到芯片ID号信息,一般不宜直接存放ID号的原码,而是经过相应的加密处理后再分散存放到不同的Flash ROM存储单元中;校验方式也不宜采用常见、简单的校验规则,如和校验等,应尽可能采用某些特殊的检验方式,使攻击者不能迅速确定校验算法。

为防止攻击者获取控制程序片段中有用代码,一旦发现ID号不符,最简单办法就是借助IAP编程方式删除控制程序代码,当然也可以随机改写控制程序代码中的1~2K字节,如图1所示。

三、基于片内RC振荡器频率离散性的加密方法

具有惟一ID号的MCU芯片加密容易,破解成功率很低。但由于生产成本、专利限制等原因,许多中低档MCU芯片,如大部分厂家的MCS-51兼容芯片、PIC系列芯片,甚至最近上市的STM8S系列芯片都没有惟一芯片ID号功能。对于这类芯片,如果内部含有作为看门狗计数器时钟或唤醒时钟的RC振荡器,如Philips公司的P89LPC900系列MCS-51兼容芯片、STM8S系列芯片、PIC16/18系列芯片等均内置了一定数量的RC振荡器。设计者可充分利用RC振荡器频率离散性生成芯片ID号,提高片内控制程序代码的安全性。

1、用RC振荡器频率作为芯片ID号

这一加密方式的加密原理大致如下:

(1)复位后启动MCU芯片的某一定时器测量RC振荡器的频率。只要定时器计数脉冲来自精度与稳定性都很高的外部石英晶体振荡器,则频率测量误差是可控的,也不会很大。

(2)考虑到RC振荡器输出信号频率受环境温度影响较大,应考虑温度变化、晶振频率误差等对测量结果的影响。例如STM8S系列MCU芯片内部低速RC振荡器标称频率为128KHz~12.5%,通过定时器TIM3测出某一特定芯片内部RC振荡器频率为OxID4ED(即120 045 Hz),则可将OxOID4ED作为该芯片的ID号。大量实验统计表明开机60秒后(上电延迟一定时间后测量的目的是为了等待MCU芯片内部温度稳定,即尽量减小环境温度对结果的影响)同一芯片频率测量误差在1%以内(不同芯片在不同环境下的频率误差可能略有不同,可通过多次实验确定。确定频率误差范围的原则是同一芯片保证每次上电复位后测到的数据均在误差允许范围内,因此允许误差不宜太小;另一方面,不同芯片频率相同的可能性又要尽可能小,因此频率误差允许范围也不能太大)。因此,只要上电后测到的RC振荡器频率与ID号相比,误差在1%以内即认为合法,反之视为非法。

该加密方式流程大致如图2所示。尽管不能排除两芯片频率接近的情形,但如果破解后的程序代码有50%或以上不能运行,那么盗版者就会烦恼万分,知难而退。

单片机控制程序加密方法

采用该加密方式对以STM8S207RB单片机芯片作控制核心的某型防盗报警器的实验统计结果如表l所示。可见只要频率误差取1—2%之间,代码复制后有50%以上的芯片不能正确运行。

单片机控制程序加密方法

(2)用RC振荡器频率校正值作为芯片ID号

部分厂家MCU芯片,如Microchip公司的PIC16/18系列、Philips公司的P89LPC900系列等内置的RC振荡器有频率校正值(保存在相应的寄存器或片内程序存储器特定单元中)。在实践中发现不同芯片的频率校正值有差异。对于具有这一功能的芯片,可将RC振荡器频率校正值作为芯片的ID号,完善控制程序代码的加密功能(操作流程与图1相似)。

尽管频率校正值一般在8位以内,但破解后的控制程序代码有50%以上不能运行就达到目的了。该加密方式实验统计结果如表2所示,可见频率校正值长度越大,代码复制的成功率就越低。

单片机控制程序加密方法

四、基于上电标志的加密方式

基于上电标志的加密方式可概括为“设置上电标志一检查芯片加密状态一检查上电标志一随机改写控制程序代码”,主要用于保护既没有芯片惟一 ID号,也没有片内RC振荡器的低档MCU芯片的控制程序代码不被复制。

1、加密过程

基于上电标志的加密过程如下。

(1)在上电复位后,开中断前,先读出Falsh ROM状态寄存器,确认芯片的加密状态。

(2)如果芯片加密状态正确,则检查首次上电标志(为防止误判,往往选择具有一定特征的字符串作为首次上电标志)是否存在:如果首次上电标志不存在,则判定为第一次上电,设置首次上电标志后进入正常的运行状态。

反之,如果芯片加密状态不正确,可根据首次上电标志是否存在进行相应处理:如果首次上电标志不存在,则表明芯片从未上电过,芯片未加密的原因可能是编程时漏选了加密锁定位,应进入IAP编程状态,对芯片进行加密操作。如果加密成功,设置了首次上电标志后,进入正常的运行状态;如果首次上电标志存在,说明芯片曾经上电运行过,加密位状态不正确,很可能是加密位被人为破坏,应立即启动某一定时器(目的是为了获得随机数),然后进入IAP编程状态,随机改写指定程序段内数十到数百字节(不必擦除改写字节所在扇区,将待改写字节内的“1”变为“0一即可)破坏应用程序代码的完整性,然后关闭中断进入死循环状态或复位退出。

该加密方法具体的加密流程如图3所示。

单片机控制程序加密方法

这种随机改写程序代码的加密方式具有很大的迷惑性;一方面,通过反汇编方式无法获得完整的源程序;另一方面,如果被随机改写的代码属于某一非主功能模块,则破解后的程序运行似乎正常,但它确实是一个不完整、运行后果难以预料的程序。

(2)代码检查与生成

为防止不法分子,通过反汇编、跟踪执行方式找到并删除随机改写程序段内的指令系列,可将改写程序代码段内的指令机器码读出,并以数表方式存放在主程序中。然后在主程序中的适当位置检查随机改写程序段代码的有效性,一旦发现代码无效,则进入IAP编程方式,重新生成改写程序段代码。

单片机应用程序加密与解密技术都在进步,可以说几乎没有哪一种加密技术绝对安全可靠。只能在实践中根据所选单片机芯片的硬件特征,有选择地交叉组合使用两种或两种以上的加密手段,以增大解密难度,并尽可能破坏解密版代码的完整性。但无论采用何种加密方式都应尽量避免增加系统的硬件成本、占用MCU芯片的硬件资源,此外也不能明显降低系统的运行效率。本文介绍的3种加密方式,尽管不能完全避免盗版者的攻击,但多年实践表明交叉组合使用这些加密手段确实能有效提高MCU芯片控制程序代码的安全性,控制程序代码被成功盗取的几率很小,且不占用任何硬件资源,也没有额外增加MCU应用系统的硬件成本。

小知识之振荡器

振荡器(英文:oscillator)是用来产生重复电子讯号(通常是正弦波或方波)的电子元件。其构成的电路叫振荡电路。能将直流电转换为具有一定频率交流电信号输出的电子电路或装置。种类很多,按振荡激励方式可分为自激振荡器、他激振荡器;按电路结构可分为阻容振荡器、电感电容振荡器、晶体振荡器、音叉振荡器等;按输出波形可分为正弦波、方波、锯齿波等振荡器。广泛用于电子工业、医疗、科学研究等方面。