2.5 软件自毁技术基础与实现
自毁软件技术是一种不同于通常说的加密的新思想,因为加密的最终目的是防止非法复制和合法使用。而采用自毁软件技术则可以使软件能自然流传但又能控制在一定范围之内,并且在使用一定次数或时间之后能自行进行销毁。还有就是当用户试图修改本软件时,也将可能导致本软件实现自毁。
2.5.1 自毁软件的原理
要实现本软件自毁技术,鉴于单纯设置一个计数器易被查出,可通过修改使其不起作用,这里通过两套计数基数,A,b为第一组,B,c为第二组……做一个数据文件,把第一组的计数基数放在数据文件中,放的位置由设定的两个关键字(数值)决定。
软件执行前先通过关键字找到计数基数,然后作计算与判别,如果在合理范围之外,就启动软件自毁功能;如果在合理范围之内,则改变数据文件并设定新的关键字,从而将第二组的计数基数放在由新关键字指定的位置。如此计数,直到达到使用的次数为止。而在数据文件中存放关键字的位置则是不变的,如定为第4,5位与第27,28位。
下面不妨先来看第一个数据文件。
从中可知其关键字分别为07和04,并且由于从第一个关键字的第一位数起的第7位是第一计数基数A,从第二个关键字的第一位数起的第4位是第二计数基数b,因此,就可以通过这两个计数基数的ASCII码来对其进行运算和判断。
如果设变换后的关键字分别为15和11(其中X代表随机产生的任意ASCII字符),则可以得到新的数据文件如下。
由此可知,如果不是软件设计者,要找出这样的规律几乎是不可能的。当然,在本例中还可以采取关键字通过运算来确定计数的位置,这样操作的好处是即使破解者找到了关键字,也同样无法找到其计数基数。
2.5.2 自毁软件的实现
下面来看一个限制使用次数n=4,也就是说当第5次使用该软件时即进行自毁的程序(其中n次的数据文件均不相同)。本例为便于讲解,考虑的只是一个关键字的例子,读者可据此类似地设计出多个关键字的程序,这样将大大提高数据文件中计数基数的隐蔽性。
由程序所给出的数据文件及其运行结果如下。
D>type data.dat alksd30jasldkjfhsaKD60hsajkfh,50nbv,938kjlsfh,9843Ark, cn9qow72r 74398ruebfdh91, 8reiuy hc84y7rh8hjf D> D>p3-3 The program is running correct! ! ! D>type data.dat WpJXV68azmY85xR6KNol52tccs4N8xhFmq281aoiIjcV47G8gWBB42sGDBXT26D yM8A757Z7L3433zEZ UBlAPqrG4MVY3csios2II D>p3-3 The program is running correct! ! ! D>type data.dat igV5N52QjzUdV5Nsp6d42974qv5GL117C1nvFlpW3R5207332j4C3280F254u7K 1GxER6j0g303oh2V2 1rFHDCXd28k6X7xJjlEm D>p3-3 The progam is running correct! ! ! D>type data.dat T6TKF74fApUgVigfKjKS642Z3Fy6jd4q751D63EGwQDja7ZpJeMcZgIg1143HYy 049DjtbQNTy427872 pp00175sxE07Bt2rGBv5 D>p3-3 The program is runing correct! ! ! D>type data.dat pkEvh29ZCro6AS6j8gsN92B17rN3102YxHPtbp3BRPll3INOPM7Pp87SBGPNe4X 118P1mpIf87Fy4G04 2h2f16fWYiJF86404bx5 D>P3-3 Error! ! ! D>
上述程序的C语言源代码清单如下。
#include<Stdio.h> #include<time.h> #include<Stdlib.h> #include<io.h> void kill(void); main() { FILE *fp1; char ch, iasc1, iasc2; int x, x1, x2, x3, x4, i, c; randomize(); if((fp1=fopen("data.dat", "r+b"))==NULL) { printf("\p caonot open data.data file\n"); exit(1); } fseek(fp1,20,0); ch=getc(fp1); x=((int)(ch))&0x0ff; x=x-0x30; x2=x*10; ch=getc(fp1); x=((int)(ch))&0x0ff; x=x-0x30; x2=x2+x; fseek(fp1,5,0); ch=getc(fp1); x=((int)(ch))&0x0ff; x=x-0x30; x1=x*10; ch=getc(fp1); x=((int)(ch))&0x0ff; x=x-0x30; x1=x1+x; fseek(fp1, x1,0); ch=getc(fp1); x=((int)(ch))&0x0ff; x=x-0x30; x3=x*101; ch=getc(fp1); x=((int)(ch))&0x0ff; x=x-0x30; x3=x3+x; fseek(fp1, x2,0); ch=getc(fp1); x=((int)(ch))&0x0ff; x=x-0x30; x4=x*10; ch=getc(fp1); x=((int)(ch))&0x0ff; x=x-0x30; x4=x4+x; fseek(fp1, x3,0); iasc1=getc(fp1); fseek(fp1, x4,0); iasc2=getc(fp1); n=((int)((iasc3-iasc1))&0x0ff)-32; if(n1! =1) kill(); if(iasc1<65||iasc1>68 kill(); if(iasc2<98||iasc2>101 kill(); iasc1=iasc1+1; iasc2=iasc2+1; fseek(fp1,0,0); for(i=0; i<100; i++= { c=random(3); if(c==0) {ch=(char)random(9); ch=ch+0x30; }; if(c==1) {ch=(char)random(26); ch=ch+0x41; }; if(c==2) {ch=(char)random(26); ch=ch+0x61; }; putc(ch, fp1); } x4==rando[n(98)]; while(x4==4||x4==5||x4==6||x4==19||x4==20||x4==21) x4=random(98); x3=rand02n(98); while(x4==x3||x4==x3+1||x3==x4+1||x3==4||x3==20||x3==6| |x3==19||x3==21||x3==5) x3=random(98); fseek(fp1, x4,0); putc(iasc2, fp1); fseek(fp1, x3,0); putc(iasc1, fpl); x2=random(98); while(x2==5||x2==20||x2==x3||x2==x3+1||x3==x2+1||x2==x4| |x2==x4+1||x4==x2+1 ||x2==6||x2==19||x2==21||x2==4) x2=random(98); x1=random(98); while(X1==4||x1==20||x1==x3||x1==x3+1||x3==x1+1||x1==x4| |x1==x4+1||x4==x1+1 ||x1==x2||x1==x2+1||x2==x1+1||x1==6||x1==19| |x1==21||x1==5) x1==random(98); ch==(char)((x4/10)+0x30); fseek(fp1, x2,0); putc(ch, fp1); ch=(char)((x4%10)+0x30); putc(ch, fp1); ch=(char)((x3/10)+0x30); fseek(fp1, x1,0); putc(ch, fp1); ch=(char)((x3%10)+0x30); putc(ch, fp1); ch=(char)((x2/10)+0x30); fseek(fp1,20,0); putc(ch, fp1); ch=(char)((x2%10)+0x30); putc(ch, fp1); ch=(char)((x1/10)+0x30); fseek(fp1,5,0); putc(ch, fp1); ch=(char)((x1%10)+0x30); putc(ch, fp1); fclose(fp1); /* end of test */ printf("The program is runing correct! ! ! "); } void kill(void) { int i, len, fd, offset; char ch; FILE *fp2; printf("\n\nerror! ! ! "); fp2=fopen("hz.exe", "wb"); fd=fi leno(fp2); len=fi lelen8th(fd); for(i=0; i<=100; i++) { offset=random(len+1); ch=random(255); fseek(fp2, offset,0); putc(ch, fp2); } fclose(fp2); exit(1); } /* end */