龙空技术网

软件开发中,如何正确获取硬盘序列号并有效实现软件注册认证?

流逝在键盘下的记忆 654

前言:

此刻各位老铁们对“硬盘序列号示例”大约比较关心,你们都需要学习一些“硬盘序列号示例”的相关资讯。那么小编同时在网摘上网罗了一些有关“硬盘序列号示例””的相关知识,希望大家能喜欢,咱们快快来学习一下吧!

现有软件加密基本都是采用各种硬件系列号作为加密依据,实现的是一机一码制,在采用硬件系列号作为加密依据之前,先要了解下各种硬件系列号的情况。这样有利于选择软件加密依据,防止注册码可以在多台计算机上使用。

获取硬盘系列号

硬盘系列号是生产厂家在硬盘出厂之前就写入到硬盘中不可以修改的系列号,也就是所谓的出厂系列号或是物理系列号,该系列号一旦写入就不可以进行修改,并且是唯一的,但有些硬盘厂家生产的硬盘没有这个系列号,也就是说系列号为空。硬盘出厂系列号与硬盘分区卷的系列号的区别在于:卷的系列号可以修改,并且只要一重新格式化,该系列号就会改变;而硬盘出厂系列号是不可修改的,格式化以后系列号不会被改变。

如果采用分区卷的系列号作为加密依据,其一,只要购买一个注册码,其他的计算机只要修改卷的系列号就可以成为软件的正式用户;其二,如果用户重新格式化过分区,那么就要重新给用户发送新的系列号,因为没有确切的证据,也不知道用户是否真的格式化过分区还是使用另外的计算机的分区系列号来获取注册码。所以为了避免出现一码多机可用和引起不必要的麻烦,建议在实际加密过程中不要使用硬盘卷的分区系列号作为加密依据,而应该采用硬盘出厂系列号作为软件的加密依据。

虽然不使用卷的系列号作为加密依据,但这里也来看看怎么获取磁盘分区卷的系列号?其实很简单,只要调用 API函数 GetVolumeInformation 就可以得到磁盘分区卷的系列号。 API 函数 GetVolumelnformation 在 MSDN 中的函数原型如下:

 BOOL GetVolumelnformation( LPCTSTR lpRootPathName, //指向文件系统根的路径字符串 LPTSTR IpVolumeNameBuffer, //接收返回的卷名的缓冲区 DWORD nVolumeNameSize, //上述缓冲区的长度 LPDWORD pVolumeSerialNumber, //接收卷序列号的整数变量的地址 LPDWORD pMaimumComponenilength, //接收卷上最大文件路径长度的整数变量的地址 LPDWORD IpFileSystemFlagx, 1/接收卷文件系统标志的整数变量的地址         LPTSTR ipFilSystemNameBufer, //接收返回的卷的文件系统名的缓冲区0 DWORD nFileSystemNameSsize //上述缓冲区的长度 ) 示例代码如下://获取指定磁盘分区的卷系列号 function GetDiskvo1 (Driver:String): DWORD;  var volumeSerialNumber : DWORD;MaximumComponentLength : DWORD;FileSystemFlags :DWORD; beqin if Driver length(Driver)] =':' thenDriver :=Driver + ‘\’GetVolumeInformation(PChar (Driver), nil,0,@VolumeSerialNumber, MaximumComponentlength, FileSystemFlags,  nil,0); Resul t:= (VolumeSeria1Number); end; procedure TForm1.Button1click(sender; Tobject);     begin Label1.caption:-IntToHex(GetDiskVo1('c:V9),8);end;

获取硬盘的出厂系列号还要考虑到硬盘的接口类型,在这里只介绍 IDE 接口的和 SCSI 接口的。首先看看要获取硬盘系列号所需要的几个 API 函数:

 BOOL DeviceloControl(HANDLE hDevice,   //设备句柄DWORD dwloControlCode, //控制代码LPVOID IpInBufer, //指向包含操作所需的数据的缓冲区指针DWORD nInBufferSize, //lpInBuffer 参数指向的缓冲区的大小LPVOID IpOutBufer, //指向用来接收输出数据的缓冲区DWORD nOuBuferSize, //指向用来接收输出数据的缓冲区 LPDWORD ipBytesRethurned //指向变量用于返回缓冲区数据的数量 LPOVERLAPPED IpOverlaped //指向 OVERLAPPED 结构);HANDLE CreateFile( LPCTSTR IpFileName, //指向文件名 DWORD dwDesiredAccess, //访问模式(读或写) DWORD dwShareMode, //共享模式 LPSECURITY_ATTRIBUTES ipSecurityAttributes,//指向安全属性 DWORD dwCreationDisposition, //如何创建文件 DWORD dwFlagsAndAtributes, //文件属性 HANDLE hTemplateFile //文件模板句柄
获取硬盘出厂系列号的完整示例代码如下: unit DiskserialUnit; interface uses Windows; SysUtils; function GetHddserial: string; implementation function GetIdeDiskserialNumber: String;type TSrbIoControl = packed recordHeaderLength :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; TsendcndInParams = packed record CBuffersize : DWORD; irDriveRegs:TIDERegs;bdriveNumber : Byte;bReserved:Arraylo..2] of byte;dwReserved:Array10..31 of DWORD;bBuffer : Array[0..0] 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 :Array10..2] of word; sSerialNumber : Arraylo..19] of Char; WBufferType  :Word;wBuffersize :Word; wEccsize  :Word;sFirmwareRev :Array[0..7] of char;sMode1Number : Array[0..39] of Char;WMoreVendorUnique :Word;wDoublewordIo:Word; wcapabilities :Word; wReserved1 : Word;   wPIOTiming:word;WDMATiming:word; wBS: Word1; WNumcurrentcyla:Word; wNumcurrentHeads:Word;wNumcurrentSectorsPerTrack:Word; ulCurrentSectorCapacity  : ULONG;ulTotalAddressableSectors:ULONG:wSingleWordDMA:Word;sMultiWordDMA:Word;bReserved:Array[0..127] of byte;end;PIdsector = ^TIdSector;const IDEID_FUNCTION -=SECI IDENTIFY BUFFER SIZE =512; DFP RECEIVE DRIVE DATA  =$0007c088: IOCTL SCSI MINIPORT =$0004d008; IOCTL SCSI MINIPORT_IDENTIFY =$001b0501; Datasito =sizeof(TSendomdInParams)-1+IDENTIFY BUFFER_SIZE; ButfferSize=Sizeof(SRB_IO_CONTROL)+DataSize;W9xbuffersize=IOENTIFYBUFER_SIZE+16; var hDevice : THandler cbbytenReturned : DWORD; pInData: PSendCmdInParams; poutData : Pointer; // PSendCndInParama;Bufter : Array[0..Buffersize-1] of Byte;srbcontrol : Tsrblocontrol absolute buffers; procedure Changonyteorder( var patat size t Integer ) varptr : PChar; i :Integer; c : Char; begin//判断操作系统//获取SCSI接口句柄 end;function ScsiHddSerialNumber:String;{$ALIGN ON}Typeend;beginend;function GetHddSerial:stringvar  NumTry:Byte;FinalStr:String;beginNumTry := 1;Repeat  Case NumTry of1:FinalStr:= ScsiHddSerialNumber;2:FinalStr:= GetIdeDiskSerialNumber;3:FinalStr:=’Error’;End;Inc(NumTry);Until(FinalStr <> ‘’) or (NumTry > 4);Result := FinalStr;end;end.

在实际加密过程中,不建议使用CPU序列号和网卡的MAC地址作为加密依据,因为相同型号的CPU的序列号相同,并且,MAC地址可以更改,以硬盘出厂序列号作为加密依据是比较好的选择。

标签: #硬盘序列号示例 #硬盘序列号百度百科