oceanwave (2002-12-2 19:8) 1479167
想加密自己的软件,看过一些软件的作法,思路如下:
1、用户安装后,得出本机的机器码(硬盘的序列号,不想用网卡,因为很多机器没有网
卡)。生成机器码代码,150分
2、用户将该机器码EMAIL给我,我用该机器码生成一个注册码,发送给用户。注册码生成
代码,150分
3、用户在程序中输入该注册码,程序逆算该注册码,与机器码核对,查看是否相符。注册
码逆算、核对代码,150分。
4、如果用户安装后没有得到注册码,在N天后部分功能不可用。不要太容易被改(虽然说
安装后也只有少部份功能能用)。时限功能代码,150分。
其余100分,参与者有分。
先出100,其余分另开贴给。谢谢!
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)
谢先!试试看,可以后马上开贴给分。
oceanwave (2002-12-3 8:1)
to zw84611:
试了你的代码后,有几个问题请教:
1、用GetHDNumber取得硬盘序列号后,用Serial生成注册码。那encode和decode如何用呢?
2、如何将serial逆算成为硬盘序列号与原序列号相核对?
3、Serial函数中第一行的8009211011应该就是一个加密转换的常量吧?还有inChar的Index
值?
再请教大家关于加密软件的一些经验,同样给出150分酬谢。(当是散分了)
sxqsxq (2002-12-3 8:10)
最好做一个不可逆的算法
oceanwave (2002-12-3 8:35)
看了一篇这方面的文章,是VC++的,不过思路一样
http://www.powerba.com/develop/vc/article/20011113001.htm
zw84611的回答很好。现在的问题是
不可逆算法的实现,多层的加密位,注册信息的保存,还有先前第四个问题。
谢谢
youth[dfw] (2002-12-3 8:37)
1、利用RSA算法
2、在功能函数中进行校验
3、多处进行校验
4、利用线程、消息、延时
5、监测软件关键点,防止强行跳过
、、、
zbsfg (2002-12-3 8:39)
这个应该是硬盘的序列号,而不是硬盘的机器码,格式化后序列号失效。
xmodem (2002-12-3 8:47)
硬盘序列号可以复制的,硬盘的机器码到是不错,但是SCSI硬盘没有,读出来全0
jifee (2002-12-3 8:51)
即使用硬盘的机器码也有问题,有些硬盘没有序列号。
我采用硬盘的机器码加密已经有三年了,这种事情遇到过!
最好采用Bios的内容加密。不过Bios一旦升级则密码失效!
我所采用的方法是内存大小+硬盘大小+硬盘序列号+CPU型号和速度+Bios中的某固定数据段
前提是他的计算机不允许升级或者升级后允许到你那里重新注册(激活)。
以上的硬件信息的获取方法本论坛十分丰富(自己找找看吧)。
oceanwave (2002-12-3 9:1)
其实用GetVolumeInformation这个API获得的是分区的序列号,我说的机器码是对用户而言
的。因为是分区的序列号,所以每次格式化或对硬盘的FAT表进行改动后,序列号都会改变
。这个问题都不大。
to youth[dfw]:请问能给出具体的代码吗?额外给100分。谢谢!
大梦 (2002-12-4 8:59)
JIFEE的做法够可靠,但如果再加上网卡序列号会更好。
因为如果组成一个多台计算机的环境,所购计算机会使用相同配置的同一批机器。
GHOST就可以解决问题。
oceanwave (2002-12-4 9:8)
有道理,不过关键是有否网卡的情况下机器码分别是如何生成。谢谢!
怎么都没人回答了?分不够可以再加嘛。
lop (2002-12-4 9:21)
这个问题我最近也想过,可否这样:不一定要取硬件的固定码,可否在程序中生成一个随机码
放在系统的注册表中,以后就用这个随机码进行生成注册码和注册码验证.你们觉得这个办法
可行吗?
飘摇客 (2002-12-4 9:25)
可行,使用GUID,放在注册表中,同时把这个GUID发回给你,你可以使用这个进行注册码和注册码验证。
获得GUID,
uses activex;
var
guid:TGUID;
CoCreateGUID(guid);
ShowMessage(GuidToString(guid));
oceanwave (2002-12-4 9:51)
希望有完整的通过GUID得到SN的代码方案。将会另外给分300分。
原来硬盘序列号方式回答完整后,也同样给分。
参与者也有分。
这次算是千分大放送了:)
谢谢!
fuda (2002-12-4 10:8)
建议不要用硬盘序列号,因为一方面在2000/NT/XP和中有问题,
另一方面对SCSI硬盘有问题。
建议不要用主板序列号,因为同批次的主板序列号后部分相同,
前部分与所插硬件相关。
建议使用CPU序列号
yczjs (2002-12-4 10:19)
用SoftSentry加密软件搞定
Delphi园地
http://mydelphi.8u8.com
jifee (2002-12-4 12:31)
GUID是利用网卡的序列号和当前的时间生成的,有些机器可能根本不装网卡,所以用网卡序列号也未必有效。
WindowsXP就是利用计算机中的硬件信息进行加密的,
如果能获取到WindowsXP中代表硬件信息的序列号就好了!
谁有这方面的经验?
xmodem (2002-12-4 12:34)
放在注册表里还不如不要算了,
1、可以检测到你把sn写在注册表哪里,在另外的电脑上复制即可
2、克隆整个硬盘
关于网卡号也不行,可以伪造,很简单。
oceanwave (2002-12-4 12:50)
xmodem兄说的没错,这样或那样的加密保护也只是“防君子,不防小人”。
查阅了网上的一些相关资料,用硬盘序列号还是比较通用的做法。
因此,我还是希望那位高手能回答完我先前的四个问题。
应该说zw84611兄已经回答第一个问题,150分是他的了。希望他能告诉我如何生成不可逆
的注册码,以及一些稍加的说明。就有第二、三个问题的300分了,谢谢!
还有第四个问题……
当然还有几位兄弟,如飘摇客,jifee,等等,也不一一列举了,我都会另外开贴给分。
总共发分1000分。希望大家踊跃讨论,谢谢!
飘摇客 (2002-12-4 13:40)
其实任何的加密基本上都能被破解,这里给你一个思路。
1、用户第一次运行软件后,生成一个GUID,保存在注册表中,另外存储在文件中或者写入系统已有的文件尾部。
此为机器码,让用户发回,如果用户在注册表中删除了,就从文件中读取GUID,然后写入注册表。当然应该还需用户发回用户的相关信息,保证在重新安装机器时能向你索回注册码;
2、根据此GUID写一个验证序列号的过程(软件中);
3、写一个注册机,根据用户邮寄回的GUID得到注册码,发给用户用于注册;
4、最好提供在线更新功能,更新时记录用户机器码(GUID),如发现有同一个GUID对同一个版本进行更新,就发布新的版本,使该GUID对应的注册码不可用。
zbsfg (2002-12-4 13:52)
to 飘摇客
那还不如用分区的序列号来的方便,加密解密算法网上不是很多吗?随便弄不就行了。不过
话又说回来了,软件只要给别人用,总会被人破解的,所以我一般只发布DEMO版,只有注册
用户才给正式版,这样可能会好些。虽然麻烦些,但至少软件被人破解的可能些大大降低了。
qweasd (2002-12-4 13:55)
我想问一下,是不是收到用户发来的机器码后,作者通过此机器码生成一个注册码给用户?
那作者是怎样生成注册码的呢?是不是编一个程序来生成,那这个程序跟那些破解注册机是
一回事吗?
请各位搞手顺便回答一下我的问题,谢谢。
飘摇客 (2002-12-4 14:0)
对,其实给Demo的办法不错,其实简单做一个注册的就行(用用户和你联系的邮箱和
用户名进行注册),如果别人要买你的软件就会买的。如果使用硬件加密的话相对要
好一些,但是也有问题,假如使用硬盘序列号来注册,
有些硬盘根本就没有序列号,主板也是一样的,有的主板也没有序列号,
网卡的和CPU的就没有试过了,不知道如何。
oceanwave (2002-12-4 14:0)
谢谢飘摇客!
但我的问题与先前用硬盘序列号的方式一样:
怎么由这个GUID,或是HD-SN生成一个不可逆的注册码?也就是注册机的实现代码?
oceanwave (2002-12-4 14:11)
先前zw81644兄提供的代码中,GetVolumeInformation获取的是分区的序列号,而不是硬盘
的序列号,我想这个序列号总该是有的。而飘摇客兄用GUID还会更好些,但突然想起来,
重新分区的机率应该比重新安装程序小得多,也就是分区序列号的变化会比GUID小。而FAT
、FAT32、NTFS的分区都有序列号。而这个序列号不用存储在注册表或是文件中,保密性
和方便性会更好。如果是GUID,一是在注册表中找找就可以COPY到其它机器中,保密性会
差一些,因为它是存储在外部,二是如果重装系统(分区序列号可以不变),GUID就改变
了,用户就要重新申请注册码,这就麻烦了。
虽然,这些加密比较表面,但在一定用户范围中可以保证开发者的利益。
所以,我想用硬盘序列号(准确的讲是“分区序列号”)做为注册码生成的基础会更适合
一些。
oceanwave (2002-12-4 14:16)
前面我有给过一个网址:
http://www.powerba.com/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位长的磁盘序列号。注册信息采集到后
,关键的问题就是如何让用户将其返回给开发者。一种较简单的方法是把采集到的硬盘序
列号与用户输入的注册名经过位操作的简单加密后存放到一个文本中通过邮件传送给开发
者。
------------------------------------------------------------------------------
飘摇客 (2002-12-4 14:17)
关于加密的算法网上有很多的,你可以搜索一下,寻找一个适合你使用的。
zbsfg (2002-12-5 8:47)
to oceanwave:
就是,就是,格式化毕竟比重装系统少些,还有为了保证正式版的安全,在给注册用户时最好
要约法三章,如果用户将正式版在网上发布或破解,就取消他注册用户免费升级的权利,所以
给用户的每个软件最好要记录软件的序列号,即软件EXE文件的CRC校验号码。
linx (2002-12-5 9:4)
软件EXE文件的CRC校验号码?什么东西,怎么获取?
oceanwave (2002-12-5 11:9)
参加讨论的人怎么这么少?
我把问题分割出来给分,免得有人认为我没有诚意
zw86611请到这里拿分
关于硬盘分区序列号的问题:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1487370
oceanwave (2002-12-5 11:20)
软件加密系列问题2:加密算法
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1487410
软件加密系列问题3:注册信息的保存
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1487438
oceanwave (2002-12-5 11:23)
软件加密系列问题0:注册流程
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1487449
zbsfg (2002-12-5 20:12)
to linx:
即通过对文件的CRC32算法取得一个唯一不变的值,每个文件的CRC值都不一样,就是同样的源代码
重新编译过都会不同,WINRAR中就用CRC算法来判断文件是否被破坏.
取得办法也很简单,网上有源代码,你找找看,另外,这种源代码还可以加到你的程序中,通过对自
身的检测来判断文件是否被修改过,这可是防破解的一道利器,
oceanwave (2002-12-6 7:42)
to 大梦:
老兄,你不要老说风凉话好不好?!不要在我的贴子里灌水!
我对软件做加密,并不指望不可能被人破解,但如有位老兄所说,别人破解不了我的
售后服务。我的软件并非做给专业或准专业人士所用,只想在一定范围内起到保护作用,
但起码不是形同虚设的。
你说我要求高,我怀疑你有没了解过共享软件的加密?现在很多的共享软件都采用这
样机器码到注册码的方式,实现也不过如此。
你说用加密狗,有没搞错,一个百来块钱的软件用加密狗,我看你是搞“公益事业”
的!
看看你“大梦”的资料,都回答了些什么问题。
拜托,如果不会回答,就像很多兄弟们一样“UP”或“学习”就好,做人谦虚一点儿
。如果会回答,就拿出高手的本事来,抄抄贴贴也没关系,互相帮助大富翁才会兴旺。
说实话,开这些贴子,一是为了急用,二是为了好好学习大家这方面的经验,三是让
想了解这方面的朋友们一起来学习。
oceanwave (2002-12-6 7:49)
另外向回答和参与问题的DFW们表示感谢!
who am i? (2002-12-6 8:10)
高手论道,我辈自当洗耳恭听!
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
// 8-byte integer
TInteger8 = Int64; // Delphi 5
{$ELSE}
{$IFDEF VER120}
TInteger8 = Int64; // Delphi 4
{$ELSE}
TInteger8 = COMP; // Delphi 2 or 3
{$ENDIF}
{$ENDIF}
PROCEDURE CalcCRC32 (p: pointer; ByteCount: DWORD; VAR CRCvalue: DWORD);
PROCEDURE CalcFileCRC32 (FromName: STRING; VAR CRCvalue: DWORD;
VAR TotalBytes: TInteger8;
VAR error: WORD);
IMPLEMENTATION
USES
{$IFDEF StreamIO}
SysUtils, // SysErrorMessage
{$ENDIF}
Dialogs, // ShowMessage
Classes; // TMemoryStream
CONST
table: ARRAY[0..255] OF DWORD =
($00000000, $77073096, $EE0E612C, $990951BA,
$076DC419, $706AF48F, $E963A535, $9E6495A3,
$0EDB8832, $79DCB8A4, $E0D5E91E, $97D2D988,
$09B64C2B, $7EB17CBD, $E7B82D07, $90BF1D91,
$1DB71064, $6AB020F2, $F3B97148, $84BE41DE,
$1ADAD47D, $6DDDE4EB, $F4D4B551, $83D385C7,
$136C9856, $646BA8C0, $FD62F97A, $8A65C9EC,
$14015C4F, $63066CD9, $FA0F3D63, $8D080DF5,
$3B6E20C8, $4C69105E, $D56041E4, $A2677172,
$3C03E4D1, $4B04D447, $D20D85FD, $A50AB56B,
$35B5A8FA, $42B2986C, $DBBBC9D6, $ACBCF940,
$32D86CE3, $45DF5C75, $DCD60DCF, $ABD13D59,
$26D930AC, $51DE003A, $C8D75180, $BFD06116,
$21B4F4B5, $56B3C423, $CFBA9599, $B8BDA50F,
$2802B89E, $5F058808, $C60CD9B2, $B10BE924,
$2F6F7C87, $58684C11, $C1611DAB, $B6662D3D,
$76DC4190, $01DB7106, $98D220BC, $EFD5102A,
$71B18589, $06B6B51F, $9FBFE4A5, $E8B8D433,
$7807C9A2, $0F00F934, $9609A88E, $E10E9818,
$7F6A0DBB, $086D3D2D, $91646C97, $E6635C01,
$6B6B51F4, $1C6C6162, $856530D8, $F262004E,
$6C0695ED, $1B01A57B, $8208F4C1, $F50FC457,
$65B0D9C6, $12B7E950, $8BBEB8EA, $FCB9887C,
$62DD1DDF, $15DA2D49, $8CD37CF3, $FBD44C65,
$4DB26158, $3AB551CE, $A3BC0074, $D4BB30E2,
$4ADFA541, $3DD895D7, $A4D1C46D, $D3D6F4FB,
$4369E96A, $346ED9FC, $AD678846, $DA60B8D0,
$44042D73, $33031DE5, $AA0A4C5F, $DD0D7CC9,
$5005713C, $270241AA, $BE0B1010, $C90C2086,
$5768B525, $206F85B3, $B966D409, $CE61E49F,
$5EDEF90E, $29D9C998, $B0D09822, $C7D7A8B4,
$59B33D17, $2EB40D81, $B7BD5C3B, $C0BA6CAD,
$EDB88320, $9ABFB3B6, $03B6E20C, $74B1D29A,
$EAD54739, $9DD277AF, $04DB2615, $73DC1683,
$E3630B12, $94643B84, $0D6D6A3E, $7A6A5AA8,
$E40ECF0B, $9309FF9D, $0A00AE27, $7D079EB1,
$F00F9344, $8708A3D2, $1E01F268, $6906C2FE,
$F762575D, $806567CB, $196C3671, $6E6B06E7,
$FED41B76, $89D32BE0, $10DA7A5A, $67DD4ACC,
$F9B9DF6F, $8EBEEFF9, $17B7BE43, $60B08ED5,
$D6D6A3E8, $A1D1937E, $38D8C2C4, $4FDFF252,
$D1BB67F1, $A6BC5767, $3FB506DD, $48B2364B,
$D80D2BDA, $AF0A1B4C, $36034AF6, $41047A60,
$DF60EFC3, $A867DF55, $316E8EEF, $4669BE79,
$CB61B38C, $BC66831A, $256FD2A0, $5268E236,
$CC0C7795, $BB0B4703, $220216B9, $5505262F,
$C5BA3BBE, $B2BD0B28, $2BB45A92, $5CB36A04,
$C2D7FFA7, $B5D0CF31, $2CD99E8B, $5BDEAE1D,
$9B64C2B0, $EC63F226, $756AA39C, $026D930A,
$9C0906A9, $EB0E363F, $72076785, $05005713,
$95BF4A82, $E2B87A14, $7BB12BAE, $0CB61B38,
$92D28E9B, $E5D5BE0D, $7CDCEFB7, $0BDBDF21,
$86D3D2D4, $F1D4E242, $68DDB3F8, $1FDA836E,
$81BE16CD, $F6B9265B, $6FB077E1, $18B74777,
$88085AE6, $FF0F6A70, $66063BCA, $11010B5C,
$8F659EFF, $F862AE69, $616BFFD3, $166CCF45,
$A00AE278, $D70DD2EE, $4E048354, $3903B3C2,
$A7672661, $D06016F7, $4969474D, $3E6E77DB,
$AED16A4A, $D9D65ADC, $40DF0B66, $37D83BF0,
$A9BCAE53, $DEBB9EC5, $47B2CF7F, $30B5FFE9,
$BDBDF21C, $CABAC28A, $53B39330, $24B4A3A6,
$BAD03605, $CDD70693, $54DE5729, $23D967BF,
$B3667A2E, $C4614AB8, $5D681B02, $2A6F2B94,
$B40BBE37, $C30C8EA1, $5A05DF1B, $2D02EF8D);
// Use CalcCRC32 as a procedure so CRCValue can be passed in but
// also returned. This allows multiple calls to CalcCRC32 for
// the "same"
沈浪 (2002-12-6 10:28)
{$IFDEF }{$ENDIF}
请问高手这是什么意思,怎么用呀.还有那个crc的算法的注释能不能在详点,谢谢!
oceanwave (2002-12-6 12:36)
哇!这么多朋友讨论
为表谢意,我决定讨论结束后,再开一个300分的贴子给以上参加讨论的DFW们。
准备在一周内结束。请DFW们积极发言,谢谢!
yanghai0437 (2002-12-18 13:8)
如果出现 'The stylesheet dose not contain a document element.
The stylesheet maybe empty, or it may not be a well- formated XML
document.'错误。
这是一个因为网络连接问题引起的暂时性的错误,请 按这里。选择一个
界面重新进入即可。
我有一个星期都是这样了,有人能帮我吗?
点“按这里”也没有用,但是点击以前回复的可以进来,就是看不到
我(左边的)自己的信息.
yanghai0437@sina.com
ljsh2008 (2002-12-28 22:34)
也正在为此问题发愁
谢谢
jamers (2002-12-29 2:6)
to 沈浪:
{$IFDEF }{$ENDIF}这是伪编译指令,这在使用在不兼容的系统中常用到,这也就是
程序跨平台的重要指令,可能还有其它的…
-----------------------------
仅为个人意见,如果有什么不对的,见谅,请高手更正…
我是一个初学Delphi的,呵
jamers (2002-12-29 1:58)
有高手可以帖出读取物理硬盘的序列号吗?
我想这个方式可能会好一点
建议注册码采用CpuID+HD_SER+MAC,只有这些东东是不会
常改变的,这样可以减少作者的一些工作,否则常给别人换注册码很累,最好还能做
到网上较验,否则一个用户多个注册码的话也是挺棘手的事。
可以在网络上封掉某个注册码!
至于如果没有网卡,这一栏置零或空值,再用其它一些特征码进行加密,我想不可能就只
用一种特征码进行加密吧?
[8][8][8][8][8][8][8][8][8][8][8][8][8][8]
lqldir (2002-12-29 10:35)
就我所了解的都是用硬盘的物理序列号来加密的.
这种方法好.
所以,现在的问题了是大家能贴出一篇能获取硬盘物理序列号的源代码出来..
我有,但是只能获wd的硬盘的,maxtor的好像得不到....
tohappy (2003-4-27 8:14)
关注下列问题,一定对你有益:
http://delphibbs.com/delphibbs/dispq.asp?lid=1743719
http://delphibbs.com/delphibbs/dispq.asp?lid=1742072
http://delphibbs.com/delphibbs/dispq.asp?lid=1655569
http://delphibbs.com/delphibbs/dispq.asp?lid=1786356
3cs (2003-4-27 15:29)
得到硬盘物理号及简单的算法:我贴出,我都是用它,挺好的,哈哈!
unit ISDNUNIT;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TSrbIoControl=packed record
HeaderLength: ULONG;
Signature: Array[0..7] of char;
Timeout: ULONG;
ControlCode: ULONG;
ReturnCode: ULONG;
Length: ULONG;
END;
SRB_IO_CONTROL=TSrbIoControl;
PSrbIoControl=^TSrbIoControl;
TIDERegs=packed record
bFeaturesReg: Byte;
bSectorCountReg: Byte;
bSectorNumberReg: byte;
bCyllowReg: byte;
bCylhighreg:byte;
bDriveHeadReg: byte;
bCommandReg: byte;
bReserved: byte;
end;
IDEREGS=TIDERegs;
PIDERegs=^TIDERegs;
TSendCmdInParams=packed record
cBufferSize: DWORD;
irDriveRegs: TIDEREGS;
bDriveNumber:byte;
bReserved: Array[0..2] of byte;
dwReserved: Array[0..3] of DWORD;
bBUFFER: array[0..10] of byte;
end;
SENDCMDINPARAMS=TSendCmdInParams;
PSendcmdinparams=^Tsendcmdinparams;
TIdSector=packed record
wGenConfig: word;
wNumCyls: word;
wReserved: word;
wNumHeads: word;
wBytesPerTrack: word;
wBytesPerSector:word;
wSectorsPerTrack:word;
wVendorUnique: array[0..2] of word;
sSerialNumber: Array[0..19] of char;
wBufferType: word;
wBufferSize : word;
wECCSize: word;
sFirmwareRev: array[0..7] of char;
sModelNumber: array[0..39] of char;
wMorevendorUnique: word;
wDoubleWordIO: WORD;
wcapabilities:word;
wreservedL:word;
wPIOTiming:word;
wDMATiming:word;
wBS:WORD;
wNUMcurrentCYls:word;
wNUMcurrentHeads:word;
wNUMCurrentsectorsPerTRACK:WORD;
ulCurrentSectorCapacity:ULONG;
wMultSectorStuff:Word;
ulTotalAddressableSectors:ULONG;
wSingleWordDMA:Word;
wMultiwordDMA:word;
bReserved: Array[0..127] of byte;
end;
PIdSector=^TidSECTOR;
type
TForm1 = class(TForm)
Label1: TLabel;
Label2: TLabel;
procedure FormActivate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
// procedure ChangeByteorder(var data; Size:INTEGER);
// Function readhdserial:string;
// FUNCTION ENCRyPT(serial:string):string;
var
Form1: TForm1;
serial:string;
inputserial:string;
CONST
IDENTIFY_BUFFER_SIZE=512;
DataSize=sizeof(TSendCmdInParams)-1+IDENTIFY_BUFFER_SIZE;
IOCTL_SCSI_MINIPORT=$0004d008;
IOCTL_SCSI_MINIPORT_IDENTIFY=$001b0501;
IDE_ID_FUNCTION=$EC;
BufferSize=1280;
implementation
{$R *.DFM}
procedure ChangeByteorder(var data; size:integer);
var
ptr:PChar;
i:INTEGER;
C:CHAR;
BEGIN
ptr:=@data;
for i:=0 to (size shr 1)-1 do
begin
c:=ptr^;
ptr^:=(ptr+1)^;
(ptr+1)^:=c;
Inc(ptr,2);
end;
end;
function readhdserial:string;
var
hDevice:THandle;
cbBYTESReturned:DWORD;
pindata:PSendCmdInParams;
//pide:Pideregs;
pOutData:Pointer;
Buffer:Array[0..BufferSize-1] of Byte;
srbCONTROL:tSrbIoControl absolute Buffer;
begin
result:='';
Fillchar(Buffer,buffersize,#0);
hDevice:=CreateFile('//./Scsi0:',GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0);
if hDevice=INVALID_HANDLE_VALUE then exit;
try
srbControl.HeaderLength:=sizeof(SRB_IO_CONTROL);
System.Move('SCSIDISK',srbControl.signature,8);
srbcontrol.timeout:=2;
srbcontrol.Length:=datasize;
srbcontrol.ControlCode:=IOCTL_SCSI_MINIPORT_IDENTIFY;
pInData:=PSendCmdInparams(pchar(@buffer)+sizeof(SRB_IO_CONTROL));
pOutData:=pInData;
with pInDATA^ DO
begin
cBuffersize:=IDENTIFY_BUFFER_SIZE;
bDriveNumber:=0;
// irDriveRegs:=0;
with irDriveRegs do
begin
bFeaturesreg:=1;
bsectorcountreg:=1;
bsectornumberreg:=1;
bcyllowreg:=0;
bcylhighreg:=0;
bdriveheadreg:=$A0;
bcommandreg:=IDE_ID_FUNCTION;
end;
end;
if not DeviceIoControl(hDevice,IOCTL_SCSI_MINIPORT,
@Buffer,BufferSize,@buffer,buffersize,cbbytesreturned,nil) then
exit;
with Pidsector(pchar(poutdata)+16)^ do
begin
changebyteorder(sSerialNUMber,sizeof(sserialnumber));
setstring(result,sserialnumber,sizeof(......
2005-5-23 10:10:38
发表评语»»»
2005-8-12 22:05:48 获取操作系统,CPU,硬盘等信息获取操作系统,CPU,硬盘等信息
http://www.delphibbs.com/keylife/iblog_show.asp?xid=16594
想加密自己的软件,看过一些软件的作法,思路如下:
1、用户安装后,得出本机的机器码(硬盘的序列号,不想用网卡,因为很多机器没有网
卡)。生成机器码代码,150分
2、用户将该机器码EMAIL给我,我用该机器码生成一个注册码,发送给用户。注册码生成
代码,150分
3、用户在程序中输入该注册码,程序逆算该注册码,与机器码核对,查看是否相符。注册
码逆算、核对代码,150分。
4、如果用户安装后没有得到注册码,在N天后部分功能不可用。不要太容易被改(虽然说
安装后也只有少部份功能能用)。时限功能代码,150分。
其余100分,参与者有分。
先出100,其余分另开贴给。谢谢!
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)
谢先!试试看,可以后马上开贴给分。
oceanwave (2002-12-3 8:1)
to zw84611:
试了你的代码后,有几个问题请教:
1、用GetHDNumber取得硬盘序列号后,用Serial生成注册码。那encode和decode如何用呢?
2、如何将serial逆算成为硬盘序列号与原序列号相核对?
3、Serial函数中第一行的8009211011应该就是一个加密转换的常量吧?还有inChar的Index
值?
再请教大家关于加密软件的一些经验,同样给出150分酬谢。(当是散分了)
sxqsxq (2002-12-3 8:10)
最好做一个不可逆的算法
oceanwave (2002-12-3 8:35)
看了一篇这方面的文章,是VC++的,不过思路一样
http://www.powerba.com/develop/vc/article/20011113001.htm
zw84611的回答很好。现在的问题是
不可逆算法的实现,多层的加密位,注册信息的保存,还有先前第四个问题。
谢谢
youth[dfw] (2002-12-3 8:37)
1、利用RSA算法
2、在功能函数中进行校验
3、多处进行校验
4、利用线程、消息、延时
5、监测软件关键点,防止强行跳过
、、、
zbsfg (2002-12-3 8:39)
这个应该是硬盘的序列号,而不是硬盘的机器码,格式化后序列号失效。
xmodem (2002-12-3 8:47)
硬盘序列号可以复制的,硬盘的机器码到是不错,但是SCSI硬盘没有,读出来全0
jifee (2002-12-3 8:51)
即使用硬盘的机器码也有问题,有些硬盘没有序列号。
我采用硬盘的机器码加密已经有三年了,这种事情遇到过!
最好采用Bios的内容加密。不过Bios一旦升级则密码失效!
我所采用的方法是内存大小+硬盘大小+硬盘序列号+CPU型号和速度+Bios中的某固定数据段
前提是他的计算机不允许升级或者升级后允许到你那里重新注册(激活)。
以上的硬件信息的获取方法本论坛十分丰富(自己找找看吧)。
oceanwave (2002-12-3 9:1)
其实用GetVolumeInformation这个API获得的是分区的序列号,我说的机器码是对用户而言
的。因为是分区的序列号,所以每次格式化或对硬盘的FAT表进行改动后,序列号都会改变
。这个问题都不大。
to youth[dfw]:请问能给出具体的代码吗?额外给100分。谢谢!
大梦 (2002-12-4 8:59)
JIFEE的做法够可靠,但如果再加上网卡序列号会更好。
因为如果组成一个多台计算机的环境,所购计算机会使用相同配置的同一批机器。
GHOST就可以解决问题。
oceanwave (2002-12-4 9:8)
有道理,不过关键是有否网卡的情况下机器码分别是如何生成。谢谢!
怎么都没人回答了?分不够可以再加嘛。
lop (2002-12-4 9:21)
这个问题我最近也想过,可否这样:不一定要取硬件的固定码,可否在程序中生成一个随机码
放在系统的注册表中,以后就用这个随机码进行生成注册码和注册码验证.你们觉得这个办法
可行吗?
飘摇客 (2002-12-4 9:25)
可行,使用GUID,放在注册表中,同时把这个GUID发回给你,你可以使用这个进行注册码和注册码验证。
获得GUID,
uses activex;
var
guid:TGUID;
CoCreateGUID(guid);
ShowMessage(GuidToString(guid));
oceanwave (2002-12-4 9:51)
希望有完整的通过GUID得到SN的代码方案。将会另外给分300分。
原来硬盘序列号方式回答完整后,也同样给分。
参与者也有分。
这次算是千分大放送了:)
谢谢!
fuda (2002-12-4 10:8)
建议不要用硬盘序列号,因为一方面在2000/NT/XP和中有问题,
另一方面对SCSI硬盘有问题。
建议不要用主板序列号,因为同批次的主板序列号后部分相同,
前部分与所插硬件相关。
建议使用CPU序列号
yczjs (2002-12-4 10:19)
用SoftSentry加密软件搞定
Delphi园地
http://mydelphi.8u8.com
jifee (2002-12-4 12:31)
GUID是利用网卡的序列号和当前的时间生成的,有些机器可能根本不装网卡,所以用网卡序列号也未必有效。
WindowsXP就是利用计算机中的硬件信息进行加密的,
如果能获取到WindowsXP中代表硬件信息的序列号就好了!
谁有这方面的经验?
xmodem (2002-12-4 12:34)
放在注册表里还不如不要算了,
1、可以检测到你把sn写在注册表哪里,在另外的电脑上复制即可
2、克隆整个硬盘
关于网卡号也不行,可以伪造,很简单。
oceanwave (2002-12-4 12:50)
xmodem兄说的没错,这样或那样的加密保护也只是“防君子,不防小人”。
查阅了网上的一些相关资料,用硬盘序列号还是比较通用的做法。
因此,我还是希望那位高手能回答完我先前的四个问题。
应该说zw84611兄已经回答第一个问题,150分是他的了。希望他能告诉我如何生成不可逆
的注册码,以及一些稍加的说明。就有第二、三个问题的300分了,谢谢!
还有第四个问题……
当然还有几位兄弟,如飘摇客,jifee,等等,也不一一列举了,我都会另外开贴给分。
总共发分1000分。希望大家踊跃讨论,谢谢!
飘摇客 (2002-12-4 13:40)
其实任何的加密基本上都能被破解,这里给你一个思路。
1、用户第一次运行软件后,生成一个GUID,保存在注册表中,另外存储在文件中或者写入系统已有的文件尾部。
此为机器码,让用户发回,如果用户在注册表中删除了,就从文件中读取GUID,然后写入注册表。当然应该还需用户发回用户的相关信息,保证在重新安装机器时能向你索回注册码;
2、根据此GUID写一个验证序列号的过程(软件中);
3、写一个注册机,根据用户邮寄回的GUID得到注册码,发给用户用于注册;
4、最好提供在线更新功能,更新时记录用户机器码(GUID),如发现有同一个GUID对同一个版本进行更新,就发布新的版本,使该GUID对应的注册码不可用。
zbsfg (2002-12-4 13:52)
to 飘摇客
那还不如用分区的序列号来的方便,加密解密算法网上不是很多吗?随便弄不就行了。不过
话又说回来了,软件只要给别人用,总会被人破解的,所以我一般只发布DEMO版,只有注册
用户才给正式版,这样可能会好些。虽然麻烦些,但至少软件被人破解的可能些大大降低了。
qweasd (2002-12-4 13:55)
我想问一下,是不是收到用户发来的机器码后,作者通过此机器码生成一个注册码给用户?
那作者是怎样生成注册码的呢?是不是编一个程序来生成,那这个程序跟那些破解注册机是
一回事吗?
请各位搞手顺便回答一下我的问题,谢谢。
飘摇客 (2002-12-4 14:0)
对,其实给Demo的办法不错,其实简单做一个注册的就行(用用户和你联系的邮箱和
用户名进行注册),如果别人要买你的软件就会买的。如果使用硬件加密的话相对要
好一些,但是也有问题,假如使用硬盘序列号来注册,
有些硬盘根本就没有序列号,主板也是一样的,有的主板也没有序列号,
网卡的和CPU的就没有试过了,不知道如何。
oceanwave (2002-12-4 14:0)
谢谢飘摇客!
但我的问题与先前用硬盘序列号的方式一样:
怎么由这个GUID,或是HD-SN生成一个不可逆的注册码?也就是注册机的实现代码?
oceanwave (2002-12-4 14:11)
先前zw81644兄提供的代码中,GetVolumeInformation获取的是分区的序列号,而不是硬盘
的序列号,我想这个序列号总该是有的。而飘摇客兄用GUID还会更好些,但突然想起来,
重新分区的机率应该比重新安装程序小得多,也就是分区序列号的变化会比GUID小。而FAT
、FAT32、NTFS的分区都有序列号。而这个序列号不用存储在注册表或是文件中,保密性
和方便性会更好。如果是GUID,一是在注册表中找找就可以COPY到其它机器中,保密性会
差一些,因为它是存储在外部,二是如果重装系统(分区序列号可以不变),GUID就改变
了,用户就要重新申请注册码,这就麻烦了。
虽然,这些加密比较表面,但在一定用户范围中可以保证开发者的利益。
所以,我想用硬盘序列号(准确的讲是“分区序列号”)做为注册码生成的基础会更适合
一些。
oceanwave (2002-12-4 14:16)
前面我有给过一个网址:
http://www.powerba.com/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位长的磁盘序列号。注册信息采集到后
,关键的问题就是如何让用户将其返回给开发者。一种较简单的方法是把采集到的硬盘序
列号与用户输入的注册名经过位操作的简单加密后存放到一个文本中通过邮件传送给开发
者。
------------------------------------------------------------------------------
飘摇客 (2002-12-4 14:17)
关于加密的算法网上有很多的,你可以搜索一下,寻找一个适合你使用的。
zbsfg (2002-12-5 8:47)
to oceanwave:
就是,就是,格式化毕竟比重装系统少些,还有为了保证正式版的安全,在给注册用户时最好
要约法三章,如果用户将正式版在网上发布或破解,就取消他注册用户免费升级的权利,所以
给用户的每个软件最好要记录软件的序列号,即软件EXE文件的CRC校验号码。
linx (2002-12-5 9:4)
软件EXE文件的CRC校验号码?什么东西,怎么获取?
oceanwave (2002-12-5 11:9)
参加讨论的人怎么这么少?
我把问题分割出来给分,免得有人认为我没有诚意
zw86611请到这里拿分
关于硬盘分区序列号的问题:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1487370
oceanwave (2002-12-5 11:20)
软件加密系列问题2:加密算法
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1487410
软件加密系列问题3:注册信息的保存
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1487438
oceanwave (2002-12-5 11:23)
软件加密系列问题0:注册流程
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1487449
zbsfg (2002-12-5 20:12)
to linx:
即通过对文件的CRC32算法取得一个唯一不变的值,每个文件的CRC值都不一样,就是同样的源代码
重新编译过都会不同,WINRAR中就用CRC算法来判断文件是否被破坏.
取得办法也很简单,网上有源代码,你找找看,另外,这种源代码还可以加到你的程序中,通过对自
身的检测来判断文件是否被修改过,这可是防破解的一道利器,
oceanwave (2002-12-6 7:42)
to 大梦:
老兄,你不要老说风凉话好不好?!不要在我的贴子里灌水!
我对软件做加密,并不指望不可能被人破解,但如有位老兄所说,别人破解不了我的
售后服务。我的软件并非做给专业或准专业人士所用,只想在一定范围内起到保护作用,
但起码不是形同虚设的。
你说我要求高,我怀疑你有没了解过共享软件的加密?现在很多的共享软件都采用这
样机器码到注册码的方式,实现也不过如此。
你说用加密狗,有没搞错,一个百来块钱的软件用加密狗,我看你是搞“公益事业”
的!
看看你“大梦”的资料,都回答了些什么问题。
拜托,如果不会回答,就像很多兄弟们一样“UP”或“学习”就好,做人谦虚一点儿
。如果会回答,就拿出高手的本事来,抄抄贴贴也没关系,互相帮助大富翁才会兴旺。
说实话,开这些贴子,一是为了急用,二是为了好好学习大家这方面的经验,三是让
想了解这方面的朋友们一起来学习。
oceanwave (2002-12-6 7:49)
另外向回答和参与问题的DFW们表示感谢!
who am i? (2002-12-6 8:10)
高手论道,我辈自当洗耳恭听!
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
// 8-byte integer
TInteger8 = Int64; // Delphi 5
{$ELSE}
{$IFDEF VER120}
TInteger8 = Int64; // Delphi 4
{$ELSE}
TInteger8 = COMP; // Delphi 2 or 3
{$ENDIF}
{$ENDIF}
PROCEDURE CalcCRC32 (p: pointer; ByteCount: DWORD; VAR CRCvalue: DWORD);
PROCEDURE CalcFileCRC32 (FromName: STRING; VAR CRCvalue: DWORD;
VAR TotalBytes: TInteger8;
VAR error: WORD);
IMPLEMENTATION
USES
{$IFDEF StreamIO}
SysUtils, // SysErrorMessage
{$ENDIF}
Dialogs, // ShowMessage
Classes; // TMemoryStream
CONST
table: ARRAY[0..255] OF DWORD =
($00000000, $77073096, $EE0E612C, $990951BA,
$076DC419, $706AF48F, $E963A535, $9E6495A3,
$0EDB8832, $79DCB8A4, $E0D5E91E, $97D2D988,
$09B64C2B, $7EB17CBD, $E7B82D07, $90BF1D91,
$1DB71064, $6AB020F2, $F3B97148, $84BE41DE,
$1ADAD47D, $6DDDE4EB, $F4D4B551, $83D385C7,
$136C9856, $646BA8C0, $FD62F97A, $8A65C9EC,
$14015C4F, $63066CD9, $FA0F3D63, $8D080DF5,
$3B6E20C8, $4C69105E, $D56041E4, $A2677172,
$3C03E4D1, $4B04D447, $D20D85FD, $A50AB56B,
$35B5A8FA, $42B2986C, $DBBBC9D6, $ACBCF940,
$32D86CE3, $45DF5C75, $DCD60DCF, $ABD13D59,
$26D930AC, $51DE003A, $C8D75180, $BFD06116,
$21B4F4B5, $56B3C423, $CFBA9599, $B8BDA50F,
$2802B89E, $5F058808, $C60CD9B2, $B10BE924,
$2F6F7C87, $58684C11, $C1611DAB, $B6662D3D,
$76DC4190, $01DB7106, $98D220BC, $EFD5102A,
$71B18589, $06B6B51F, $9FBFE4A5, $E8B8D433,
$7807C9A2, $0F00F934, $9609A88E, $E10E9818,
$7F6A0DBB, $086D3D2D, $91646C97, $E6635C01,
$6B6B51F4, $1C6C6162, $856530D8, $F262004E,
$6C0695ED, $1B01A57B, $8208F4C1, $F50FC457,
$65B0D9C6, $12B7E950, $8BBEB8EA, $FCB9887C,
$62DD1DDF, $15DA2D49, $8CD37CF3, $FBD44C65,
$4DB26158, $3AB551CE, $A3BC0074, $D4BB30E2,
$4ADFA541, $3DD895D7, $A4D1C46D, $D3D6F4FB,
$4369E96A, $346ED9FC, $AD678846, $DA60B8D0,
$44042D73, $33031DE5, $AA0A4C5F, $DD0D7CC9,
$5005713C, $270241AA, $BE0B1010, $C90C2086,
$5768B525, $206F85B3, $B966D409, $CE61E49F,
$5EDEF90E, $29D9C998, $B0D09822, $C7D7A8B4,
$59B33D17, $2EB40D81, $B7BD5C3B, $C0BA6CAD,
$EDB88320, $9ABFB3B6, $03B6E20C, $74B1D29A,
$EAD54739, $9DD277AF, $04DB2615, $73DC1683,
$E3630B12, $94643B84, $0D6D6A3E, $7A6A5AA8,
$E40ECF0B, $9309FF9D, $0A00AE27, $7D079EB1,
$F00F9344, $8708A3D2, $1E01F268, $6906C2FE,
$F762575D, $806567CB, $196C3671, $6E6B06E7,
$FED41B76, $89D32BE0, $10DA7A5A, $67DD4ACC,
$F9B9DF6F, $8EBEEFF9, $17B7BE43, $60B08ED5,
$D6D6A3E8, $A1D1937E, $38D8C2C4, $4FDFF252,
$D1BB67F1, $A6BC5767, $3FB506DD, $48B2364B,
$D80D2BDA, $AF0A1B4C, $36034AF6, $41047A60,
$DF60EFC3, $A867DF55, $316E8EEF, $4669BE79,
$CB61B38C, $BC66831A, $256FD2A0, $5268E236,
$CC0C7795, $BB0B4703, $220216B9, $5505262F,
$C5BA3BBE, $B2BD0B28, $2BB45A92, $5CB36A04,
$C2D7FFA7, $B5D0CF31, $2CD99E8B, $5BDEAE1D,
$9B64C2B0, $EC63F226, $756AA39C, $026D930A,
$9C0906A9, $EB0E363F, $72076785, $05005713,
$95BF4A82, $E2B87A14, $7BB12BAE, $0CB61B38,
$92D28E9B, $E5D5BE0D, $7CDCEFB7, $0BDBDF21,
$86D3D2D4, $F1D4E242, $68DDB3F8, $1FDA836E,
$81BE16CD, $F6B9265B, $6FB077E1, $18B74777,
$88085AE6, $FF0F6A70, $66063BCA, $11010B5C,
$8F659EFF, $F862AE69, $616BFFD3, $166CCF45,
$A00AE278, $D70DD2EE, $4E048354, $3903B3C2,
$A7672661, $D06016F7, $4969474D, $3E6E77DB,
$AED16A4A, $D9D65ADC, $40DF0B66, $37D83BF0,
$A9BCAE53, $DEBB9EC5, $47B2CF7F, $30B5FFE9,
$BDBDF21C, $CABAC28A, $53B39330, $24B4A3A6,
$BAD03605, $CDD70693, $54DE5729, $23D967BF,
$B3667A2E, $C4614AB8, $5D681B02, $2A6F2B94,
$B40BBE37, $C30C8EA1, $5A05DF1B, $2D02EF8D);
// Use CalcCRC32 as a procedure so CRCValue can be passed in but
// also returned. This allows multiple calls to CalcCRC32 for
// the "same"
沈浪 (2002-12-6 10:28)
{$IFDEF }{$ENDIF}
请问高手这是什么意思,怎么用呀.还有那个crc的算法的注释能不能在详点,谢谢!
oceanwave (2002-12-6 12:36)
哇!这么多朋友讨论
为表谢意,我决定讨论结束后,再开一个300分的贴子给以上参加讨论的DFW们。
准备在一周内结束。请DFW们积极发言,谢谢!
yanghai0437 (2002-12-18 13:8)
如果出现 'The stylesheet dose not contain a document element.
The stylesheet maybe empty, or it may not be a well- formated XML
document.'错误。
这是一个因为网络连接问题引起的暂时性的错误,请 按这里。选择一个
界面重新进入即可。
我有一个星期都是这样了,有人能帮我吗?
点“按这里”也没有用,但是点击以前回复的可以进来,就是看不到
我(左边的)自己的信息.
yanghai0437@sina.com
ljsh2008 (2002-12-28 22:34)
也正在为此问题发愁
谢谢
jamers (2002-12-29 2:6)
to 沈浪:
{$IFDEF }{$ENDIF}这是伪编译指令,这在使用在不兼容的系统中常用到,这也就是
程序跨平台的重要指令,可能还有其它的…
-----------------------------
仅为个人意见,如果有什么不对的,见谅,请高手更正…
我是一个初学Delphi的,呵
jamers (2002-12-29 1:58)
有高手可以帖出读取物理硬盘的序列号吗?
我想这个方式可能会好一点
建议注册码采用CpuID+HD_SER+MAC,只有这些东东是不会
常改变的,这样可以减少作者的一些工作,否则常给别人换注册码很累,最好还能做
到网上较验,否则一个用户多个注册码的话也是挺棘手的事。
可以在网络上封掉某个注册码!
至于如果没有网卡,这一栏置零或空值,再用其它一些特征码进行加密,我想不可能就只
用一种特征码进行加密吧?
[8][8][8][8][8][8][8][8][8][8][8][8][8][8]
lqldir (2002-12-29 10:35)
就我所了解的都是用硬盘的物理序列号来加密的.
这种方法好.
所以,现在的问题了是大家能贴出一篇能获取硬盘物理序列号的源代码出来..
我有,但是只能获wd的硬盘的,maxtor的好像得不到....
tohappy (2003-4-27 8:14)
关注下列问题,一定对你有益:
http://delphibbs.com/delphibbs/dispq.asp?lid=1743719
http://delphibbs.com/delphibbs/dispq.asp?lid=1742072
http://delphibbs.com/delphibbs/dispq.asp?lid=1655569
http://delphibbs.com/delphibbs/dispq.asp?lid=1786356
3cs (2003-4-27 15:29)
得到硬盘物理号及简单的算法:我贴出,我都是用它,挺好的,哈哈!
unit ISDNUNIT;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TSrbIoControl=packed record
HeaderLength: ULONG;
Signature: Array[0..7] of char;
Timeout: ULONG;
ControlCode: ULONG;
ReturnCode: ULONG;
Length: ULONG;
END;
SRB_IO_CONTROL=TSrbIoControl;
PSrbIoControl=^TSrbIoControl;
TIDERegs=packed record
bFeaturesReg: Byte;
bSectorCountReg: Byte;
bSectorNumberReg: byte;
bCyllowReg: byte;
bCylhighreg:byte;
bDriveHeadReg: byte;
bCommandReg: byte;
bReserved: byte;
end;
IDEREGS=TIDERegs;
PIDERegs=^TIDERegs;
TSendCmdInParams=packed record
cBufferSize: DWORD;
irDriveRegs: TIDEREGS;
bDriveNumber:byte;
bReserved: Array[0..2] of byte;
dwReserved: Array[0..3] of DWORD;
bBUFFER: array[0..10] of byte;
end;
SENDCMDINPARAMS=TSendCmdInParams;
PSendcmdinparams=^Tsendcmdinparams;
TIdSector=packed record
wGenConfig: word;
wNumCyls: word;
wReserved: word;
wNumHeads: word;
wBytesPerTrack: word;
wBytesPerSector:word;
wSectorsPerTrack:word;
wVendorUnique: array[0..2] of word;
sSerialNumber: Array[0..19] of char;
wBufferType: word;
wBufferSize : word;
wECCSize: word;
sFirmwareRev: array[0..7] of char;
sModelNumber: array[0..39] of char;
wMorevendorUnique: word;
wDoubleWordIO: WORD;
wcapabilities:word;
wreservedL:word;
wPIOTiming:word;
wDMATiming:word;
wBS:WORD;
wNUMcurrentCYls:word;
wNUMcurrentHeads:word;
wNUMCurrentsectorsPerTRACK:WORD;
ulCurrentSectorCapacity:ULONG;
wMultSectorStuff:Word;
ulTotalAddressableSectors:ULONG;
wSingleWordDMA:Word;
wMultiwordDMA:word;
bReserved: Array[0..127] of byte;
end;
PIdSector=^TidSECTOR;
type
TForm1 = class(TForm)
Label1: TLabel;
Label2: TLabel;
procedure FormActivate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
// procedure ChangeByteorder(var data; Size:INTEGER);
// Function readhdserial:string;
// FUNCTION ENCRyPT(serial:string):string;
var
Form1: TForm1;
serial:string;
inputserial:string;
CONST
IDENTIFY_BUFFER_SIZE=512;
DataSize=sizeof(TSendCmdInParams)-1+IDENTIFY_BUFFER_SIZE;
IOCTL_SCSI_MINIPORT=$0004d008;
IOCTL_SCSI_MINIPORT_IDENTIFY=$001b0501;
IDE_ID_FUNCTION=$EC;
BufferSize=1280;
implementation
{$R *.DFM}
procedure ChangeByteorder(var data; size:integer);
var
ptr:PChar;
i:INTEGER;
C:CHAR;
BEGIN
ptr:=@data;
for i:=0 to (size shr 1)-1 do
begin
c:=ptr^;
ptr^:=(ptr+1)^;
(ptr+1)^:=c;
Inc(ptr,2);
end;
end;
function readhdserial:string;
var
hDevice:THandle;
cbBYTESReturned:DWORD;
pindata:PSendCmdInParams;
//pide:Pideregs;
pOutData:Pointer;
Buffer:Array[0..BufferSize-1] of Byte;
srbCONTROL:tSrbIoControl absolute Buffer;
begin
result:='';
Fillchar(Buffer,buffersize,#0);
hDevice:=CreateFile('//./Scsi0:',GENERIC_READ or GENERIC_WRITE,
FILE_SHARE_READ or FILE_SHARE_WRITE,nil,OPEN_EXISTING,0,0);
if hDevice=INVALID_HANDLE_VALUE then exit;
try
srbControl.HeaderLength:=sizeof(SRB_IO_CONTROL);
System.Move('SCSIDISK',srbControl.signature,8);
srbcontrol.timeout:=2;
srbcontrol.Length:=datasize;
srbcontrol.ControlCode:=IOCTL_SCSI_MINIPORT_IDENTIFY;
pInData:=PSendCmdInparams(pchar(@buffer)+sizeof(SRB_IO_CONTROL));
pOutData:=pInData;
with pInDATA^ DO
begin
cBuffersize:=IDENTIFY_BUFFER_SIZE;
bDriveNumber:=0;
// irDriveRegs:=0;
with irDriveRegs do
begin
bFeaturesreg:=1;
bsectorcountreg:=1;
bsectornumberreg:=1;
bcyllowreg:=0;
bcylhighreg:=0;
bdriveheadreg:=$A0;
bcommandreg:=IDE_ID_FUNCTION;
end;
end;
if not DeviceIoControl(hDevice,IOCTL_SCSI_MINIPORT,
@Buffer,BufferSize,@buffer,buffersize,cbbytesreturned,nil) then
exit;
with Pidsector(pchar(poutdata)+16)^ do
begin
changebyteorder(sSerialNUMber,sizeof(sserialnumber));
setstring(result,sserialnumber,sizeof(......
2005-5-23 10:10:38
发表评语»»»
2005-8-12 22:05:48 获取操作系统,CPU,硬盘等信息获取操作系统,CPU,硬盘等信息
http://www.delphibbs.com/keylife/iblog_show.asp?xid=16594