搜索
bottom↓
回复: 674

绝对安全的单片机程序加密技术--如果你的程序再被盗请找我索陪!讨论热烈

  [复制链接]

出0入0汤圆

发表于 2010-3-21 21:15:15 | 显示全部楼层 |阅读模式
注:flywater拥有对标题中“索陪”含义的最终解释权.....

此贴谨献给以下朋友:
  1、面对盗版者屡战屡败、屡败屡战者。
  2、因产品N次被盗,终日郁郁寡欢而呕血500CC以上者。
  3、靠抄版、盗版别人产品,且事业有所成或欲有所成者。--不看此贴恐怕以后饭碗不保(~.~)。
  4、实在无聊,又找不到地方拍砖者。
以下人员可以飘过:
  1、产品从不加密者。
  2、产品不加密也没人盗版本者。
  3、高手及牛人。


[正文]:

传统加密方式:
  1、使用芯片厂家提供加密位配置。
  2、烧断引脚。
  3、利用芯片本身提供的唯一可识别信息。
  4、外加有可唯一可识别信息的芯片。
以上方式的优势及敝端:
  1、不提了,到目前为止,未发现一种不可解密得到其HEX的芯片,如果某哥吹它不可解密,那它一定是个传说....
  2、也不提了....
  3、相信现在大部分朋友都仍是使用这种方式加密,它也确实可有效防止盗版者直接复制你的产品,但用这种方式朋友的产品被盗版的也不在少数。只要懂点汇编,即可对唯一识别码的校验进行修改,比如AVR的OSCCAL方式,盗版者只需在你未校验OSCCAL前将其值修改一下即可,具体方法:把后面的表值绑定及入口函数标号加齐后,主程序开始前只需一句汇编语句就能搞定你的OSCCAL加密。STC也是同样道理,我已在其它贴中提到过。
  4、能解决无序列号MCU的程序加密问题,弊端在于:A、外部序列号可以用另加MCU模拟。B、反汇编后找到读外部序列号的函数,稍加修改即可搞定。

  总结以上的加密方式及各方式失败的教训可以看出,你的最大敌人:懂汇编、且汇编能力较强的盗版者(直接从你电脑上考走源代码的盗版者除外)。

  自从我们第一代、第二代、第...代产品被盗后,我就至力到程序加密的研究及测试,虽然仍无什么大成,但自从第...代后的产品,至今仍无盗版成功者了。
  注:我一直未用程序自宫这种超高境界加密方法----不是说这种方法不好,只是怕失手把自己给宫了,俺可是还要娶妻生子呢......不过高手们可以配合使用,并会达到更好的效果,不在本文所述之列。

  ok,我郑重提醒一下,下面才是正文,上边所述完全可以不看.......
  
  正在写,打字速度不快,请耐心等待.....

出0入0汤圆

发表于 2010-3-21 21:32:09 | 显示全部楼层
sf

出0入0汤圆

发表于 2010-3-21 21:32:31 | 显示全部楼层
占个楼

出0入0汤圆

发表于 2010-3-21 21:33:48 | 显示全部楼层
破解是个成本问题

出0入0汤圆

发表于 2010-3-21 21:38:23 | 显示全部楼层
在听!

出0入0汤圆

发表于 2010-3-21 21:53:37 | 显示全部楼层
下文?

出0入0汤圆

发表于 2010-3-21 21:53:50 | 显示全部楼层
等下文...

出0入0汤圆

发表于 2010-3-21 21:54:20 | 显示全部楼层
这么神……, 占座先

出0入0汤圆

发表于 2010-3-21 21:54:44 | 显示全部楼层
也来听听楼主的高招。

出0入0汤圆

 楼主| 发表于 2010-3-21 21:56:51 | 显示全部楼层
可用下文所讲加密方法的硬件(MCU类型)需求:有唯一识别码的单片机<AVR的OSCCAL或传说中的AVR序列号;有其宣称序列号的STC单片机;其它所有可以唯一或唯二识别此MCU的单片机;无任何可做唯一识别此MCU身份,但外扩了诸如18B20可唯一识别的设备>。

  加密开始.....
  在此选用51内核的STC单片机做范例,因为要把HEX反汇编才能帮大家弄得清楚些。
  说到汇编不得不先自己先BS一下,其实我的AVR汇编水平很差的....只好用51来糊弄大家了....

  范例程序当然越简单越好,如下图,4个按键,4个LED,按下对应键,对应LED就亮,松开就灭....
  串口设备是调试用的....
  

(原文件名:ppppp.JPG)

基本思路及加密流程:
1、取序列号,放在sMcuId[]中;
2、写序列号验证函数,校验读得的序列号是否与程序中于存序列号一致;

  注意了:往往破解者反编后会从这里下手...要么在你读序列号后,直接往sMcuId[]数组中填上已解过MCU的序列号,要么在你校验函数返回处直接返回真值,绕过你程序要求MCU的唯一性,这样就轻松达到破解的目的;

  我们要做的文章也在于此:你不是要改取得序列号的值吗,你不是要改我的校验函数吗?ok!只要这些地方你动一个BYTE,程序就罢工!要有改动,不可能不动一个BYTE吧!

3、校验FLASH从地址0开始N个字节的CRC16校验码(不一定是CRC16,你也可以自定义验证方式),与存于FLASH 中 A处数据进行比对,防止盗版者对程序开始的主函数及中断函数跳转地址做改动(下面范例中此步骤略去)。
4、校验FLASH从MAIN函数开始N个字节的CRC16码,与存于FLASH 中 B处数据进行比对,防止盗版者对主函数开始取序列号等重要函数入口地址做改动。
5、校验FLASH从CheckMcuId()函数(检查MCU id是否与于存ID一致)入口开始N个字节的CRC16码,与存于FLASH 中 C处数据进行比对。
6、再根据你的需要,校验N个主要函数入口开始N个字节的CRC16与存在FLASH的D、E、.....处数据进行比对。
7、把存在A、B、C、D....处的各CRC16码再用CRC16校验一次,与存于Z处的数据进行比对。
8、生成HEX或BIN文件,在A、B、C.....Z处写上这些地方的验证码,供MCU验证使用。
9、范例中最后三步骤也略去,因为方法同4或5是一样的,如果程序中全做上会增加大家理解的难度!
10、最后再帮大家解决量产问题。

加密仍在继续........

出0入0汤圆

发表于 2010-3-21 22:07:39 | 显示全部楼层
下文是...

出0入0汤圆

发表于 2010-3-21 22:15:14 | 显示全部楼层
泡杯茶   等等楼主

出0入0汤圆

发表于 2010-3-21 22:15:22 | 显示全部楼层
这个方法还是要有系列号或类系列号才行呀。

出0入0汤圆

发表于 2010-3-21 22:15:49 | 显示全部楼层
无论你检验多少个ID,多少次CRC
本质问题(FLASH中还是包含完整的功能代码)并没有解决,被人找出来很容易

出0入0汤圆

 楼主| 发表于 2010-3-21 22:18:42 | 显示全部楼层
他不是要破解吗?好,从头至尾重要函数均不可改,1B都不行,而且各入口地址亦不能改。

  你也许会说,只要遇到高手,一步一步分析,肯定还是能解开这些套套的。

  答案是肯定的,但要这个高手所费的时间可不在一个数量级上,给你一斤乱麻,我相信你可能可以把它解开,如果给你一吨乱麻,你看到会不头疼?别忘了,高手也是人。
  如果你的程序只仅仅1K或以下,建议不用加密了,别人照功能写也不费什么劲的。

  当然,至此远远不能算完,还注意一些编程技巧....
1、只要堆栈不溢出,尽可能多的使用内存(即使你非常节约,也没人给你发奖),而且多用全局变量,哪怕是让这些变量自己玩,到真正有用时再销毁它们--要在不影响你执行效果的前提下。
2、多用些表数据,用来掩饰你的CRC校验码存放位置。
3、程序中除了校验时用CRC16,正常程序中一定要有其它函数用到CRC16(如果没用到,建议改为XOR或ADD等你程序中用到的校验,一则节省空间,再让则盗版者不敢轻易改动这些函数),反汇编后你会发现这个有多重要了。
4、我原来很喜欢用if...else..语法,但如果你是想把程序加密性高些,读懂反汇编难些的话,建议改成swich{case}。反汇编后你就知道这是为什么了,其实执行效率也并差不到哪去。

出0入134汤圆

发表于 2010-3-21 22:19:01 | 显示全部楼层
不懂   难道不能把ROM FLASH中的值都读出来么,要你的数据处理程序就行了

出0入0汤圆

发表于 2010-3-21 22:21:53 | 显示全部楼层
学习学习

出0入0汤圆

 楼主| 发表于 2010-3-21 22:23:56 | 显示全部楼层
回复【15楼】elecfun 熊
-----------------------------------------------------------------------
关键你无法区分哪些是处理数据的哪些是处理加密的。

下面整理C程序及相应反汇编程序,可能会慢一些.......

出0入0汤圆

发表于 2010-3-21 22:26:23 | 显示全部楼层
占位.

出0入0汤圆

发表于 2010-3-21 22:33:32 | 显示全部楼层
MCU的加密技术赶不上PC的随便一个壳

出0入0汤圆

发表于 2010-3-21 22:33:47 | 显示全部楼层
等待 (下面整理C程序及相应反汇编程序,可能会慢一些....... )

出0入0汤圆

发表于 2010-3-21 22:35:27 | 显示全部楼层
不懂,纯粹路过

出0入0汤圆

 楼主| 发表于 2010-3-21 22:36:38 | 显示全部楼层
回复【19楼】tyou
-----------------------------------------------------------------------

这个没办法呀,咱们的水平还没到给MCU加壳的程度......

出0入4汤圆

发表于 2010-3-21 22:57:18 | 显示全部楼层
mark

出0入25汤圆

发表于 2010-3-21 23:10:48 | 显示全部楼层
Mark!

出0入0汤圆

发表于 2010-3-21 23:15:54 | 显示全部楼层
占个楼

出0入0汤圆

发表于 2010-3-21 23:18:26 | 显示全部楼层
关注一下

出0入296汤圆

发表于 2010-3-21 23:26:17 | 显示全部楼层
这么说来……我把代码全体状态机化的做法加密特性非常好?

出0入0汤圆

 楼主| 发表于 2010-3-21 23:43:17 | 显示全部楼层
哈哈,看来被忽悠来的人还真不少.....
大部分也许是照着标题所言“索陪”而来的,在此做出解释,除了女生包含全部“陪”的项目外,男生仅限“陪聊”.....

刚写了段简单的C代码(时间短,可能较乱),仿真图如下:

(原文件名:ppppp.JPG)

串口返回数据,前7B为MCU序列号,用于量产软件识别用。
接下来的:0382是主函数入口地址,E0EC是主函数后50B的CRC16码,再接下是序列号校验函数的入口地址,验证码没写,程序中有说明。

反汇编HEX后自己验证了一下理清思路的难度,程序量太小,代码重用率不高,我都能理清,相信大家更容易理清....
所以想靠这个小程序让大家相信此法的可行性也许有些难....
上大点的程序?光反汇编就得老长时间弄,还得挣钱买米,即便我有时间,各位大侠未必有时间陪我玩 (;< .....
不过此法的可行性是经过验证的....

附上C 代码,起个抛砖作用,此法能否被充分发挥作用,看自己的造化了。

出0入0汤圆

 楼主| 发表于 2010-3-21 23:54:05 | 显示全部楼层
//小程序就不另外头文件了,都写一个文件里,凑合着用吧.....

#include <STC11F04E.h>                                         //你包含2051的头文件即可
#include <string.h>
#define byte      unsigned char
#define word      unsigned int
#define dword     unsigned long
#define SetBit(byte,bit) (byte|=(1<<bit))
#define ClrBit(byte,bit) (byte&=~(1<<bit))
sbit        LED1        =        P3^2;
sbit        LED2        =        P3^3;
sbit        LED3        =        P3^4;
sbit        LED4        =        P3^5;

byte sMcuId[7];                                //处理器序列号;
byte code sMcuIdFlash[7] _at_ 0x300;                //FLASH中于存的MCU序列号;
word code wMainFuncAddOnFlash _at_ 0x320;          //(800) 存放在Flash中Main函数的入口地址,便于量产软件识别;
word code wGetIdFuncAddOnFlash _at_ 0x3e8;         //(1000)作用同上;
//.....                                        //可以定义N个要校验的主要函数;

word code wMainCrc16 _at_ 0x380;                   //从MAIN开始50Byte 数据的CRC16验证码存放地。
word code wGetIdCrc16 _at_ 0x400;                //从取ID号入口函数开始以后50 Byte的CRC校验码;
//......                                        //N个主要函数代码的校验码;
byte iCheckStatus;                                //校验结果;
byte iCheckIndex=0;                        //校验次序;
byte iCommandIndex=0;                        //主程序里的命令序列;
word wKeyTimer=0;                                //按键处理记时;
byte iKeyData=0;
union unionIntAddr        //系统联合体,共8byte; 用于串口返回;
{
    struct strSysStru
    {
        word wMainFuncAddr;        //入口地址;
        word wCRC16A;                //从0开始的50B校验码;
        word wGetIdFuncAddr;
        word wCRC16B;                //取MCU ID函数校验码;
    } struSys;
    byte sUionBuff[8];                //用于向串口发数据;
} untest;
//---------CRC16校验计算-----------
word CRC16Check(byte * buf, byte len)
{
    word crc=0x0000;
    word c,i;
    while(len!=0)
    {
        c=*buf;
        for(i=0;i<8;i++)
        {
            if((crc ^ c) & 1)
            crc=(crc>>1)^0xa001;
            else
            crc>>=1;
            c>>=1;
        }
        len--;
        buf++;
    }
    return crc;
}
void        InitIoPort()
{
    P1=0XFF;
}
//串口发送函数,为了使程序易读些,就不用中断发送了;
void        Send1Byte(byte iSendData)
{
    TI=0;
    //ACC=iSendData;
    //TB8=P;//Odd_Checkout(i);        //校验位;
    SBUF = iSendData;
    while(!TI)
    {
        ;
    }
    TI=0;
}
//向串口发送缓冲区iNum个字节内容;
void SendBuffer(byte *sBuffer,byte iNum)
{
    byte i;
    for(i=0;i<iNum;i++)
    {
        Send1Byte(*sBuffer);
        sBuffer++;
    }
    return;
}
//取得序列号或OSCCAL;
void GetMcuIdNo()
{
    byte idata *idata_point;
    idata_point = 0xF1;
    memset(sMcuId,0,7);
    memcpy(sMcuId,idata_point,7);
}
//将MCU ID发给串口;
void SendMcuIdNo()
{
    SendBuffer(sMcuId,7);
    return;
}
void MainCheck()
{
    //校验00开始到50的FLASH是否被改动过
    byte code *sData;
    word wTemp=0;
    sData=0;                    //将sData指针指向FLASH的0位置;
    wTemp=CRC16Check(sData,50);        //算出校验值
    untest.struSys.wCRC16A=wTemp;
    //调试用,将校验码发到串口上;
    SendBuffer(untest.sUionBuff,4);
    if(wTemp!=wMainCrc16)        //比较校验值;数据有误;
    {
        SetBit(iCheckStatus,0);        //防盗版标志;
                                //可以不立即爆发,
        return ;
    }
    ClrBit(iCheckStatus,0);    //防盗版标志;
    return ;
}
//校验比对序列号;
void GetIdCheck()
{
    if(memcmp(sMcuId,sMcuIdFlash,7)>0)
    {
        //序列号不一致;
        ClrBit(iCheckStatus,1);        //防盗版标志;
        return;
    }
    //发送GetIdCheck函数入口地址,及校验码
    //注,此处不对代码进行校验了,与主函数校验方式一样
    //......
    SendBuffer(untest.sUionBuff+4,4);
    SetBit(iCheckStatus,1);
    return;
}
//按键处理程序,可根据自己喜好改用其它方式检测;
//此法优点在于无需等待消抖,不占处理器时间;
byte CheckKey()
{
    byte iKeyTemp;
    P1=0XFF;
    iKeyTemp=P1;
    iKeyTemp=(~iKeyTemp)&0x0f;
    if(iKeyTemp==0)
    {
        wKeyTimer=0;        //清相同按键记时;
        return 0;           //无按键
    }
    if(iKeyTemp==iKeyData)        //有按键,且和上次检测相同;
    {
        wKeyTimer++;
        if(wKeyTimer>800)        //按下此键超过一定时间,视为有效
        {
            wKeyTimer=800;
            return iKeyData;
        }
    }
    else
    {
        iKeyData=iKeyTemp;
        wKeyTimer=0;
    }
    return iKeyData;
}
void DoFunc1()
{
    //点亮第一个灯;当然,你的程序可不只是点灯;
    LED1 = 0;
    return;
}
void DoFunc2()
{
    LED2=0;
    return;
}
void DoFunc3()
{
    LED3=0;
    return;
}
void DoFunc4()
{
    LED4=0;
    return;
}
void DoFunc5()
{    //熄灯;
    P3=0xff;
    return;
}
void main()
{
    GetMcuIdNo();                //取得序列号;
    //取得主函数的入口地址;
    untest.struSys.wMainFuncAddr =(word)&MainCheck;
    //取得取CPU ID号函数的入口地址;
    untest.struSys.wGetIdFuncAddr=(word)&GetIdCheck;
    InitIoPort();
    //初始化寄存器;用到串口,返回各函数地址,便于量产;
    SCON=0xd0;                  //串行口0 工作在方式3 不倍频;
    PCON=PCON|0X80;               
    //CLK_DIV=0;                  
    //AUXR=0X0;               
    IT1=1;                       
    TMOD=0x21;            
    TH1=0xfa;
    TL1=0xFa;
    ES=1;                 
    TR1=1;
    EA=1;                 //开放中断
    //将序列号发到串口;
    SendMcuIdNo();
    while(1)
    {
        iCommandIndex=CheckKey();
        switch(iCommandIndex)        //此处多用SWITCH不用IF语句,因为反编后IF思路非常清晰,对加密并不利。
        {
            case 1:
                DoFunc1();            //以下点灯
            break;
            case 2:
                DoFunc2();
            break;
            case 4:
                DoFunc3();
            break;
            case 8:
                DoFunc4();
            break;
            default:            //只是做个范例,组合键就免了
                DoFunc5();
            break;
        }
        switch(iCheckIndex)
        {
            case 0:            //执行第一次校验,Main主函数校验;
                MainCheck();
                iCheckIndex=1;
            break;
            case 1:
                GetIdCheck();
                iCheckIndex=2;
            break;
            //......还有一些校验,不写了;
        }
    }

}

出0入0汤圆

发表于 2010-3-22 00:20:25 | 显示全部楼层
深深被lz的无畏精神感动。
不过,加密的精髓不在于“不能破解”----这是不存在的;而在于破解所耗费的代价:时间和金钱。
解密者往往不是使用加密者的思路去破解,这意味着加密者无论多么殚精竭力的加密,最终在一个意想不到的薄弱环节被hack,就被破解了(“能装多少水取决于最短的那块板”)。
况且,就针对软件加密而言,倘若lz也经历过在pc上使用保护模式+堆栈传递参数+模块校验等手段被加密过万次壳的程序却被人一个通宵就破掉的经历,恐怕就不会说得那么绝对了。
而对于资深的分析破解人员,由于对体系和指令系统的熟悉,对于mcu这类的很小机器代码规模的反汇编,几k的机器码恐怕半个晚上就看完了,更别论酚蓝染色对flash拍x片还原数据等更加极端的手段...

撤远了,只要程序(机器码)能被静态的完整读出,几k的机器码数量真是太、太小菜了。
举个例子:任何的机器代码使用校验的方法防止被更改,因此确保无法破解,前提是校验的代码本身无法被hack---ok,到第是先有鸡还是先有蛋?oh no,情况比鸡和蛋更坏---不hack校验并不能肯定保障就一定无法被破解,而hack校验几乎意味着肯定被破解了。

这也就是为何这类机器码数量较少的mcu一般使用硬件破坏的如烧掉引脚甚至是破坏ic体的方法加密的原因了,这可以较大的增加破解的硬性成本,至少不会让破解者容易得到机器码;至少使用染色等手段,成本还是相对的高。

出0入0汤圆

发表于 2010-3-22 00:22:15 | 显示全部楼层
cool!

出0入0汤圆

发表于 2010-3-22 00:35:23 | 显示全部楼层
听课的

出0入0汤圆

 楼主| 发表于 2010-3-22 00:40:11 | 显示全部楼层
回复【30楼】vilin_li
-----------------------------------------------------------------------

所言极是!

  我是搞上位机程序出身的,我所做的上位机程序也曾被多次破解过,最可气的是第一次的程序被他们发邮给我告诉我只改了其中一个B的内容,不过后来没这么容易了。
  单片机程序指望厂家的加密位实现加密已是缘木求鱼,想实现更深层次的加密,只能靠自己从程序上增加反汇编及修改的难度,我通篇也是基于这个理念去做的。
  我未说此法是绝对的万无一失,如果你这样认为,我只能说你根本没看帖子内容就回复了。

出0入0汤圆

 楼主| 发表于 2010-3-22 01:04:00 | 显示全部楼层
回复【27楼】Gorgon Meducer 傻孩子
-----------------------------------------------------------------------

  谢谢高手前来捧场,希望不是来索陪的,哈哈....
  我认为全部代码状态机化有以下不妥:
  1、遍地都是小偷,被抓的机率更大。
  2、无论用什么方式校验,都是要占时间滴~!
  3、空间占用量可能会增加,单片机的时间和空间都是银子换来的....
  我们要做的是:
  1、尽量少的代码,尽量多的校验,尽量保证重要代码不可改动性。
  2、校验中尽量多的使用程序中通用函数,增加跟踪的难度。
  3、校验环环相扣,动一发而牵全身,从精神上打击跟踪者。

出30入25汤圆

发表于 2010-3-22 01:10:44 | 显示全部楼层
我想起了马其诺防线

出0入0汤圆

发表于 2010-3-22 01:34:20 | 显示全部楼层
记号。

出0入0汤圆

发表于 2010-3-22 05:24:26 | 显示全部楼层
太折腾了.而且是明显的马其诺防线,绕过就行了.用函数来加密是行不通的.

出0入0汤圆

发表于 2010-3-22 07:07:20 | 显示全部楼层
jh

出0入0汤圆

发表于 2010-3-22 08:16:10 | 显示全部楼层
jh

出0入0汤圆

发表于 2010-3-22 08:30:04 | 显示全部楼层
ding

出0入264汤圆

发表于 2010-3-22 08:42:03 | 显示全部楼层
搬凳子过来听课。

出0入0汤圆

发表于 2010-3-22 08:59:37 | 显示全部楼层
破解的目的不一定是直接克隆。

有些公司的“作品”是关注别人的算法,这里的算法不是指什么高深算法。

比如,南宁某家公司专Hack高档轿车(如阿奔阿宝阿奥等等品牌)中的总里程记录芯片(一些24Cxx、93Cxx之类串行存储器件),也做成了大公司!

出0入0汤圆

 楼主| 发表于 2010-3-22 09:04:18 | 显示全部楼层
回复【37楼】rainyss
-----------------------------------------------------------------------

  很显然,你并没真正理解我的用意,这是一个简单的例子....
  其实,加密是内家功夫,我相信大家也都是有自己一套独特的方式,但很多人都是在观望别人,希望别人能真正共享,而自己却尽量低调,保密....比如烧引脚,你如你只停留在这个层面上,那你的确得向破解者保密你的做法....
  我只是将自己的方式系统化,并且尽量使原理简单化,希望能为大家贡献点什么,虽然你可能会以为加密的重要性在整套系统方案中根本排不上号,但也许有的人不这样认为。
  上面代码只是说明加密要用用最少的代码,充分利用代码及指针,以较高的效率去实现较难些的反跟踪,这一点我想你仔细看过代码后会明白,无论是代码校验还是序列号处理,代码量都不大,而且极宜融入程序,也许这段程序的实际加密效果并不是很卓越,因为我的重点不在这段代码上。
  单片机加密是相对的,没有绝对的不可破解,因为单片机程序就这么大一点....
  但还有一种变通加密方法就是这么绝对,可以保证任何高手均无法解密你单片机程序的真正思路(我可以保证直接给HEX和硬件,无法使它象正版那样完成它应有的功能),你可能想到过它,但你没有重视过上面程序所述之思路作为基础, 你也许只能与它擦肩而过了.....
  上面程序及思路其实只是我日后要提的某种变通加密思路的基础,如果看了上面程序你无任何启示,或者没看贴子内容就觉得楼主提出这么绝对言辞是在发疯,你可以直接顠过了......

出0入0汤圆

发表于 2010-3-22 09:04:41 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-22 09:04:48 | 显示全部楼层
学习中。。。

出50入0汤圆

发表于 2010-3-22 09:05:35 | 显示全部楼层
回复【30楼】vilin_li
深深被lz的无畏精神感动。
不过,加密的精髓不在于“不能破解”----这是不存在的;而在于破解所耗费的代价:时间和金钱。
解密者往往不是使用加密者的思路去破解,这意味着加密者无论多么殚精竭力的加密,最终在一个意想不到的薄弱环节被hack,就被破解了(“能装多少水取决于最短的那块板”)。
况且,就针对软件加密而言,倘若lz也经历过在pc上使用保护模式+堆栈传递参数+模块校验等手段被加密过万次壳的程序却被人一个通宵就破掉的经历,恐怕就不会说得那么绝对了。
而对于资深的分析破解人员,由于对体系和指令系统的熟悉,对于mcu这类的很小机器代码规模的反汇编,几k的机器码恐怕半个晚上就看完了,更别论酚蓝染色对flash拍x片还原数据等更加极端的手段...
撤远了,只要程序(机器码)能被静态的完整读出,几k的机器码数量真是太、太小菜了。
举个例子:任何的机器代码使用校验的方法防止被更改,因此确......
-----------------------------------------------------------------------

LZ说的是在程序中加密 与硬件加密无关 这是一种带序列号形式的加密 相对硬件加密 效果算是好的了

出0入0汤圆

发表于 2010-3-22 09:08:45 | 显示全部楼层
哈哈,顶下楼主的精神!思路很好。

出0入0汤圆

 楼主| 发表于 2010-3-22 09:24:54 | 显示全部楼层
感谢管理支持,终于穿一次裤子....结束原始的祼奔时代.....(~.~)
庆祝一下,推出免费陪吃活动,女生优先,餐费对方付.....

出100入0汤圆

发表于 2010-3-22 10:15:51 | 显示全部楼层
mark?

出0入0汤圆

发表于 2010-3-22 10:41:18 | 显示全部楼层
记号,学习。

出0入0汤圆

发表于 2010-3-22 10:41:26 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-3-22 11:15:53 | 显示全部楼层
来听课

出0入0汤圆

发表于 2010-3-22 11:25:42 | 显示全部楼层
来听课,再付本人愚见:

(1)盗板的只要能拿到CPU那基本上就等于拿到机器码(手段太多-_-!)
(2)机器码根据CPU型号反汇编,个人觉得到这一步CPU已经没有任何加密手段了.

请问各位DX情况是否如此.

出10入0汤圆

发表于 2010-3-22 11:29:13 | 显示全部楼层
楼主我的这个方法看看怎么样

仅适用于有人机界面的:

程序照样给人COPY,发现在盗版的,就让他用一段时间,然后一段时间之后显示:你使用的是侵权产品,举报重奖!电话:XXXXXXX

OK,接下来请阿莫帮你处理了。

如果是仪器,就更好处理了,等一段时间之后,数据给他来个偏差。让他晕也不是,不晕也不是。

出0入0汤圆

发表于 2010-3-22 11:34:53 | 显示全部楼层
Mark ,有空再学习

出0入0汤圆

发表于 2010-3-22 11:38:39 | 显示全部楼层
写的代码还不到需要加密成度,帮顶。

出0入0汤圆

发表于 2010-3-22 11:49:24 | 显示全部楼层
这只是一种理念,如果算法一样,就都死了.
在这基础上,加人个人的算法,这才叫五花八门.
富有中_国_特_色的加密代码.

出0入0汤圆

发表于 2010-3-22 11:52:39 | 显示全部楼层
回复【28楼】flywater 落叶

哈哈,看来被忽悠来的人还真不少.....
大部分也许是照着标题所言“索陪”而来的,在此做出解释,除了女生包含全部“陪”的项目外,男生仅限“陪聊”.....
-----------------------------------------------------------------------

上当了,我可不用你“陪”!(:P


不过我还是喜欢某些前辈比较“阴”的做法:最好能让破解者“不屑”->“疑惑”->“抓狂”->“换名”

出0入0汤圆

发表于 2010-3-22 11:56:15 | 显示全部楼层
兄弟,你去21ic看看HOTPOWER的51加密,加密模块用汇编写的,加入后编译,全部变成了花指令,分不清什么是数据,什么是程序了.用C语言搞出花指令不可能的

出0入0汤圆

发表于 2010-3-22 11:57:10 | 显示全部楼层
楼主,记得有个软件叫IDA.Pro.Advanced
我曾用它反汇编C8051F芯片的HEX代码,然后再加到KEIL C51里编译,出来的HEX代码和原来的一字不差.
这就意味着可以用这些软件手段来调试楼主的代码,对懂汇编的不难吧?

出0入0汤圆

发表于 2010-3-22 12:12:07 | 显示全部楼层
楼上的 ,IDA.Pro.Advanced 也不是万能的,要不我传一个HEX代码,你给我反汇编看看,然后摘掉死循环部分?点击此处下载 ourdev_540185.rar(文件大小:36K) (原文件名:PTMFL.rar)


你会发现代码和数据混在一块了,没有办法分开的,我试过了

出0入0汤圆

发表于 2010-3-22 12:17:53 | 显示全部楼层
这个。。学习了啊。

出0入0汤圆

发表于 2010-3-22 12:20:34 | 显示全部楼层
反汇编不是我的强项,不过用IDA反汇编出来后,加到开发编译环境里仿真调试下,你就知道哪里是代码,哪里是数据了.

出0入0汤圆

发表于 2010-3-22 12:23:19 | 显示全部楼层
有能纯软件骗过枋真的吗,我估计有^_^

出0入0汤圆

发表于 2010-3-22 13:01:54 | 显示全部楼层
MARK

出0入0汤圆

 楼主| 发表于 2010-3-22 13:14:11 | 显示全部楼层
回复【54楼】WOTASOM 突击驾驶员
来听课,再付本人愚见:
(1)盗板的只要能拿到CPU那基本上就等于拿到机器码(手段太多-_-!)
(2)机器码根据CPU型号反汇编,个人觉得到这一步CPU已经没有任何加密手段了.
请问各位DX情况是否如此.

-----------------------------------------------------------------------

  如果我们只停留在让别人反汇编一下就轻松搞定的层面上,那我完全没必要费这么长的篇幅去讨论加密这个问题,也没必要再费这么大劲去考究什么代码校验法了.....
  以上代码例子作用在于增加反汇编跟踪的难度,不是给解密者一斤乱麻让他解,而是要给他一吨.....
  当然,只靠上面给出的代码,顶多算得上一两.....

出0入0汤圆

发表于 2010-3-22 13:19:10 | 显示全部楼层
加密手段再多,在小小的mcu里面,找到那个if, 与pc上M为单位的代码量相比,还是容易很多的。
舞台有限,自然施不开手脚。

出0入0汤圆

 楼主| 发表于 2010-3-22 13:31:43 | 显示全部楼层
回复【60楼】kangar0065 冒牌袋鼠
兄弟,你去21ic看看HOTPOWER的51加密,加密模块用汇编写的,加入后编译,全部变成了花指令,分不清什么是数据,什么是程序了.用C语言搞出花指令不可能的
-----------------------------------------------------------------------

对HOTPOWER的汇编下花指令加密我还是十分敬仰的,过去及至现在也仍在使用--限于51汇编下写的程序。
但我也不是只限于用一下花指令就算完事....
更不能因为现在都是用C了,一句"不能实现花指令"就彻底放弃C语言吧,成功是属于契而不舍者....
我前面提到过,还有一种变通的加密方式,从单片机HEX上反编是绝对不能解开的,只不过今天没公布罢了.....

顺便提一下,很多高人用AVR传统的OSCCAL加密方式做的产品,解密只需一行代码....
另外还有一种另人发指的解AVR OSCCAL加密的方法,在此本人不再公布,不然令人发指的不是这种方法,而会是我本人了.....

出0入0汤圆

发表于 2010-3-22 13:34:56 | 显示全部楼层
回复【13楼】h2feo4 无机酸
无论你检验多少个ID,多少次CRC
本质问题(FLASH中还是包含完整的功能代码)并没有解决,被人找出来很容易
-----------------------------------------------------------------------

正解。



等待LZ继续。

出0入0汤圆

发表于 2010-3-22 13:42:09 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-22 14:02:48 | 显示全部楼层
51系列的单片机有不同指令长度的指令,可以造成花指令,但是诸如pic等定长的指令,就没有什么办法了。

关键问题是向其他人说的那样,代码被得到了,仿真执行,只是时间的问题了,加密和解密永远是相对的。

只要是效果达到即可,比如延长分析时间等,但是加密搞的过分复杂,代码维护也是很麻烦的,而且会在某种程度上影响系统稳定。

出0入0汤圆

发表于 2010-3-22 14:20:56 | 显示全部楼层
关注

出0入0汤圆

发表于 2010-3-22 14:21:06 | 显示全部楼层
OSCCAL加密,也可以复杂点的,将OSCCAL经过简单变换运算得到KEY,再把 大部分函数都做成函数指针形式调用,函数跳转表用KEY来加密,
第一次启动后,bootloader完成flash中函数表或其它参数的KEY加密过程,再销毁加密程序。
采用不完全可逆的密文算法,使得KEY与密文运算后得到的是正确的函数指针或参数数据,
这样就大大增加了破解难度,因为就不能简单的修改下读取或判断OSCCAL的指令了。
当然一步步仿真,慢慢研究,最终还是可以破解的。。。不过这个花费应该就大了

出0入0汤圆

发表于 2010-3-22 14:34:41 | 显示全部楼层
mark一下 不知道还有更新么

出0入0汤圆

 楼主| 发表于 2010-3-22 14:40:32 | 显示全部楼层
回复【74楼】snoopyzz
-----------------------------------------------------------------------

  思路很有创意,这个过程是在bootloader中完成的,一旦生成跳转表后这些就是死的了,怎么再去通过新芯片的OSCCAL去校验非法性呢?
  如果程序运行中再用OSCCAL重新变换的话,你就得再去读OSCCAL,只需在读前改一下其值,仍能轻易解密...
  或许我没理解你的意思....

出0入0汤圆

 楼主| 发表于 2010-3-22 14:42:03 | 显示全部楼层
回复【75楼】ksniper
-----------------------------------------------------------------------

如果读完全文的话,你会发现这才只是开头,怎么会没更新呢?

出0入0汤圆

发表于 2010-3-22 14:46:14 | 显示全部楼层
继续等楼主更新   先把网页保存到本地先

出0入0汤圆

发表于 2010-3-22 14:48:25 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-22 14:48:41 | 显示全部楼层
我觉得关键的位置是在 if 处,暨判断出否正版的条件语句,一般只要找到这,就搞定了,不需要去考虑用什么方法加密

出0入0汤圆

发表于 2010-3-22 15:33:34 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-22 15:57:01 | 显示全部楼层
mark 有用

出0入0汤圆

发表于 2010-3-22 16:10:13 | 显示全部楼层
回复【80楼】jackielau  
我觉得关键的位置是在 if 处,暨判断出否正版的条件语句,一般只要找到这,就搞定了,不需要去考虑用什么方法加密
-----------------------------------------------------------------------

可能你还没有了解LZ的思路,LZ是说对Flash的每一个Byte都做完整性测试,如果你改了任何一个byte那么就破坏了code的完整性,当然也就无法正常运行。

如果我理解的不对,请LZ更正。

出0入0汤圆

发表于 2010-3-22 16:22:20 | 显示全部楼层
mark

出0入0汤圆

 楼主| 发表于 2010-3-22 18:15:58 | 显示全部楼层
回复【83楼】zhang_mike2000
-----------------------------------------------------------------------

理论上是这样的,但并不是全部FLASH都不让动,只是你认为重要的地方不能动而已,
把CODE程序做存储数据去用,是真正的代码即是数据,数据即是代码的做法,如果代码和数据无法分不清的话,无形中就增加了跟踪难度,再则校验不要一下全校验了,个别是随机去校验的,正常使用时个别校验可能N天不来一次,不要每次上电就做全部。

出0入0汤圆

 楼主| 发表于 2010-3-22 18:19:37 | 显示全部楼层
回复【80楼】jackielau
-----------------------------------------------------------------------

至于加密只用一个if语句的,从现阶段解密人员层次上来讲那根本不叫加密.....真的要退出历史了.....

出0入0汤圆

发表于 2010-3-22 18:21:10 | 显示全部楼层
自宫吧

出0入0汤圆

 楼主| 发表于 2010-3-22 18:40:26 | 显示全部楼层
回复【87楼】kevintang
-----------------------------------------------------------------------

自宫是最高境界....

不过我倒不太喜欢拿把刀在自己身上剜来剜去得,除了在线升级和做EEP使用外,课余时间很少动FLASH。
希望高手们把自己比较温柔的自宫法也贴上来,毕竟,任何事的成功,均不可能是一人之力,我在自宫方面真没什么特长 ;-(。
加密技术,只能是做到让盗版者知道你是怎么加的,仍无法解密的程度,才有可能真正普及,真正起到保护知识产权的作用....

出0入0汤圆

发表于 2010-3-22 18:41:05 | 显示全部楼层
非常好,以后来看卡!

出0入0汤圆

发表于 2010-3-22 19:01:09 | 显示全部楼层
回复【88楼】flywater 落叶
-----------------------------------------------------------------------

某些IO会有上拉或下拉电阻,开机检测电阻的存在,为防止错误检测以及电阻假焊等故障,如电路中存在10个上拉或下拉电阻,检测到存在5个以上的电阻即认为芯片在PCB上,否则认为芯片已经离开了PCB,即刻执行自宫程序。高手请继续!

出0入0汤圆

发表于 2010-3-22 19:08:28 | 显示全部楼层
这样搞法,代码不好维护,移植性差。只有给出功能要求和报酬,copy出来相信不难。做兼职的高手多的是。

出0入0汤圆

发表于 2010-3-22 19:13:13 | 显示全部楼层
回复【91楼】Edesigner
-----------------------------------------------------------------------

另外开发不在讨论之列

出0入0汤圆

发表于 2010-3-22 19:20:48 | 显示全部楼层
【86楼】 flywater 落叶
至于加密只用一个if语句的,从现阶段解密人员层次上来讲那根本不叫加密.....真的要退出历史了.....
-------------------------------------------------------------------------------------
楼主是用什么方式呢??请教了!

出0入0汤圆

发表于 2010-3-22 19:24:13 | 显示全部楼层
到处都是炸_弹,防不胜防,拆弹的再能,也能被炸到...

出0入0汤圆

发表于 2010-3-22 19:48:32 | 显示全部楼层
其实加密方法应该综合多种,整体加密强度才高。首先要阻止别人拿到原hex,或者原电路图,从源头上增加难度。可做hex自毁,pcb陷阱等。
别人好不容易拿到hex了,根据一般解密流程,放到原电路板上,看可以正常运行不?如果可以运行,那就付破解费,如果不能运行,就加钱找别人反汇编。针对这点,可以先让程序正常运行一段时间,等破解者收钱了,程序再开始罢工。至于罢工方式看你喜欢了,模拟成干扰,导致MCU复位也行,模拟MCU定时器出错也行。那别人就不会一下子认为是HEX里面动了手脚,还以为是买了的元件质量不过关呢。

至于加密方法,肯定要复杂一些。
太简单了,例如
if(校准值 == 正常)
{
正常运行
}
else
{
失效
}

现在看来,这种已经不堪一击。要知道,不同难度的反汇编修改,破解者是收不同的钱的!!让解密成本高是我们的目的。
最后做得复杂一点。起码不能一眼看出一个所以然。当然,加密的复杂程序是和原程序的价值相关的,各位看着办吧。

至于判别正版盗版的方法,AVR不一定是校准值,还有唯一的序列号(某些型号)
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3772177&bbs_page_no=1&search_mode=1&search_text=%D0%F2%C1%D0%BA%C5&bbs_id=1000

根据我的测试PA后缀的,有序列号。M48PA M88PA M168PA等,旧版本的10AU 20AU是没有的。
除了数字方式,还有模拟方式,电阻值,电容值等。反正要多多思考,多留意破解资讯,留意破解新手段,多跟破解者聊天,装作客户,套他们资料,要让他们日子不好过。

出0入0汤圆

 楼主| 发表于 2010-3-22 19:49:45 | 显示全部楼层
回复【93楼】jackielau
-----------------------------------------------------------------------

呵呵,都是喜欢直接进来问,我真的不能把前面的贴子再重复一遍了.....

出0入0汤圆

发表于 2010-3-22 19:59:15 | 显示全部楼层
回复【62楼】kangar0065  冒牌袋鼠
-----------------------------------------------------------------------

对于没有动态修改指令的代码,可以类比于烧在Flash中,运行中固定不变,不会被动态修改的代码。如果完整得到正确的代码本身,比如原始HEX文件,这种东西是没有办法逃过IDA Pro这种静态代码分析软件或者软件仿真环境的。

花代码,只是造成“按照内存地址顺序”顺序反汇编的反向工程工具 直接 反向输出的结果错误。如果你使用IDA Pro这样的工具进行逐条指令跟踪操作,花代码不会造成任何困扰。对于软件仿真环境来说,一样,物理CPU怎么执行操作,就怎么执行,没有影响。

即,花代码使得反向工程时,干扰了反向工程工具的函数调用关系分析。迫使反向工程人员从函数级的分析,局部的陷入指令级分析,大大增加了反向分析的成本。当然,对于有经验的反向工程人员,使用较为高级的静态分析工具,较小规模的花代码基本上无法起到太大的作用。

只要拿到的是真实的HEX数据,在软件仿真环境面前,都是不堪一击的。约完善的软件环境越是如此。

修改添加:
之所以你说IDA无法分析,个人猜测是没有正确使用IDA这个工具。很大可能是加载代码后直接看反汇编结果,而不是利用软件“分析”,这是静态分析的分析所在。
相对正确的方法是,加载之后,根据芯片调整段结构;把所有的ROM打回数据,从程序入口开始变Code,逐层推进。依赖于向量表等入口,逐个获得函数。从而得到正确的结果。
如果用熟练,我初步感觉工作量增加不是太明显,主要是人工界定各种调用点的合法性,判定异常跳转点。这也是花指令的意义所在。
当然,如果说花指令本身(原始代码)就合并了数据和指令,经过人力特别优化,编写的代码;那对应的就会在静态分析中,要求人力分析出来这究竟是怎么回事儿。肯定有复杂度增加,但是也不至于很隐晦。

出0入0汤圆

发表于 2010-3-22 19:59:43 | 显示全部楼层
楼主请继续,等待更精彩内容

出0入0汤圆

 楼主| 发表于 2010-3-22 20:05:33 | 显示全部楼层
回复【90楼】kevintang
-----------------------------------------------------------------------

说实在话,加密的方式真的很多很多,下架就自宫的确是一种很好的方式,它的难点在于不能宫了自己,万分之一的可能都不行...
但你说的这种方法不行,他完全按你的电路去做,你的这种方法是行不通的,你的程序这时不分敌我。
你的这种利用原电路上的上拉或下拉电阻自宫的方式只适合于硬件破解难度大,必须开盖的MCU,AVR是别想了,不用从板上取下,更根本不用开盖就拿HEX了。
自己把AVR在板子上用不到的引脚用细线连起来,程序上电检查决定是否自宫倒是可以的---他们抄板,也许你可以期望他们看不到你有几个脚中间用焊点连起来了,而是以为你的焊接失误,而只抄了你的PCB,自己焊上MCU后并不知道把某几个脚也连起来,进而一上电就自宫....

出0入0汤圆

发表于 2010-3-22 20:14:26 | 显示全部楼层
个人感觉加密的至高境界是让解密者可用,然后等解密者量产好,如果有数据需要发送的,可以发送些随机数据,也不要if else,让数据不正确,一般解密者是不会注意的,可想而知,解密的东西全部是废品是什么感觉。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 08:47

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表