現(xiàn)有軟件加密基本都是采用各種硬件系列號作為加密依據(jù),實現(xiàn)的是一機一碼制,在采用硬件系列號作為加密依據(jù)之前,先要了解下各種硬件系列號的情況。這樣有利于選擇軟件加密依據(jù),防止注冊碼可以在多臺計算機上使用。

獲取硬盤系列號

電腦如何查硬盤序列號?查詢查硬盤序列號和mac地址的方法

硬盤系列號是生產(chǎn)廠家在硬盤出廠之前就寫入到硬盤中不可以修改的系列號,也就是所謂的出廠系列號或是物理系列號,該系列號一旦寫入就不可以進行修改,并且是唯一的,但有些硬盤廠家生產(chǎn)的硬盤沒有這個系列號,也就是說系列號為空。硬盤出廠系列號與硬盤分區(qū)卷的系列號的區(qū)別在于:卷的系列號可以修改,并且只要一重新格式化,該系列號就會改變;而硬盤出廠系列號是不可修改的,格式化以后系列號不會被改變。

如果采用分區(qū)卷的系列號作為加密依據(jù),其一,只要購買一個注冊碼,其他的計算機只要修改卷的系列號就可以成為軟件的正式用戶;其二,如果用戶重新格式化過分區(qū),那么就要重新給用戶發(fā)送新的系列號,因為沒有確切的證據(jù),也不知道用戶是否真的格式化過分區(qū)還是使用另外的計算機的分區(qū)系列號來獲取注冊碼。所以為了避免出現(xiàn)一碼多機可用和引起不必要的麻煩,建議在實際加密過程中不要使用硬盤卷的分區(qū)系列號作為加密依據(jù),而應該采用硬盤出廠系列號作為軟件的加密依據(jù)。

雖然不使用卷的系列號作為加密依據(jù),但這里也來看看怎么獲取磁盤分區(qū)卷的系列號?其實很簡單,只要調(diào)用 API函數(shù) GetVolumeInformation 就可以得到磁盤分區(qū)卷的系列號。 API 函數(shù) GetVolumelnformation 在 MSDN 中的函數(shù)原型如下:

 BOOL GetVolumelnformation( LPCTSTR lpRootPathName, //指向文件系統(tǒng)根的路徑字符串 LPTSTR IpVolumeNameBuffer, //接收返回的卷名的緩沖區(qū) DWORD nVolumeNameSize, //上述緩沖區(qū)的長度 LPDWORD pVolumeSerialNumber, //接收卷序列號的整數(shù)變量的地址 LPDWORD pMaimumComponenilength, //接收卷上最大文件路徑長度的整數(shù)變量的地址 LPDWORD IpFileSystemFlagx, 1/接收卷文件系統(tǒng)標志的整數(shù)變量的地址         LPTSTR ipFilSystemNameBufer, //接收返回的卷的文件系統(tǒng)名的緩沖區(qū)0 DWORD nFileSystemNameSsize //上述緩沖區(qū)的長度 ) 示例代碼如下://獲取指定磁盤分區(qū)的卷系列號 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 函數(shù):

 BOOL DeviceloControl(HANDLE hDevice,   //設備句柄DWORD dwloControlCode, //控制代碼LPVOID IpInBufer, //指向包含操作所需的數(shù)據(jù)的緩沖區(qū)指針DWORD nInBufferSize, //lpInBuffer 參數(shù)指向的緩沖區(qū)的大小LPVOID IpOutBufer, //指向用來接收輸出數(shù)據(jù)的緩沖區(qū)DWORD nOuBuferSize, //指向用來接收輸出數(shù)據(jù)的緩沖區(qū) LPDWORD ipBytesRethurned //指向變量用于返回緩沖區(qū)數(shù)據(jù)的數(shù)量 LPOVERLAPPED IpOverlaped //指向 OVERLAPPED 結構);HANDLE CreateFile( LPCTSTR IpFileName, //指向文件名 DWORD dwDesiredAccess, //訪問模式(讀或?qū)? DWORD dwShareMode, //共享模式 LPSECURITY_ATTRIBUTES ipSecurityAttributes,//指向安全屬性 DWORD dwCreationDisposition, //如何創(chuàng)建文件 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//判斷操作系統(tǒng)//獲取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序列號和網(wǎng)卡的MAC地址作為加密依據(jù),因為相同型號的CPU的序列號相同,并且,MAC地址可以更改,以硬盤出廠序列號作為加密依據(jù)是比較好的選擇。