篇一:通过机器码获得注册码的完整方案(转贴过来,留着看看)
通过机器码获得注册码的完整方案(转贴过来,留着看看)
想加密自己的软件,看过一些软件的作法,思路如下:
1、用户安装后,得出本机的机器码(硬盘的序列号,不想用网卡,因为很多机器没有网
卡)。生成机器码代码
2、用户将该机器码EMAIL给我,我用该机器码生成一个注册码,发送给用户。注册码生成
代码
3、用户在程序中输入该注册码,程序逆算该注册码,与机器码核对,查看是否相符。注册
码逆算、核对代码,
4、如果用户安装后没有得到注册码,在N天后部分功能不可用。不要太容易被改(虽然说
安装后也只有少部份功能能用)。时限功能代码,
zw84611 (2002-12-2 23:8)
function GetHDNumber(Drv : String): DWORD; //得到硬盘序列号
var
VolumeSerialNumber : DWORD;
MaximumComponentLength : DWORD;
FileSystemFlags : DWORD;
begin
if Drv[Length(Drv)] =':' then Drv := Drv + '\';
GetVolumeInformation(pChar(Drv),
nil,
0,
@VolumeSerialNumber,
MaximumComponentLength,
FileSystemFlags,
nil,
0);
Result:= (VolumeSerialNumber);
end;
function Serial(Num:DWORD):string; //这个号码是用户给你生成注册码的,它通过对硬盘序列号编码而来。
var sNum:string; inChar:array[1..4]of char;
begin
Num:=Num xor 8009211011;
sNum:=inttostr(Num);
inChar[1]:=char(((integer(sNum[1])+integer(sNum[2]))mod 5)+integer('a'));
inChar[2]:=char(((integer(sNum[3])+integer(sNum[4]))mod 5)+integer('a'));
inChar[3]:=char(((integer(sNum[5])+integer(sNum[6]))mod 5)+integer('a'));
inChar[4]:=char(((integer(sNum[7])+integer(sNum[8])+integer(sNum[9]))mod 5)+integer('a'));
insert(inChar[1],sNum,1);
insert(inChar[4],sNum,3);
insert(inChar[2],sNum,5);
insert(inChar[3],sNum,9);
Result:=sNum;
end;
function encode(License:string):string;
var str,sNum:string; number:dword; byte,byte1:array[1..4]of dword;
inChar:array[1..3]of char;
begin
str:=license;
delete(str,1,1);
delete(str,2,1);
delete(str,3,1);
delete(str,6,1);
number:=strtoint64(str);
number:=not number;
number:=number xor $1973122980;
byte[1]:=(number and $0ff000000) shr 24;
byte[2]:=(number and $0ff0000) shr 16;
byte[3]:=(number and $0ff00) shr 8;
byte[4]:=(number and $0ff);
byte1[1]:=((byte[1]and $0c0)+(byte[2]and $0c0)shr 2)+((byte[3]and $0c0)shr 4)+((byte[4]and $0c0)shr 6); byte1[2]:=((byte[1]and $30)shl 2)+(byte[2]and $30)+((byte[3]and $30)shr 2)+((byte[4]and $30)shr 4); byte1[3]:=((byte[1]and $0c)shl 4)+((byte[2]and $0c)shl 2)+(byte[3]and $0c)+((byte[4]and $0c)shr 2); byte1[4]:=((byte[1]and $03)shl 6)+((byte[2]and $03)shl 4)+((byte[3]and $03)shl 2)+(byte[4]and $03);
number:=((byte1[1])shl 24)+((byte1[2])shl 16)
+((byte1[3])shl 8)+(byte1[4]);
byte[1]:=((number and $0ff000000)shr 24);//右移24位
byte[2]:=((number and $0ff0000)shr 16);
byte[3]:=((number and $0ff00)shr 8);
byte[4]:=(number and $0ff);
byte[1]:=(((byte[1] and $f0))shr 4)+(((byte[1] and $0f))shl 4);
byte[2]:=(((byte[2] and $f0))shr 4)+(((byte[2] and $0f))shl 4);
byte[3]:=(((byte[3] and $f0))shr 4)+(((byte[3] and $0f))shl 4);
byte[4]:=(((byte[4] and $f0))shr 4)+(((byte[4] and $0f))shl 4);
number:=((byte[2])shl 24)+((byte[1])shl 16)
+((byte[4])shl 8)+(byte[3]);
sNum:=inttostr(Number);
inChar[1]:=char(((integer(sNum[1])+integer(sNum[2]))mod 5)+integer('a'));
inChar[2]:=char(((integer(sNum[3])+integer(sNum[4]))mod 5)+integer('a'));
inChar[3]:=char(((integer(sNum[5])+integer(sNum[6]))mod 5)+integer('a'));
insert(inChar[1],sNum,1);
insert(inChar[2],sNum,5);
insert(inChar[3],sNum,9);
result:=sNum;
end;
function decode(code:string):dword;
var str:string; number:dword; byte,byte1:array[1..4]of dword;
begin
str:=code;
delete(str,1,1);
delete(str,4,1);
delete(str,7,1);
number:= strtoint64(str);
byte[1]:=(number and $0ff000000) shr 24;
byte[2]:=(number and $0ff0000) shr 16;
byte[3]:=(number and $0ff00) shr 8;
byte[4]:=(number and $0ff);
////0123 --> 1032
byte[1]:=(((byte[1] and $f0))shr 4)+(((byte[1] and $0f))shl 4);
byte[2]:=(((byte[2] and $f0))shr 4)+(((byte[2] and $0f))shl 4);
byte[3]:=(((byte[3] and $f0))shr 4)+(((byte[3] and $0f))shl 4);
byte[4]:=(((byte[4] and $f0))shr 4)+(((byte[4] and $0f))shl 4);
number:=((byte[2])shl 24)+((byte[1])shl 16)
+((byte[4])shl 8)+(byte[3]);
byte[1]:=((number and $0ff000000)shr 24);//右移24位
byte[2]:=((number and $0ff0000)shr 16);
byte[3]:=((number and $0ff00)shr 8);
byte[4]:=(number and $0ff);
byte1[1]:=(byte[1]and $0c0)+((byte[2]and $0c0)shr 2)+((byte[3]and $0c
oceanwave (2002-12-3 7:28)
谢先!试试看,可以后马上开贴给分。
妙兔无花 (2002-12-3 7:41)
分
sxd781017 (2002-12-3 7:50)
good!
oceanwave (2002-12-3 8:1)
to zw84611:
试了你的代码后,有几个问题请教:
1、用GetHDNumber取得硬盘序列号后,用Serial生成注册码。那encode和decode如何用呢?
2、如何将serial逆算成为硬盘序列号与原序列号相核对?
3、Serial函数中第一行的8009211011应该就是一个加密转换的常量吧?还有inChar的Index
值?
oceanwave (2002-12-3 8:35)
看了一篇这方面的文章,是VC++的,不过思路一样
/develop/vc/article/20011113001.htm
youth[dfw] (2002-12-3 8:37)
1、利用RSA算法
2、在功能函数中进行校验
3、多处进行校验
4、利用线程、消息、延时
5、监测软件关键点,防止强行跳过
、、、
飘摇客 (2002-12-4 9:25)
可行,使用GUID,放在注册表中,同时把这个GUID发回给你,你可以使用这个进行注册码和注册码验
证。
获得GUID,
uses activex;
var
guid:TGUID;
CoCreateGUID(guid);
ShowMessage(GuidToString(guid));
yczjs (2002-12-4 10:19)
用SoftSentry加密软件搞定
Delphi园地
http://mydelphi.8u8.com
飘摇客 (2002-12-4 13:40)
其实任何的加密基本上都能被破解,这里给你一个思路。
1、用户第一次运行软件后,生成一个GUID,保存在注册表中,另外存储在文件中或者写入系统已有的文
件尾部。
此为机器码,让用户发回,如果用户在注册表中删除了,就从文件中读取GUID,然后写入注册表。当然
应该还需用户发回用户的相关信息,保证在重新安装机器时能向你索回注册码;
2、根据此GUID写一个验证序列号的过程(软件中);
3、写一个注册机,根据用户邮寄回的GUID得到注册码,发给用户用于注册;
4、最好提供在线更新功能,更新时记录用户机器码(GUID),如发现有同一个GUID对同一个版本进行
更新,就发布新的版本,使该GUID对应的注册码不可用。
zbsfg (2002-12-4 13:52)
oceanwave (2002-12-4 14:16)
前面我有给过一个网址:
/develop/vc/article/20011113001.htm
这里就有提到:
------------------------------------------------------------------------------
为了确保注册码的唯一性,在注册源的采集上应当尽量选取一些唯一的、不易复制的软、 硬件信息作为原始信息。而硬件由于其不可复制性和物理唯一性成为了我们的首选目标, 而且多数计算机配件在出厂时都有一个唯一的标识号,我们可以将其作为识别的依据。符 合上述条件的标识号大致有硬盘的序列号、网卡的序列号、BIOS中的主版序列号或主机出 厂日期和标志等几种,考虑到硬件通用性、实现起来的难易程度以及系统安全性等多种因 素以硬盘序列号为佳,因为网卡随说唯一性最好但不能保证每台计算机都装有网卡,而
ROM BIOS中F000H-FFFFH区域虽存有与硬件配置有关的信息、F000H:FFF5H-F000H:FFFFH存 有主机出厂日期和主机标志值等参数,但在Windows 9x的保护模式下编程实现是比较困难 的。虽然在Windows 9x保护模式下对硬盘序列号也不能按通常在DOS模式下的通过硬盘端口 1F6H和1F7H直接读取,但Windows API函数中提供的下面这个函数可以非常简单的获取到指
定磁盘驱动器的序列号:
GetVolumeInformation("C:\\",NULL,NULL,&dwIDESerial,NULL,NULL,NULL,NULL);
第一个参数设为"C:\\"表示我们要读取C盘驱动器的序列号。之所以选C盘,是因为我们不 能保证用户有多个分区,而C盘却是每一个用户都具有的。该函数成功调用完毕后,在 DWORD型的变量dwIDESerial中就存储了获取到的32位长的磁盘序列号。注册信息采集到后 ,关键的问题就是如何让用户将其返回给开发者。一种较简单的方法是把采集到的硬盘序 列号与用户输入的注册名经过位操作的简单加密后存放到一个文本中通过邮件传送给开发
者。
------------------------------------------------------------------------------
oceanwave (2002-12-5 11:20)
软件加密系列问题2:加密算法
/delphibbs/dispq.asp?lid=1487410
软件加密系列问题3:注册信息的保存
/delphibbs/dispq.asp?lid=1487438
oceanwave (2002-12-5 11:23)
软件加密系列问题0:注册流程
/delphibbs/dispq.asp?lid=1487449
zbsfg (2002-12-6 9:23)
crc32算法,保证能用
UNIT CRC32;
INTERFACE
USES
Windows; // DWORD for D3/D4 compatibility
TYPE
{$IFDEF VER130} // This is a bit awkward
篇二:VC++带加密的密码类编程要点
带加密的密码类编程要点
一、密码类的结构
二、密码类的定义
#include<conio.h>
#include<fstream>
#include<string.h>
#incl(本文来自:WwW.xiaOCaofAnweN.Com 小草范文 网:vc加密序列号)ude<iostream>
using namespace std;
class PassWord
{
private:
struct user
{
char username[11];
char password[11];
}up[10];
public:
PassWord()
{
int i;
for(i=0;i<11;i++)
{
strcpy(up[i].username,"");
strcpy(up[i].password,"");
}
}
void ReadFile() // 读用户文件
void WriteFile()// 写用户文件
void GetUserName(char uname[],int i) // 获取用户名
void InputUserName(int &i) // 输入用户名
void hide(char mm[])// 隐藏输入密码
void InputPassWord(int i)// 输入密码
void AppendUser() // 增加用户
void DelUser() // 删除用户
void ModifyPassword() // 修改用户密码
void PrintUser() // 显示用户名和密码
void ModifyUser(char cz[]) // 用户维护主菜单
} ;
函数代码如下:
PassWord()
{
int i;
for(i=0;i<11;i++)
{
strcpy(up[i].username,"");
strcpy(up[i].password,"");
}
}
void WriteFile() //写用户文件
{
fstream userfile;
userfile.open("user.dat",ios::out);
if(!userfile)
{
cout<<"password file can't open.\n";
abort();
}
userfile.write((char *)up,sizeof(up));
userfile.close();
}
void ReadFile() //读用户文件
{
fstream userfile;
userfile.open("user.dat",ios::in);
if(!userfile)
{
int i,j;
i=0;
cout<<"\n\n 您是第一次实用该系统,请设置用户"<<endl<<endl;
cout<<" 请输入用户名(1-10个字符):";
cin>>up[i].username;
cout<<" 请输入用户密码(1-10个字符):";
cin>>up[i].password;j=0;
}
else
{
userfile.read((char *)up,sizeof(up));
userfile.close();
}
}
void InputUserName(int &i) //输入用户名
{
char str[11];
int check=0;
ReadFile();
cout<<"\n\t\t\t\t 用户名: ";
for(int n=3;n>0;n--)
{
}
void hide(char mm[]) //输入密码
{
int index=0;
while(1)
{
char ch;
ch=getch();
if(ch==8)
{
if(index!=0)
{
cout<<char(8)<<" "<<char(8);
index--;
}
}
else if(ch=='\r')
{
mm[index]='\0';
cout<<endl;
break;
}
else
{
cout<<"*";
mm[index++]=ch;
}
}
}
void InputPassWord(int i) //输入密码
{
char pw[11];
int check=0;
int n=3;
printf("\n\t\t\t\t%s"," 密 码: ");
cout<<" ";
do
{ cin>>str; i=0; while(strcmp(str,up[i].username)!=0 && i<10)i++; if(strcmp(str,up[i].username)==0) { check=1; break; } else {cout<<"用 户 名 不 正 确, 请 重 新 输 入 : "; } } if(!check) { cout<<endl<<"对不起,您已经输入了三次,请查证后再进入!!!"<<endl<<endl;exit(1); }
hide(pw);
if(strcmp(pw,up[i].password)==0)
{
system("cls");
cout<<"\n\n\n\t\t欢 迎 进 入 趣 味 抽 奖 系 统 !"<<endl<<endl; check=1;
break;
}
else
{
printf("密 码 不 正 确, 请 重 新 输 入 : ");
n--;
}
}while(n>0);
if(!check)
{
cout<<endl<<"对不起,您已经输入了三次,请查证后再进入!!!"<<endl<<endl;exit(1);
}
}
void AppendUser() //增加用户
{
int i,j;
i=0;
cout<<"\n\n 增加用户"<<endl<<endl;
while(strcmp(up[i].username,"")!=0)
i++;
cout<<" 请输入用户名(1-10个字符):";
cin>>up[i].username;
j=0;
while(strcmp(up[i].username,up[j].username)!=0)
j++;
if(j==i)
{
cout<<" 请输入用户密码(1-10个字符):";
cin>>up[i].password;
}
else
cout<<" 该用户已经存在!";
}
void DelUser() //删除用户
{
int i,j;
char yn,delname[11];
cout<<" 请输入要删除的用户名:";
cin>>delname;
cout<<" 是否确认(y/n)?:";
cin>>yn;
if(yn=='Y'||yn=='y')
{
i=0;
while(strcmp(delname,up[i].username)!=0 && i<11)
i++;
if(i==11)
cout<<" 用户名错误或没有该用户!";
else
for(j=i+1;j<11;j++)
{
strcpy(up[j-1].username,up[j].username);
strcpy(up[j-1].password,up[j].password);
}
}
}
void ModifyPassword() //修改用户密码
{
char delname[11],oldpassword[11];
int i;
cout<<" 请输入用户名:";
cin>>delname;
i=0;
while(strcmp(delname,up[i].username)!=0 && i<11)
i++;
if(i==11)
cout<<" 用户名错误或没有该用户!";
else
{
cout<<" 请输入用户旧密码:";
cin>>oldpassword;
if(strcmp(oldpassword,up[i].password)!=0)
{
cout<<" 用户旧密码错误!";
}
else
{
cout<<" 请输入用户新密码:";
cin>>up[i].password;
}
}
}
void PrintUser() //显示用户名和密码
{
int i=0;
cout<<"用户名\t密码\n";
while(strcmp(up[i].username,"")!=0)
{
cout<<up[i].username<<"\t"<<up[i].password<<endl;
i++;
}
}
void ModifyUser() // 维护用户菜单
{
char ynn='n',choice,jx,cho[2];
ReadFile();
do
{
system("cls");
cout<<"**********************************************"<<endl;cout<<"* 用 户 名 及 密 码 维 护 程 序 *"<<endl;
cout<<"**********************************************"<<endl<<endl;cout<<" A. 增加用户" <<endl<<endl;
cout<<" B. 删除用户" <<endl<<endl;
篇三:VC获得硬盘序列号
VC 之获取硬盘序列号
上一回,一帆风给大家讲了讲如何读取计算机的MAC地址,这次聊聊怎么获取硬盘序列号。硬盘物理序列号是硬盘的出厂序列号,它是全球都是唯一的,不会随着系统的安装、硬盘的格式化等操作而改变,跟mac地址一样都具有唯一性。 1,第一步:创建设备对象,得到设备句柄,设备为硬盘。
{
CString sFilePath;
sFilePath.Format("\\\\.\\PHYSICALDRIVE%d", driver);
HANDLE hFile=::CreateFile(sFilePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING,
0, NULL);
DWORD dwBytesReturned;
GETVERSIONINPARAMS gvopVersionParams;
DeviceIoControl(hFile, //向设备对象发送SMART_GET_VERSION设备请求,获取硬盘属性
SMART_GET_VERSION,
NULL,
0,
&gvopVersionParams,
sizeof(gvopVersionParams),
&dwBytesReturned, NULL);
if(gvopVersionParams.bIDEDeviceMap <= 0) return -2;
2。第二步,发送SMART_RCV_DRIVE_DATA设备请求,获取硬盘详细信息。 // IDE or ATAPI IDENTIFY cmd
int btIDCmd = 0;
SENDCMDINPARAMS InParams;
int nDrive =0;
btIDCmd = (gvopVersionParams.bIDEDeviceMap >> nDrive & 0x10) ? IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;
// 输出参数
BYTE btIDOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
if(DoIdentify(hFile,
&InParams,
(PSENDCMDOUTPARAMS)btIDOutCmd,
(BYTE)btIDCmd,
(BYTE)nDrive, &dwBytesReturned) == FALSE) return -3;
::CloseHandle(hFile);
DWORD dwDiskData[256];
USHORT *pIDSector; // 对应结构IDSECTOR,见头文件
pIDSector = (USHORT*)((SENDCMDOUTPARAMS*)btIDOutCmd)->bBuffer; for(int i=0; i < 256; i++) dwDiskData[i] = pIDSector[i];
// 取系列号
ZeroMemory(szSerialNumber, sizeof(szSerialNumber));
strcpy(szSerialNumber, ConvertToString(dwDiskData, 10, 19));
// 取模型号
ZeroMemory(szModelNumber, sizeof(szModelNumber));
strcpy(szModelNumber, ConvertToString(dwDiskData, 27, 46));
return 0;
}
BOOL __fastcall DoIdentify( HANDLE hPhysicalDriveIOCTL,
PSENDCMDINPARAMS pSCIP,
PSENDCMDOUTPARAMS pSCOP,
BYTE btIDCmd,
BYTE btDriveNum,
PDWORD pdwBytesReturned)
{
pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
pSCIP->irDriveRegs.bFeaturesReg = 0;
pSCIP->irDriveRegs.bSectorCountReg = 1;
pSCIP->irDriveRegs.bSectorNumberReg = 1;
pSCIP->irDriveRegs.bCylLowReg = 0;
pSCIP->irDriveRegs.bCylHighReg = 0;
pSCIP->irDriveRegs.bDriveHeadReg = (btDriveNum & 1) ? 0xB0 : 0xA0;
pSCIP->irDriveRegs.bCommandReg = btIDCmd;
pSCIP->bDriveNumber = btDriveNum;
pSCIP->cBufferSize = IDENTIFY_BUFFER_SIZE;
return DeviceIoControl( hPhysicalDriveIOCTL,
SMART_RCV_DRIVE_DATA,
(LPVOID)pSCIP,
sizeof(SENDCMDINPARAMS) - 1,
(LPVOID)pSCOP,
sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
pdwBytesReturned, NULL);
}
char *__fastcall ConvertToString(DWORD dwDiskData[256], int nFirstIndex, int nLastIndex)
{
static char szResBuf[1024];
char ss[256];
int nIndex = 0;
int nPosition = 0;
for(nIndex = nFirstIndex; nIndex <= nLastIndex; nIndex++)
{
ss[nPosition] = (char)(dwDiskData[nIndex] / 256);
nPosition++;
// Get low BYTE for 2nd character
ss[nPosition] = (char)(dwDiskData[nIndex] % 256);
nPosition++;
}
// End the string
ss[nPosition] = '\0';
int i, index=0;
for(i=0; i<nPosition; i++)
{
if(ss[i]==0 || ss[i]==32) continue; szResBuf[index]=ss[i];
index++;
}
szResBuf[index]=0;
return szResBuf;
}