找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1667|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

Unique ID的單片機程序加密系統(tǒng)

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:260753 發(fā)表于 2018-8-6 11:32 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式

  • 單片機一般作為一個產(chǎn)品的邏輯中心,工作時一直在進行著邏輯判斷與執(zhí)行操作,相當(dāng)于人類的大腦。單片機可以通過修改程序來控制外圍電路的工作狀態(tài),從而改變產(chǎn)品的功能。如果一個產(chǎn)品具有單片機,那么它往往是這個產(chǎn)品的核心。而開發(fā)一款功能復(fù)雜且成熟的產(chǎn)品所需要的費用不低并且研發(fā)周期較長,一些個人為了某些原因,為了快速仿造競爭對手的產(chǎn)品,一般就原樣照抄對方的硬件電路,但由于單片機內(nèi)部有針對產(chǎn)品功能單獨設(shè)計的程序,不能直接再市面上購買,所以就只能想辦法通過特殊的解密方法將單片機內(nèi)部的程序讀取出來。將解密后讀取出來的程序燒錄在新的芯片中從而完成產(chǎn)品功能的抄襲。通過專用的設(shè)備和工具,利用單片機芯片設(shè)計上的硬件漏洞或軟件缺陷,通過多種技術(shù)手段獲取單片機內(nèi)程序這叫做單片機解密或單片機破解。以不正當(dāng)方式獲得其他公司或個人的商業(yè)秘密,是一種常見的不正當(dāng)競爭行為。單片機加密技術(shù)是對產(chǎn)品知識產(chǎn)權(quán)保護的一種技術(shù)手段。

Unique ID加密原理
當(dāng)前市面上的單片機資源中大多數(shù)具有Unique ID,即每一個芯片內(nèi)部均具有唯一的芯片ID號。不同的芯片廠家實現(xiàn)該功能的方式不同,一些用生產(chǎn)線的流水號,另一些是用晶圓的特性來生成ID。 利用Unique ID加密的方法流程如下:

  • A. 將單片機燒錄程序A后上電運行程序,完成加密操作。
  • B. 將單片機燒錄程序最終程序B,該程序包含ID識別部分。 加密流程圖如下:
  • 程序A負(fù)責(zé)讀取芯片內(nèi)部的Unique ID,并進行加密運算。將運算的結(jié)果寫入芯片內(nèi)部的EEPROM。
  • 程序B是實現(xiàn)產(chǎn)品最終功能的程序,該程序其中加入了產(chǎn)品身份識別功能。該程序首次上電后將首先讀取EEPROM數(shù)據(jù),并進行與加密算法相同的逆向算法,將加密后的數(shù)據(jù)進行解密獲得芯片Unique ID。將解密后的ID與當(dāng)前芯片的ID進行比對,如果數(shù)據(jù)不同則判斷為非法程序。

加密算法

為了防止破解者通過仿真的方式找到芯片ID信息,一般不宜直接存放ID號。而是經(jīng)過相應(yīng)的加密處理后寫入存儲器中。校驗方式也不宜采用常見、簡單的校驗規(guī)則,應(yīng)盡可能采用某些特殊的檢驗方式,使破解者不能迅速確定校驗算法。
加密的算法類似數(shù)學(xué)公式 Y=F(X)
其中Y為加密以后的數(shù)據(jù),X為原始數(shù)據(jù),而F則為加密算法。
加密算法有很多種,本實驗中采用簡單的位移后取反的方式來進行數(shù)據(jù)加密。

最后將加密的數(shù)據(jù)存入EEPROM中,由于芯片的ID廠家不允許更改,這大大增加了破解難度,加強了對產(chǎn)品的保護。

詳細(xì)設(shè)計過程
使用Unique ID對單片機程序加密功能的實現(xiàn)需要以下幾點功能:
① 實驗板1用于對程序加密實驗。
② 將從實驗板1中讀取到的數(shù)據(jù)燒錄到實驗板2中,通過實驗板上的LED狀態(tài)驗證程序加密是否成功。
基于Unique ID的單片機程序加密分為2個程序,這2個程序是不同的。
程序A:用于讀取芯片硬件ID并進行算法處理,將處理后的數(shù)據(jù)保存到EEPROM中。
程序B:用于將EEPROM中的數(shù)據(jù)讀取出來并使用與加密相同的算法進行解密獲得芯片ID,將解密后獲得的ID與芯片本身的ID進行比較。比較結(jié)果只有2種可能,即為相同與不同,程序根據(jù)結(jié)果從而執(zhí)行不同的操作如圖所示;

實驗中使用STM8S單片機作為硬件載體

軟件設(shè)計

系統(tǒng)初始化函數(shù)選擇了內(nèi)部16MHz時鐘源,1分頻后系統(tǒng)總線時鐘頻率為16MHz。
將GPIO與EEPROM擦寫均進行了初始化配置。 函數(shù)代碼如下:

void SystemInit(void){    CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);    //總時鐘源 使用內(nèi)部時鐘源1分頻 16M/1分頻 =16MHz    Gpio_Init(); //單片機系統(tǒng)GPIO初始化 FLASH_DeInit();//存儲數(shù)據(jù)的EEPROM初始化    FLASH_SetProgrammingTime(FLASH_PROGRAMTIME_STANDARD);// 默認(rèn)的EEPROM寫入時間}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

LED驅(qū)動程序

根據(jù)硬件的電路原理圖可以看出,LED連接到PE5引腳。采用灌電流驅(qū)動,當(dāng)引腳為低電平時LED點亮,引腳為高電平時LED熄滅。上電后LED默認(rèn)為熄滅狀態(tài),所以引腳初始化配置為高速輸出模式高電平。函數(shù)代碼如下:

/*描述:MCU外圍GPIO初始化*//*輸入:無*/void Gpio_Init(vod){    //功能引腳上電初始化,引腳初始化狀態(tài)根據(jù)外部功能而定義//    GPIO_Init(GPIOE, GPIO_PIN_5, GPIO_MODE_OUT_PP_HIGH_FAST); //LED}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

LED的狀態(tài)采用宏定義方式,直接控制IO管腳電平狀態(tài)。 操作代碼如下:

/*LED操作宏定義*/#define LED_ON GPIO_WriteLow(GPIOE, GPIO_PIN_5); //點亮LED#define LED_OFF GPIO_WriteHigh(GPIOE, GPIO_PIN_5); //熄滅LED
  • 1
  • 2
  • 3

獲取Unique ID程序

STM8S105K4T6數(shù)據(jù)手冊顯示該芯片具有96bit Unique ID,96bit/8=12byte。存放ID的起始地址為0x48CD,從該地址讀取12次,將芯片ID獲取并存入數(shù)組。 函數(shù)代碼如下:

/*描述:獲取芯片ID*//*輸入:存放芯片ID的數(shù)組*//*輸出:無*//*參數(shù):無*/void Get_ChipID(unsigned char *p)//Get chip ID{    unsigned char i=0; for(i=0; i<12; i++) //讀取12次    {        *p = *(u8*)(0X48CD+i); //將數(shù)據(jù)讀出后進行存放        p++;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 121
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

加密算法程序

編碼函數(shù)執(zhí)行對Unique ID進行數(shù)據(jù)算法處理。實驗中采用的算法為將存放Unique ID的數(shù)組進行左移三個元素后逐位取反。將編碼后的數(shù)據(jù)存入另一個數(shù)組。
編碼函數(shù)代碼如下:

/*描述:對芯片ID進行編碼處理*//*輸入:存放芯片ID的數(shù)組;存放芯片ID編碼后的數(shù)組*//*輸出:無*/ /*參數(shù):對輸入數(shù)組左移三次后逐位取反*/void Encode(unsigned char *DataIn,unsigned char *DataOut)//對數(shù)據(jù)進行編碼加密{    unsigned char i;//數(shù)組數(shù)據(jù)左移次數(shù) unsigned char j;//數(shù)據(jù)位移臨時局部變量    unsigned char DataSwap;//搬運數(shù)據(jù)用的臨時變量    unsigned char TempData[12];//數(shù)據(jù)處理交換變量數(shù)組    for(i=0;i<12;i++)//數(shù)據(jù)數(shù)組交換    {        TempData = *DataIn; DataIn++;    }    for(i=0;i<3;i++)    {        //數(shù)組元素左移操作        DataSwap = TempData[0];        for(j=0;j<11;j++) //數(shù)組左移搬運        {            TempData[j] = TempData[j+1]; } TempData[11] = DataSwap;        }    for(i=0;i<12;i++)    {        TempData = ~ TempData ; //對數(shù)組數(shù)據(jù)進行按位取反        *DataOut = TempData ; DataOut++;    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

解密算法程序

解碼函數(shù)負(fù)責(zé)對從EEPROM中讀取的數(shù)據(jù)進行解碼,是編碼函數(shù)的一個逆向算法處理。算法為將輸入的數(shù)組(EEPROM數(shù)據(jù))進行右移三個元素后按位取反。示意圖如下:

函數(shù)如下

/*描述:對從EEPROM讀出的數(shù)據(jù)進行解碼*//*輸入:存放編碼數(shù)據(jù)的數(shù)組,存放解碼數(shù)據(jù)的數(shù)組*//*輸出:無*//*參數(shù):數(shù)據(jù)右移三位后按位取反(算法)*/void Decode(unsigned char *DataIn,unsigned char *DataOut){  unsigned char i;//數(shù)組數(shù)據(jù)左移次數(shù)  unsigned char j;//數(shù)據(jù)位移臨時局部變量  unsigned char DataSwap;//搬運數(shù)據(jù)用的臨時變量  unsigned char TempData[12];//數(shù)據(jù)處理交換變量數(shù)組  for(i=0;i<12;i++)//數(shù)據(jù)數(shù)組交換  {    TempData = *DataIn; DataIn++;  }  for(i=0;i<3;i++)//數(shù)據(jù)右移三次  {    //數(shù)組元素右移操作    DataSwap = TempData[11];     for(j=10;j>0;j--)//數(shù)組右移搬運    {      TempData[j+1] = TempData[j];    }    TempData[1] = TempData[0];    TempData[0] = DataSwap;//最后一次搬運  }  for(i=0;i<12;i++)//對數(shù)組數(shù)據(jù)進行諸位取反  {    TempData = ~ TempData ;    *DataOut = TempData;    DataOut ++;  }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

數(shù)據(jù)寫入EEPROM程序

將編碼處理后的數(shù)據(jù)寫入EEPROM,存儲器起始地址為0x000040A0,通過單字節(jié)寫入。將12個字節(jié)全部寫入EEPROM。函數(shù)代碼如下:

/*描述:EEPROM數(shù)據(jù)寫入*//*輸入:數(shù)據(jù)源的數(shù)組*//*輸出:無*//*參數(shù):無*/void EEPROMWrite(unsigned char *p){  unsigned char i;//數(shù)據(jù)交換用局部臨時變量  FLASH_Unlock(FLASH_MEMTYPE_DATA); //解鎖EEPROM,允許寫入數(shù)據(jù)  while( !(FLASH_GetFlagStatus(FLASH_FLAG_DUL)) );//等待EEPROM解鎖完成  for(i=0;i<12;i++)  {    FLASH_ProgramByte(0x000040A0+i, *p);//將數(shù)據(jù)寫入EEPROM,寫入存儲起始地址為0x000040A0    while( !( FLASH_GetFlagStatus(FLASH_FLAG_EOP)) );//等待EEPROM單次寫入完成    p++;  }  FLASH_Lock(FLASH_MEMTYPE_DATA); //鎖定EEPROM}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

從EEPROM讀出數(shù)據(jù)程序

程序首先需要從EEPROM中讀取加密后的數(shù)據(jù),將數(shù)據(jù)保存到數(shù)組EncodeData中。程序代碼如下:

/*描述:讀取芯片EEPROM數(shù)據(jù)*//*輸入:用于存放EEPROM的數(shù)組*//*輸出:無*//*參數(shù):*/void Get_EEPROMData(unsigned char *p){  unsigned char i=0; for(i=0; i<12; i++)  {    *p = FLASH_ReadByte(0x40A0 + i);//從EEPROM讀取數(shù)據(jù)    p++;  }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

數(shù)據(jù)比對程序

數(shù)據(jù)比對函數(shù)負(fù)責(zé)將解密后數(shù)據(jù)與Unique ID兩個數(shù)組的數(shù)據(jù)進行比對。該函數(shù)只有兩個返回結(jié)果,數(shù)據(jù)完全相同與不同,返回不同的值。根據(jù)不同的返回值從而判斷程序是否合法。函數(shù)代碼如下:

/*描述:將兩個數(shù)據(jù)進行比對*//*輸入:要比對的數(shù)據(jù)A,要比對的數(shù)據(jù)B*//*輸出:比對結(jié)果 1:數(shù)據(jù)相同 0:數(shù)據(jù)不同*//*參數(shù):對數(shù)組進行按字節(jié)比對*/unsigned char IDCheck(unsigned char *a,unsigned char *b){  unsigned char i; unsigned char Flag;//比對結(jié)果標(biāo)志 1:數(shù)據(jù)相同 0:數(shù)據(jù)不同  Flag = 1; for(i=0;i<12;i++)  {    if( (*a) != (*b) ) { Flag = 0; } a++; b++;  }  return Flag;//返回值:比對結(jié)果標(biāo)志 1:數(shù)據(jù)相同 0:數(shù)據(jù)不同}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

數(shù)據(jù)數(shù)組
使用數(shù)組的存儲芯片ID與編碼加密后的數(shù)據(jù)。代碼如下:

/*數(shù)組定義*/unsigned char Chip_IDData[12]; //存放芯片Unique ID unsigned char EnCodeData[12]; //對芯片Unique ID編碼加密后的數(shù)據(jù)unsigned char DecodeData[12]; //對芯片EEPROM解密后的數(shù)據(jù)
  • 1
  • 2
  • 3
  • 4

A程序主函數(shù)代碼
本程序主要作用是將數(shù)據(jù)進行加密編碼處理并將結(jié)果寫入EEPROM, 程序的主函數(shù)調(diào)用上方的單元功能函數(shù)。

/*描述:主函數(shù)*//*輸入:無*//*輸出:無*//*參數(shù):無*/void main(void){  SystemInit(); //系統(tǒng)初始化  Get_ChipID(Chip_IDData); //獲取芯片 ID并存儲在數(shù)組  Encode(Chip_IDData,EnCodeData); //編碼運算處理  EEPROMWrite(EnCodeData); //將編碼數(shù)據(jù)寫入  EEPROM LED_ON; //寫入完成后點亮LED  while(1); //軟件循環(huán)}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

運行該程序后,將讀取到的芯片ID數(shù)據(jù)存入數(shù)組。通過內(nèi)部編碼算法函數(shù)將ID進行處理并寫入EEPROM。程序運行流程圖如圖所示:

B程序主函數(shù)代碼
程序B作用為對EEPROM數(shù)據(jù)讀取并進行解碼處理后判斷程序合法性。主函數(shù)代碼如下:

/*描述:Main主函數(shù)*//*輸入:無*//*輸出:無*//*參數(shù):無*/void main(void){  SystemInit(); //系統(tǒng)初始化  Get_ChipID(Chip_IDData);//獲取芯片自身ID Get_EEPROMData(EncodeData);  //從EEPROM讀取編碼后的數(shù)據(jù)   Decode(EncodeData,DecodeData);//將編碼數(shù)據(jù)進行解碼 //將解碼后的數(shù)據(jù)與當(dāng)前芯片ID進行比對  if(IDCheck(Chip_IDData,DecodeData))  {    //返回1 比對通過,芯片與ID身份識別通過    LED_ON; //點亮LED  }  else  {//比對失敗 程序非法    LED_OFF; //熄滅LED    While(1); //死循環(huán)  }  while(1)  {    ; //程序正常執(zhí)行循環(huán)  }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

解碼程序為最終燒錄到芯片中的程序,產(chǎn)品功能也是在次此結(jié)構(gòu)下開發(fā)的。程序執(zhí)行后會讀取當(dāng)前芯片自身的Unique ID與存儲在EEPROM中的數(shù)據(jù)。將EEPROM中的數(shù)據(jù)進行解碼后與Unique ID進行比對,當(dāng)數(shù)據(jù)完全相同時判斷程序合法并執(zhí)行正常程序功能,當(dāng)數(shù)據(jù)比對不相同后判斷程序非法并執(zhí)行相應(yīng)操作。解碼程序運行流程圖如圖所示:

系統(tǒng)測試

將運行B程序后的實驗板1通過通過仿真器與電腦連接,將STVP切換到“Program Memory”選項卡后點擊“Read curren tab of active sectors”按鈕后讀取數(shù)據(jù)。在菜單File->save中選擇保存程序B。(模擬程序被解密)

將讀取的程序B燒錄到實驗板2中,觀察LED的現(xiàn)象。
燒錄程序B后實驗板1測試LED亮起,實驗板2測試LED未亮起。

測試結(jié)果
從實驗中可以看到,實驗板二雖然燒錄了程序B,但是之前并沒有運行過程序A的加密算法,所以程序識別出EEPROM解密后數(shù)據(jù)與芯片自身ID不匹配從而熄滅LED。
本文所設(shè)計的系統(tǒng)已經(jīng)通過上述過程的測試,可以滿足對單片機程序加密的功能需求。

當(dāng)前加密系統(tǒng)中需要完善的部分
程序中僅僅有1處判斷程序合法性,一旦遭到反編譯后容易被破解
程序被判斷為非法后沒有保護操作,應(yīng)加入強制擦除 Flash進行保護
程序需要燒錄2次來完成整個加密系統(tǒng)的流程. 應(yīng)在程序中加入啟動加密條件,實現(xiàn)一次程序燒錄即可完成加


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表