unit ScHaspEncrypt; interface uses Windows, SysUtils, Hasp4, Forms, Classes; function SimpleHaspCheck(var APortNum: Integer): Boolean; // 返回值大于0,成功;小于0,不成功 function LoadMemory: Integer; function CheckHaspTimes(AIsOnOpen: Boolean = False): Integer; function CheckHaspHours: Integer; function CheckHaspEdition: Integer; function CheckHaspAdditionEdition: Integer; function CheckHaspData: Integer; procedure LoadHaspReportOprs; procedure LoadHaspReportFuncs; procedure EncrpytFile(Source, Target: string); function OpenHaspDog: Integer; procedure SaveHaspDog; function HaspUserAuthorize(AAuthorize: array of Byte): Boolean; function HaspUserUpdateLock(AUpdateData: array of Byte): Boolean; implementation uses Math, CommonMessages, ConstMethodUnit, ScHaspPWD, CryptUtils, ScConfig, ScEncryptEditions, ScEncryptUnit; var MemHaspID: Integer = 0; DogBuf: array [0..HASP_MemorySizeInByte - 1] of Byte; function SimpleHaspCheck(var APortNum: Integer): Boolean; var P1, P2, P3, P4: Integer; begin Randomize; Result := False; // ZeroMemory(@DogBuf[0], HASP_MemorySizeInByte * SizeOf(Byte)); P1 := 0; P2 := 0; P3 := 0; P4 := 0; Hasp(LOCALHASP_ISHASP, 0, 0, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); if P1 = 0 then Exit; P1 := 0; P2 := 0; P3 := 0; P4 := 0; Hasp(LOCALHASP_HASPSTATUS, 0, 0, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); if P3 = 0 then Exit; APortNum := P3; Result := True; end; function LoadMemory: Integer; var P1, P2, P3, P4: Integer; I, PortNum: Integer; begin Randomize; Result := 0 - RandomRange(1, 1234); ZeroMemory(@DogBuf[0], HASP_MemorySizeInByte * SizeOf(Byte)); if not SimpleHaspCheck(PortNum) then Exit; P1 := 0; P2 := HASP_MemorySizeInByte div 2; P3 := 0; P4 := LongInt(@DogBuf[0]); Hasp(MEMOHASP_READBLOCK, 0, 0, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); if P3 <> 0 then Exit else Result := - Result; P1 := 0; P2 := 0; P3 := 0; P4 := 0; Hasp(MEMOHASP_HASPID, 0, 0, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); if (P3 = 0) then begin MemHaspID:= p2; MemHaspID:= MemHaspID shl 16; MemHaspID:= MemHaspID or p1; end; strHaspID := IntToHex(MemHaspID, 8); end; function CheckHaspTimes(AIsOnOpen: Boolean): Integer; var iCheckData: Integer; P1, P2, P3, P4: Integer; iSeedCode, PortNum: Integer; iTimes, iRunTimes: Integer; bFromMemory: Boolean; begin Result := CS_NoDog; if not SimpleHaspCheck(PortNum) then Exit; Randomize; iCheckData := RandomRange(1023, 1044); case iCheckData of 1023..1033: begin if LoadMemory < 0 then Exit; bFromMemory := True; end else bFromMemory := False; end; if bFromMemory then begin iTimes := DogBuf[11] shl 8 + DogBuf[10]; end else begin // 允许次数 P1 := 5; P2 := 0; P3 := 0; P4 := 0; Hasp(MEMOHASP_READMEMO, iSeedCode, PortNum, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); if P3 <> 0 then Exit; iTimes := P2; end; if iTimes = $FFFF then begin Result := CS_Success; Exit; end; bAuthorized := False; if bFromMemory then begin iRunTimes := DogBuf[13] shl 8 + DogBuf[12]; end else begin // 实际次数 P1 := 6; P2 := 0; P3 := 0; P4 := 0; Hasp(MEMOHASP_READMEMO, iSeedCode, PortNum, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); if P3 <> 0 then Exit; iRunTimes := P2; end; Activations := iRunTimes; if AIsOnOpen then begin if iRunTimes >= iTimes then Result := CS_NeedAuthorize else Result := CS_WantAuthorize; end else begin if iRunTimes > iTimes then Result := CS_NeedAuthorize else Result := CS_WantAuthorize; end; end; function CheckHaspHours: Integer; var iCheckData: Integer; P1, P2, P3, P4: Integer; iSeedCode, PortNum: Integer; iHours, iRunHours: Integer; bFromMemory: Boolean; begin Result := CS_Error; if not SimpleHaspCheck(PortNum) then Exit; Randomize; iCheckData := RandomRange(5000, 5244); case iCheckData of 5103..5220: begin if LoadMemory < 0 then Exit; bFromMemory := True; end else bFromMemory := False; end; // 允许小时 if bFromMemory then begin iHours := (DogBuf[03] shl 8 + DogBuf[02]) shl 16; end else begin P1 := 1; P2 := 0; P3 := 0; P4 := 0; Hasp(MEMOHASP_READMEMO, iSeedCode, PortNum, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); if P3 <> 0 then Exit; iHours := P2 shl 16; end; if bFromMemory then begin iHours := iHours + DogBuf[05] shl 8 + DogBuf[04]; end else begin P1 := 2; P2 := 0; P3 := 0; P4 := 0; Hasp(MEMOHASP_READMEMO, iSeedCode, PortNum, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); if P3 <> 0 then Exit; iHours := iHours + P2; end; if iHours = -1 then begin Result := CS_Success; Exit; end; bAuthorized := False; // 实际小时 if bFromMemory then begin iRunHours := (DogBuf[07] shl 8 + DogBuf[06]) shl 16; end else begin P1 := 3; P2 := 0; P3 := 0; P4 := 0; Hasp(MEMOHASP_READMEMO, iSeedCode, PortNum, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); if P3 <> 0 then Exit; iRunHours := P2 shl 16; end; if bFromMemory then begin iRunHours := iRunHours + DogBuf[9] shl 8 + DogBuf[8]; end else begin P1 := 4; P2 := 0; P3 := 0; P4 := 0; Hasp(MEMOHASP_READMEMO, iSeedCode, PortNum, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); if P3 <> 0 then Exit; iRunHours := iRunHours + P2; end; LastTime := iRunHours; if iRunHours > iHours then Result := CS_NeedAuthorize else Result := CS_WantAuthorize; end; function CheckHaspAdditionEdition: Integer; var P1, P2, P3, P4: Integer; iSeedCode, PortNum: Integer; iEdition: Integer; arrData: array [0..3] of Byte; begin Result := CS_NoDog; if not SimpleHaspCheck(PortNum) then Exit; ZeroMemory(@arrData[0], Length(arrData)); // 附加版本 P1 := $16; P2 := Length(arrData) div 2; P3 := 0; P4 := LongInt(@arrData[0]); Hasp(MEMOHASP_READBLOCK, iSeedCode, PortNum, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); if P3 <> 0 then Exit; {$IFDEF _ScBills} if arrData[0] = $08 then {$ENDIF} {$IFDEF _ScBudget} {$IFDEF _ScEstimate} if arrData[2] = $24 then {$ELSE} if arrData[1] = $16 then {$ENDIF} {$ENDIF} Result := CS_Success else Result := CS_NeedUpdate; end; function CheckHaspEdition: Integer; var iCheckData: Integer; P1, P2, P3, P4: Integer; iSeedCode, PortNum: Integer; iEdition: Integer; begin Result := CS_NoDog; if not SimpleHaspCheck(PortNum) then Exit; Randomize; iCheckData := RandomRange(256, 357); case iCheckData of 310..314, 260..271: begin Result := CS_Ignore; Exit; end; end; // 版本 P1 := 0; P2 := 0; P3 := 0; P4 := 0; Hasp(MEMOHASP_READMEMO, iSeedCode, PortNum, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); if P3 <> 0 then Exit; iEdition := P2; DogEdition := iEdition; if CheckEncryptEdition(iEdition) then (* if iEdition in {$IFDEF _ScPersonal} [164] {$ENDIF} {$IFDEF _ScBillsForArch} [178] {$ELSE} {$IFDEF _ScBills} {$IFDEF _ScGanSu} [81] {$ELSE} [161, 162] {$ENDIF} {$ENDIF} {$IFDEF _ScBudget} {$IFDEF _ScGanSu} [81, 82] {$ELSE} [161, 163] {$ENDIF} {$ENDIF} {$ENDIF} then*) Result := CS_Success else Result := CS_DogTypeError; end; function CheckHaspData: Integer; var iCheckData, PortNum, iOutputLength: Integer; arrInput1: array [0..11] of Byte; arrInput2: array [0..11] of Byte; arrOutput1: array [0..3] of Byte; arrOutput2: array [0..3] of Byte; strHaspIDHex, strTemp: string; P1, P2, P3, P4: Integer; I: Integer; begin Result := CS_NoDog; strHaspIDHex := ''; if not SimpleHaspCheck(PortNum) then Exit; { Randomize; iCheckData := RandomRange(11000, 11050); case iCheckData of 11011..11040: begin if LoadMemory < 0 then Exit; end; end;} if LoadMemory < 0 then Exit; // 加密校验码2 CopyMemory(@arrInput1[0], @DogBuf[$10], Length(arrInput2) * SizeOf(Byte)); Decrypt_BlowFish(EncryptKey, arrInput1, Length(arrInput1), arrOutput1, iOutputLength); for I := 0 to 3 do strHaspIDHex := strHaspIDHex + IntToHex(arrOutput1[I], 1); // 加密校验码2 CopyMemory(@arrInput2[0], @DogBuf[$1C], Length(arrInput2) * SizeOf(Byte)); Decrypt_BlowFish(EncryptKey, arrInput2, Length(arrInput2), arrOutput2, iOutputLength); for I := 0 to 3 do strHaspIDHex := strHaspIDHex + IntToHex(arrOutput2[I], 1); if MemHaspID = strToInt('$' + strHaspIDHex) then Result := CS_Success else Result := CS_VerifyError; end; procedure LoadHaspReportOprs; var P1, P2, P3, P4, iLength: Integer; fsFile: TFileStream; Buf: array [0..65535] of Byte; msFile: TMemoryStream; strOprs: string; PortNum: Integer; begin if not SimpleHaspCheck(PortNum) then Exit; { fsFile := TFileStream.Create(ConfigInfo.DataFilePath + 'HerFio.dat', fmOpenRead); try iLength := fsFile.Size; ZeroMemory(@Buf[0], 65535); fsFile.Read(Buf, iLength); finally fsFile.Free; end; P1 := 0; P2 := iLength; P3 := 0; P4 := LongInt(@Buf[0]); Hasp(LOCALHASP_DECODEDATA, 0, PortNum, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); SetString(strOprs, PChar(@Buf[0]), iLength); GetReportOprList.Delimiter := ','; GetReportOprList.DelimitedText := strOprs; } { msFile := TMemoryStream.Create; try msFile.Write(Buf, iLength); GetReportOprList.LoadFromStream(msFile); finally msFile.Free; end;} end; procedure LoadHaspReportFuncs; var P1, P2, P3, P4, iLength: Integer; fsFile: TFileStream; Buf: array [0..65535] of Byte; msFile: TMemoryStream; strOprs: string; PortNum: Integer; begin if not SimpleHaspCheck(PortNum) then Exit; { fsFile := TFileStream.Create(ConfigInfo.DataFilePath + 'HerFif.dat', fmOpenRead); try iLength := fsFile.Size; ZeroMemory(@Buf[0], 65535); fsFile.Read(Buf, iLength); finally fsFile.Free; end; P1 := 0; P2 := iLength; P3 := 0; P4 := LongInt(@Buf[0]); Hasp(LOCALHASP_DECODEDATA, 0, PortNum, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); SetString(strOprs, PChar(@Buf[0]), iLength); GetReportFuncList.Delimiter := ','; GetReportFuncList.DelimitedText := strOprs; } { msFile := TMemoryStream.Create; try msFile.Write(Buf, iLength); GetReportFuncList.LoadFromStream(msFile); finally msFile.Free; end;} end; procedure EncrpytFile(Source, Target: string); var P1, P2, P3, P4, iLength: Integer; fsFile: TFileStream; Buf: array [0..65535] of Byte; msFile: TFileStream; begin fsFile := TFileStream.Create(Source, fmOpenRead); try iLength := fsFile.Size; ZeroMemory(@Buf[0], 65535); fsFile.Read(Buf, iLength); finally fsFile.Free; end; P1 := 0; P2 := iLength; P3 := 0; P4 := LongInt(@Buf[0]); Hasp(LOCALHASP_ENCODEDATA, 0, 0, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); msFile := TFileStream.Create(Target, fmCreate); try msFile.Write(Buf, iLength); //GetReportOprList.LoadFromStream(msFile); finally msFile.Free; end; end; function OpenHaspDog: Integer; var P1, P2, P3, P4: Integer; PortNum: Integer; begin Result := CS_Success; P1:= 6; { The address to which the data word will be written } P2:= Activations + 1; { The value to be written } P3:= 0; { unused } P4:= 0; { unused } Hasp(MEMOHASP_WRITEMEMO, 0, PortNum, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); end; procedure SaveHaspDog; var iSeedCode, P1, P2, P3, P4, PortNum: Integer; iLastTime: LongWord; iRunHours: LongWord; begin { RunTime := GetTickCount div 1000; if RunTime < StartTime then begin iLastTime := High(LongWord) div 1000 + RunTime - StartTime; end else iLastTime := RunTime - StartTime;} RunTime := GetTickCount; if (RunTime - StartTime < 0) and (LastTime < 720000000) then begin iLastTime := High(LongWord) - StartTime + RunTime; end else iLastTime := RunTime - StartTime; // 先读出运行总时间 P1 := 3; P2 := 0; P3 := 0; P4 := 0; Hasp(MEMOHASP_READMEMO, iSeedCode, PortNum, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); if P3 <> 0 then iRunHours := P2 shl 16; P1 := 4; P2 := 0; P3 := 0; P4 := 0; Hasp(MEMOHASP_READMEMO, iSeedCode, PortNum, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); if P3 <> 0 then iRunHours := iRunHours + P2; iLastTime := iLastTime + iRunHours; // 再加上本次运行时间 P1 := 3; { The address to which the data word will be written } P2 := iLastTime shr 16; { The value to be written } P3 := 0; { unused } P4 := 0; { unused } Hasp(MEMOHASP_WRITEMEMO, 0, PortNum, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); P1 := 4; { The address to which the data word will be written } P2 := iLastTime and $0000FFFF; { The value to be written } P3 := 0; { unused } P4 := 0; { unused } Hasp(MEMOHASP_WRITEMEMO, 0, PortNum, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); end; function HaspUserAuthorize(AAuthorize: array of Byte): Boolean; var iOutputLength: Integer; arrInput1: array [0..11] of Byte; arrOutput1: array [0..3] of Byte; arrInput2: array [0..11] of Byte; arrOutput2: array [0..3] of Byte; I, PortNum: Integer; P1, P2, P3, P4: Integer; arrEncryptKey: array [0..Length_AuthorizeFile - 1] of Byte; arrKey: array [0..Length_AuthorizeData - 1] of Byte; bRightKey: Boolean; strHaspIDHex: string[8]; pFile: PAuthorizeFile; begin Result := False; CopyMemory(@arrEncryptKey[0], @AAuthorize[0], Length_AuthorizeFile * SizeOf(Byte)); Decrypt_BlowFish(AuthorizeKey, arrEncryptKey, Length(arrEncryptKey), arrKey, iOutputLength); New(pFile); try CopyMemory(pFile, @arrKey[0], Length_AuthorizeData * SizeOf(Byte)); if not SameText(pFile^.Head, HASP_AuthorizeFileHead) then Exit; CopyMemory(@arrInput1[0], @(pFile^.Key1[0]), Length(arrInput1) * SizeOf(Byte)); CopyMemory(@arrInput2[0], @(pFile^.Key2[0]), Length(arrInput2) * SizeOf(Byte)); Decrypt_BlowFish(AuthorizeKey, arrInput1, Length(arrInput1), arrOutput1, iOutputLength); strHaspIDHex := ''; for I := 0 to 3 do strHaspIDHex := strHaspIDHex + IntToHex(arrOutput1[I], 1); Decrypt_BlowFish(AuthorizeKey, arrInput2, Length(arrInput2), arrOutput2, iOutputLength); for I := 0 to 3 do strHaspIDHex := strHaspIDHex + IntToHex(arrOutput2[I], 1); bRightKey := MemHaspID = strToInt('$' + strHaspIDHex); if bRightKey then begin SimpleHaspCheck(PortNum); // 版本 P1:= 0; { The address to which the data word will be written } P2:= pFile^.Edition; { The value to be written } P3:= 0; { unused } P4:= 0; { unused } Hasp(MEMOHASP_WRITEMEMO, 0, PortNum, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); if P3 <> 0 then begin bAuthorized := False; Exit; end; // 允许时间 P1:= 1; { The address to which the data word will be written } P2:= pFile^.Hours shr 16; { The value to be written } P3:= 0; { unused } P4:= 0; { unused } Hasp(MEMOHASP_WRITEMEMO, 0, PortNum, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); if P3 <> 0 then begin bAuthorized := False; Exit; end; P1:= 2; { The address to which the data word will be written } P2:= pFile^.Hours and $0000FFFF; { The value to be written } P3:= 0; { unused } P4:= 0; { unused } Hasp(MEMOHASP_WRITEMEMO, 0, PortNum, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); if P3 <> 0 then begin bAuthorized := False; Exit; end; // 允许次数 P1:= 5; { The address to which the data word will be written } P2:= pFile^.Times; { The value to be written } P3:= 0; { unused } P4:= 0; { unused } Hasp(MEMOHASP_WRITEMEMO, 0, PortNum, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); if P3 <> 0 then begin bAuthorized := False; Exit; end; bAuthorized := True; Result := True; end; finally Dispose(pFile); end; end; function HaspUserUpdateLock(AUpdateData: array of Byte): Boolean; var arrSN: array [0..7] of Byte; aEncryptKey: array [0..19] of Byte; aKey: array [0..15] of Byte; strS4SNDC, strS4SN: string[8]; iFileSize, iDataSize, iSNSize: Integer; aData: array [0..15] of Byte; aUpdate: array [0..3] of Byte; I: Integer; iMemHaspID: Integer; P1, P2, P3, P4: Integer; iSeedCode, iPortNum: Integer; begin Result := False; iDataSize := 16; iSNSize := 8; iFileSize := iDataSize + 8; if iFileSize mod 8 <> 0 then iFileSize := 8 * (iFileSize div 8 + 1); ZeroMemory(@aEncryptKey[0], Length(aEncryptKey)); ZeroMemory(@aKey[0], Length(aKey)); ZeroMemory(@aData[0], Length(aData)); ZeroMemory(@aUpdate[0], Length(aUpdate)); CopyMemory(@aEncryptKey[0], @AUpdateData[0], iFileSize); Decrypt_BlowFish(AuthorizeKey, aEncryptKey, iFileSize, aKey, iFileSize); CopyMemory(@aData[0], @aKey[0], Length(aData)); CopyMemory(@arrSN[0], @aData[0], iSNSize); aUpdate[0] := aData[9]; aUpdate[1] := aData[12]; aUpdate[2] := aData[14]; strS4SNDC := ''; for I := Low(arrSN) to High(arrSN) do strS4SNDC := strS4SNDC + IntToHex(arrSN[I], 1); // 读出序列号 P1 := 0; P2 := 0; P3 := 0; P4 := 0; Hasp(MEMOHASP_HASPID, 0, 0, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); if (P3 = 0) then begin iMemHaspID:= p2; iMemHaspID:= iMemHaspID shl 16; iMemHaspID:= iMemHaspID or p1; end else Exit; strS4SN := IntToHex(iMemHaspID, 8); // 如果验证序列号相同,设置允许升级 if SameText(strS4SN, strS4SNDC) then begin // 版本 P1 := $16; P2 := Length(aUpdate) div 2; P3 := 0; P4 := LongInt(@aUpdate[0]); Hasp(MEMOHASP_WRITEBLOCK, 0, 0, GetHaspPass1, GetHaspPass2, P1, P2, P3, P4); if P3 <> 0 then Exit; end else Exit; Result := True; end; end.