软件自毁初探

  今天在看《加密解密全攻略》的时候,看到了软件自毁技术的介绍,感觉挺有意思的。其基本原理是:

  鉴于单纯设置一个计数器易被查出,通过修改使其不起作用。即通过数据文件,软件执行前通过关键字找到计数基数,然后计算和判别,如果在合理范围,则设定新的关键字,将计数基数放在新关键字指定的位置;不合理, 则启动自毁程序。

例:

位置:0 1 2 3 4 5 6 7 8 9 0

数据:X U T N 0 7 a h d g  A

上例中关键字位置为4、5,找到0、7,根据0、7从0开始的第七个数就是基数。

该书上提供了一段实现代码,我实现了一下,发现代码中有很多的错误,我将程序做了一些更改和修正,终于得到正确结果。

例子是限制使用次数为n=4,即第五次的时候自毁。初始数据文件为data.dat,原始数据为alksd30jasldkjfhsaKD60hsajkfh,50nbv,938kjlsfh,9843Ark,cn9qow72r74398r uebfdh 91, 8reiuy hc84y7rh8hjf

代码
#include<stdio.h>
#include
<time.h>
#include
<stdlib.h>
#include
<io.h>

void kill(void); //自毁函数

main()
{
FILE
*fp1;
char ch,iasc1,iasc2;//iasc1、iasc2要比较的基数
int x,x1,x2,x3,x4,i,c,n;
srand((unsigned)time(NULL));
//初始化随机数

if((fp1=fopen("data.dat","r+b"))==NULL)
{
printf(
"\n cannot open data.dat file\n");
exit(
1);
}

/*取出数据文件中第一个关键字,即基数的位置的位置,第一个关键字放在数据文件的20、21位上*/
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;

/*取出数据文件中的第二个关键字,第二个关键字放在数据文件的5、6位上*/
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*10;
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);

/*根据第一、第二个基数的ascii码大小进行比较,其差必须为1。由于设定了使用次数为4次,基数从
A开始,因此第一个基数的ascii码必须在65-68中,第二必须在98-101中
*/
n
=((int)(iasc2-iasc1)&0x0ff)-32;
if (n!=1) kill();
if(iasc1<65||iasc1>68) kill();
if(iasc2<98||iasc2>101) kill();

/*判定正确,则判定部分结束,设置下一次的数据文件,基数为原始基数的技术上加1*/
iasc1
=iasc1+1;
iasc2
=iasc2+1;

fseek(fp1,
0,0);
for (i=0;i<100;i++)//书籍产生原始数据文件
{
c
=rand()%3;
if (c==0){ch=(char)rand()%9;ch=ch+0x30;};
if (c==1){ch=(char)rand()%26;ch=ch+0x41;};
if (c==2){ch=(char)rand()%26;ch=ch+0x61;};
putc(ch,fp1);
}
x4
=rand()%98;//随机一个基数的存放位置,注意有限定条件,4、5、6、19、20、21位置上空出
while(x4==4||x4==5||x4==6||x4==19||x4==20||x4==21)
x4
=rand()%98;

x3
=rand()%98;
while(x4==x3||x4==x3+1||x3==x4+1||x3==4||x3==5||x3==6
||x3==19||x3==20||x3==21)
x3
=rand()%98;
fseek(fp1,x4,
0);
putc(iasc2,fp1);
fseek(fp1,x3,
0);
putc(iasc1,fp1);

x2
=rand()%98;
while(x2==4||x2==5||x2==6||x2==19||x2==20||x2==21||
x2
==x3||x2==x3+1||x3==x2+1||x2==x4||x2==x4+1||x4==x2+1)
x2
=rand()%98;

x1
=rand()%98;
while(x1==4||x1==5||x1==6||x1==19||x1==20||x1==21||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
=rand()%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);
/*将基数的位置的存储位置放入5、6、20、21的位置*/
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 running correct!!!");
}
void kill(void)
{
int i,len,fd,offset;
char ch;
FILE
*fp2;
printf(
"\n\nerror!!!");
fp2
=fopen("sefd.exe","wb");//自毁程序,sefd.exe为我编译产生的可执行文件
fd=fileno(fp2);
len
=filelength(fd);
for(i=0;i<100;i++)
{
offset
=rand()%(len+1);
ch
=rand()%255;
fseek(fp2,offset,
0);
putc(ch,fp2);
}
fclose(fp2);
exit(
1);
}
/*end*/

 

 

 

posted on 2010-09-27 16:37  Rochen  阅读(2612)  评论(0编辑  收藏  举报

导航