共享软件的注册加密法
副标题#e#
Internet网络的迅速成长,为软件高效流传开发越发辽阔的天地。如海内著名的金蜘蛛软件下载中心,就是一个典范的宣布软件集散地。宣布共享软件主要包罗两种形式:日期限制形式和电子注册形式。日期限制形式答允下载软件的用户利用软件一段时间,如一个月等,假如用户承认该软件,可购置该软件的注册序列号继承利用;电子注册形式就是按照用户所用呆板的硬件信息发生注册码,并在软件中对某些先进或常用成果举办限制,假如用户要利用其全部成果,必需将软件收罗的有关硬件信息反馈给开拓者,并交必然的注册费可得到该软件在本身呆板中的注册码,才气正常利用。
前一种形式很容易给盗版者造成可乘之机,假如建造盗版者购置了一个注册序列号并发布于天下,则所有用户利用这个注册号都可举办正常利用;后者对用户来说注册手段稍显巨大些,对开拓者来说也需要必然的编程真工夫,但其具有“八点锁紧”成果,防盗性却是不容置疑。本文按照本身的实践,将后者的实现进程先容给想要建造宣布共享软件的读者。
一、注册源
在WIN98/95的掩护模式下,要按照硬件信息形成注册码可不是一件容易的事,在实模式下可通过硬盘端口1F6H和1F7H直接读取硬盘的序列号等信息作为注册的数据源,但这一要领在掩护模式下却被亮出了红牌。操作BIOS中的主板序列号、BIOS版本序列号或主机出厂日期和符号等,完全可以作为注册码的注册源。如ROMBIOS中F000H-FFFFH区域中就存在与硬件设置有关的信息,还可以收罗其它一处或几处主板等的信息作为注册码的出产基地。譬喻可按照F000H:FFF5H-F000H:FFFFH 中存放的主机出厂日期和主机符号值,发生应用措施的注册码。由于计较机产物的更新换代较量快,并且所有用户利用的计较机不行能设置都完全沟通,所以注册码发生的源也不会完全沟通。并且这些硬件信息内容在任何操纵系统下均完全沟通,兼容性很是好,更不会因为操纵系统的更新而造成注册成果失效。
注册源确定之后,要害的问题就是共享软件安装措施如何收罗注册源信息,并让用户将其返回给开拓者。最简朴的要领就是将收罗到的注册源信息颠末位操纵加密后存放到一个文本中,形成注册码的数据源资料。这个注册源数据串可稍长一些,但不宜过长,利用户可以或许通过电子邮箱、电话或信件顺利转给开拓者为宜。如笔者安装措施是用C语言体例的,假如将上述内存地点作为注册源,数据串文本文件名为KEYID.DOC,长度为20个字符。其示例代码如下:
FILE *fp2;
unsigned int keyrom[9];
unsigned char buff[0x410];
unsigned char pathstmp[80];
unsigned char path[80]={"C:\\WBCOOL"};
unsigned int far *pt=(unsigned int far*)0xf000fff6L;
......
outportb(0x21,0x2);
strcpy(pathstmp,path);
strcat(pathstmp,"\\");
strcat(pathstmp,"KEYID.DOC");
for(i=0;i<5;i++)
keyrom[i]=(*(pt+i)+0x1818)^0x5858;//第一级加密算法
sprintf(buff,"KEYID:%04x%04x%04x%04x%04x",
keyrom[0],keyrom[1],keyrom[2],keyrom[3],keyrom[4]);
buff[0x1a]=0;
if((fp2=fopen(pathstmp,"wb"))==NULL)
{
printf("FILE %s CREATE ERROR!",pathtmp);
} else {
fseek(fp2,0L,SEEK_SET);
fprintf(fp2,"%s\xd\xa",buff);
fclose(fp2);
}
outportb(0x21,0x0);
#p#副标题#e#
二、注册机
开拓者获得用户提供的注册源数据之后,就需要操作注册机生成注册码并返回给用户。注册机操作既定的位操纵和不行逆算法,形成用户较量容易操纵的字符串注册码,注册码的长度一般为8-16位为宜,用户只需注册一次就可以恒久利用,所以注册码的长度不会影响用户的注册操纵。虽然注册机的算法应与共享软件中的算法部门基内情同。对付长途用户,注册机应该具有从键盘和内存两种取得注册源数据的成果,所以注册机的加密算法实际为两个分支:第一个分支是从键盘获取注册源数据后直接按照注册算法形成注册码的进程,是直接给长途用户反馈注册码的进程;第二个分支是直接从ROM BIOS中按照注册源算法取得注册源数据,再按照注册算法形成注册码的进程,是直接读取当地机注册码的。
用户获得注册码后,按照共享宣布软件的注册要领举办一次注册,应用措施会自动将这个注册码存放到软件的特定位置处,当应用措施被他人拷贝到其它呆板中去后,由于注册码因差异呆板而异,所以应用措施的成果或利用次数仍然受限,要在其它呆板中利用该应用措施,还必需举办从头注册,到达共享软件宣布目标。同时由于注册源数据的算法和注册码算法均可因人而异,因此这种要领很是靠得住。本人实现的注册机带参数时接管键盘输入注册源;不带任何参数时从当地呆板内直吸收罗注册源数据。我的注册机示例措施如下:
#p#分页标题#e#
#include <conio.h>
#include <dos.h>
#include <io.h>
#include <dir.h>
#include <alloc.h>
#include <string.h>
#include <stdio.h>
#include <process.h>
#include <fcntl.h>
#include <ctype.h>
#include <stdlib.h>
unsigned char Buff[18];
unsigned char Buff1[18];
unsigned int keyrom[9];
unsigned int sum,sum1,sumi,sumj;
unsigned int far *pt=(unsigned int far *)0xf000fff6L;
unsigned int i=0,j=0,m,imecom;
unsigned char p;
unsigned int nn,nn1,nn2;
unsigned char rbuff[100],cc,cc1,cc2;
int fp;
void main(int argc,char *argv[])
{
if(argc>=2){
printf("KEYID:");
scanf("%s",rbuff);//接管键盘输入长途注册源
j=strlen(rbuff);
if(j!=20) exit(1);
for(i=0;i<20;i++){//读入20位注册源数据
if((rbuff[i]>='a')&&(rbuff[i]<='f')) rbuff[i]&=0xdf;
if((rbuff[i]>='A')&&(rbuff[i]<='F')) rbuff[i]-=0x37;
else if((rbuff[i]>='0')&&(rbuff[i]<='9')) rbuff[i]-=0x30;
else exit(1);
}
for(i=0;i<5;i++){//形成字符串
cc1=rbuff[i*4]&0xf;
cc2=rbuff[i*4+1]&0xf;
cc=(cc1<<4)|cc2;
nn1=(unsigned int)cc;
cc1=rbuff[i*4+2]&0xf;
cc2=rbuff[i*4+3]&0xf;
cc=(cc1<<4)|cc2;
nn2=(unsigned int)cc;
nn=(nn1<<8)|nn2;
keyrom[i]=nn;
}
sum=0x1234;
sum1=0x7456;
for(sumj=0;sumj<4;sumj++){//形成16位注册码
for(sumi=0;sumi<5;sumi++){
sum+=keyrom[sumi]; //形成前4位码
sum1+=keyrom[sumi];
}
sum^=0x1234<<sumj; //举办移位异或处理惩罚
sum1^=0x7456<<sumj;
sprintf(Buff+4*sumj,"%04x",sum);
sprintf(Buff1+4*sumj,"%04x",sum1);
} //形成16位注册码
printf("\nWIN-KEY:");
printf(Buff);
printf("\nDOS-KEY:");
printf(Buff1);
exit(1);
} else {
sum=0x1234;
sum1=0x7456;
for(sumj=0;sumj<4;sumj++){//形成16位注册码
for(sumi=0;sumi<5;sumi++){
sum+=(*(pt+sumi)+0x1818)^0x5858;
sum1+=(*(pt+sumi)+0x1818)^0x5858;
}
sum^=0x1234<<sumj;
sum1^=0x7456<<sumj;//举办移位异或处理惩罚
sprintf(Buff+4*sumj,"%04x",sum);
sprintf(Buff1+4*sumj,"%04x",sum1);
}
printf("\nWIN-KEY:");
printf(Buff);
printf("\nDOS-KEY:");
printf(Buff1);
}
}
三、注册码
当用户注册乐成后,注册码就被写到共享软件的相应位置。这时共享软件必需对用户注册码举办及时检测与判定,才气实现注册限制成果。这时要求共享软件必需内部取得注册源数据,并操作注册机中沟通的算法发生内部注册码。这就要求共享软件直接读取ROM BIOS的注册源信息,并在共享软件中需要限制的成果处增加注册码检测判定成果,这需要按照共享软件的实际需要、软件巨细和实现的难易水平来确定限制的数量,使盗版者很难举办解密。这样既使计较机中多个共享软件利用沟通的注册源,也不会产生注册斗嘴问题;既使是利用了沟通的注册源数据,由于注册算法的差异注册码也不会沟通;纵然解密者知道注册算法的注册源地点,由于无法知道注册算法并且注册点遍布整个共享软件,也很难举办盗版。因此,这一注册要领使共享软件有效地超过各类系统平台。
要在共享软件内部发生注册码,必需在共享软件中读取ROM BIOS数据源内存数据。WINDOWS掩护模式下必需操作段选择符要领和API编程接口提供的函数才气实现:
1.AllocSelector(Selector)分派一个与参数沟通的空选择器
2.FreeSelector(Selector) 释放分派的选择器
3.SetSelectorBase() 配置选择器描写符物理起始地点
4.GetSelectorBase() 获取选择器描写符物理起始地点
5.SetSelectorLimit() 配置选择器描写符会见边界
6.GetSelectorLimit() 获取选择器描写符会见边界
#p#分页标题#e#
个中函数AllocSelector(Selector) 是掩护模式下物理内存会见的要害,Selector是分派空选择器的段寄存器模板,可以操作GlobalAlloc()函数分派内存,再操作GlobalHandleToSel()函数将内存句柄转换为相应选择器,内存单位会见竣事后再操作GlobalFree()释放分派的内存。最简朴的要领就是将系统的数据段寄存器__DS直接作为模板参数,这个参数在一般应用措施中完全可以正常利用。然后操作SetSelectorBase()和SetSelectorLimit( )函数别离配置内存的物理起始地点和会见边界值,操作正常的指针操纵*pt=Value和Value=*pt会见物理内存单位,会见竣事后必需利用FreeSelector()函数释放分派的选择器,因为WINDOWS 并不自动释放无用的选择器,并且系统的选择器共享资源长短常有限,只有8192个供利用。按照以上道理及注册机中的注册源和注册码算法,就不难实现共享软件内部注册码函数:
UINT ImeCmpkey(void)
{ //共享软件内部注册码发生函数
static unsigned int sum;
static BOOL flag;
static unsigned int far *pt;
static UINT Sel1,Sel2;
static WORD Seg,Off,Start;
static DWORD Bas,Lim;
flag=TRUE;
sum=0x1234;
__asm mov Sel1,ds;//将DS作为模板
Sel2=AllocSelector(Sel1);//分派一个新选择符
if(Sel2==NULL){
flag=FALSE;
pt=(unsigned int far*)0xf000fff0L;
} else {
Seg=0xffff; //绝对地点段址
Off=0x10; //绝对地点偏移
Start=0x0;
Bas=((unsigned long)Seg)<<4|Start;
Lim=(unsigned long)Off-1;
SetSelectorBase(Sel2,Bas);
SetSelectorLimit(Sel2,Lim);
pt=(unsigned int far*)((((unsigned long)Sel2)<<16)|Start);
}
for(j=0;j<4;j++){//形成16位注册码
for(i=0;i<5;i++) sum+=(*(pt+3+i)+0x1818)^0x5858;//形成前4位
sum^=0x1234<<j;//举办移位异或处理惩罚
wsprintf((LPSTR)sImeG.ImeKey+4*j,(LPSTR)"%04x",sum);
}
if(flag==TRUE) FreeSelector(Sel2);
sImeG.ImeKey[16]=0;//对注册码自己加密
for(i=16;i>0;i--) sImeG.ImeKey[16-i]^=(unsigned char)i;
for(i=0;i<16;i++){ //判定注册码
if(sImeG.ImeKey[i]!=lpImeL->ZcMyOk[i]) break;
}
if(i==16){
sImeG.ZcFlag=FALSE;
sImeG.ZcCount=0x0;
lpImeL->UseNum=0x0;
for(i=0;i<16;i++) sImeG.ImeKey[i]=0x0;
return(0);
} else {
sImeG.ZcFlag=TRUE;
sImeG.ZcCount=0x0;
sImeG.iSel = 1;
sImeG.FScrCz = TRUE;
lstrcpy(sImeG.szSel[0],(LPSTR)"注册:_________________");
sImeG.szSel[0][6]=0x11;
sImeG.szSel[0][23]=0x0;
UpdateInList();
return(~0);
}
}
四、注册点
共享软件内部注册码发生后,需要反抗盗版的注册点的几多取决于共享软件的自身代价、开拓者的加密深度和软件实现的庞洪水平等诸多因素,同时这也抉择了注册提示信息的显示频度,来套磁用户举办正当利用。但就笔者自身而言,至少应该将共享软件中实现难度较大、深受用户接待以及普遍利用的成果加上注册点。发起差异平台之间的注册码要别离设计注册算法和注册码。其代码示譬喻下:
注册点一:
if(lpImeL->UseNum>=0x3f80){
if(ImeCmpKey()==~0){
sImeG.ZcFlag=TRUE;
} else {
sImeG.ZcFlag=FALSE;
lpImeL->UseNum=0x0;
}
} else lpImeL->UseNum+=sImeG.iWord;
注册点二:
if(ImeCmpKey()==~0){
sImeG.ZcFlag=TRUE;
return;
} else {
sImeG.ZcFlag=FALSE;
lpImeL->UseNum=0x0;
}
五、注册口
对付共享软件,不管其实现何种成果,最好采纳再线注册方法,这样可以减罕用户许多反复操纵。同时应该采纳多个注册进口,如本人软件可以在增加或删除词组等时举办注册,只要一处注册乐成整个软件就算注册乐成,并留意对注册口输入的注册码举办再加密处理惩罚。
笔者共享软件中注册口代码示例代码如下:
#p#分页标题#e#
if(sImeG.ZcFlag==TRUE){
if((cCharCode==0x8)||(cCharCode==0x4b)){
if(sImeG.ZcCount>0){ //删除键处理惩罚
if(sImeG.ZcCount<17)
sImeG.szSel[0][sImeG.ZcCount+6]=0x5f;
else sImeG.szSel[0][sImeG.ZcCount+6]=0x0;
sImeG.ZcCount--;
sImeG.szSel[0][sImeG.ZcCount+6]=0x11;
lpImeL->ZcMyOk[sImeG.ZcCount]=0x0;
sImeG.iSel = 0x1;
sImeG.FScrCz = TRUE;
UpdateInList();
} else MessageBeep(-1);
} else if (cCharCode==0xd){//回车键处理惩罚
if(sImeG.ZcCount==0x10){
sImeG.ZcFlag=FALSE;
sImeG.ZcCount=0x0;
sImeG.iSel = 0x0;
ScrnCode(sImeG.iStart);
sImeG.FScrCz = TRUE;
UpdateInList();
for(i=16;i>0;i--)
lpImeL->ZcMyOk[16-i]^=(unsigned char)i;
lpImeL->ZcMyOk[16]=0;
for(i=0;i<16;i++){
if(sImeG.ImeKey[i]!=lpImeL->ZcMyOk[i]) break;
}
if(i==16){//写入注册码
for(i=0;i<16;i++) sImeG.ImeKey[i]=0x0;
j=GetSystemDirectory(FileName,80);
if((j==0)||(j>64)){
wsprintf((LPSTR)sImeG.ImeBuff,(LPSTR)"系统路径犯科!");
ErrMessageBox((LPSTR)sImeG.ImeBuff);
for(i=0;i<16;i++) lpImeL->ZcMyOk[i]=0x0;
ShowMessTs(8);
} else {
lstrcat(FileName,(LPSTR)"\\");
lstrcat(FileName,(LPSTR)"WBCOOL.IME");
if((hTmp=_lopen(FileName,READ_WRITE))==-1){
wsprintf((LPSTR)sImeG.ImeBuff,(LPSTR)"措施打开堕落!");
ErrMessageBox((LPSTR)sImeG.ImeBuff);
for(i=0;i<16;i++) lpImeL->ZcMyOk[i]=0x0;
ShowMessTs(8);
} else {
_llseek(hTmp,0x12345L,SEEK_SET);//12345为注册码地点
_lwrite(hTmp,lpImeL->ZcMyOk,16);
_lclose(hTmp);
ShowMessTs(7);
}
}
} else {
for(i=0;i<16;i++){
sImeG.ImeKey[i]=0x0;
lpImeL->ZcMyOk[i]=0x0;
}
ShowMessTs(8);
}
} else MessageBeep(-1);
} else if ((cCharCode>=0x30)&&(cCharCode<='~')){
if(sImeG.ZcCount<16){
if((cCharCode>='A')&&(cCharCode<='Z')) cCharCode^=0x20;
lpImeL->ZcMyOk[sImeG.ZcCount]=cCharCode;
sImeG.szSel[0][sImeG.ZcCount+6]=cCharCode;
sImeG.ZcCount++;
sImeG.szSel[0][sImeG.ZcCount+6]=0x11;
sImeG.iSel = 0x1;
sImeG.FScrCz = TRUE;
UpdateInList();
} else MessageBeep(-1);
} else MessageBeep(-1);
return(iRet);
}
总之,共享宣布软件的建造应做到:注册源要选准、注册算法要多变、注册码要再加密、注册秘密管好、注册点要多方位、注册方法要在线、注册进口要多点。这样才气确保软件的安详靠得住。