731 lines
25 KiB
ObjectPascal
731 lines
25 KiB
ObjectPascal
(* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is TurboPower OnGuard
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* TurboPower Software
|
|
*
|
|
* Portions created by the Initial Developer are Copyright (C) 1996-2002
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Andrew Haines andrew@haines.name {AH.01}
|
|
* conversion to CLX {AH.01}
|
|
* December 30, 2003 {AH.01}
|
|
*
|
|
*
|
|
* Boguslaw Brandys brandys@o2.pl
|
|
* conversion to Free Pascal
|
|
* June 04, 2006
|
|
*
|
|
*
|
|
* ***** END LICENSE BLOCK ***** *)
|
|
{*********************************************************}
|
|
{* OGPROEXE.PAS 1.13 *}
|
|
{* Copyright (c) 1996-02 TurboPower Software Co *}
|
|
{* All rights reserved. *}
|
|
{*********************************************************}
|
|
|
|
|
|
|
|
{$B-} {Complete Boolean Evaluation}
|
|
{$I+} {Input/Output-Checking}
|
|
{$P+} {Open Parameters}
|
|
{$T-} {Typed @ Operator}
|
|
|
|
|
|
{$mode delphi}{$H+}
|
|
{$ASMMODE INTEL}
|
|
|
|
|
|
unit ogproexe; {AH.01}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF MSWINDOWS} Windows, {$ENDIF} {AH.01}
|
|
{$IFDEF LINUX} BaseUnix, {$ENDIF} {AH.01}
|
|
Classes,
|
|
{$IFDEF MSWINDOWS} MMSystem, {$ENDIF} {AH.01}
|
|
SysUtils,
|
|
ogutil; {AH.01}
|
|
|
|
type
|
|
{exe signature record}
|
|
PSignatureRec = ^TSignatureRec;
|
|
TSignatureRec = packed record
|
|
Sig1 : DWord; {!!.07}
|
|
Sig2 : DWord; {!!.07}
|
|
Sig3 : DWord; {!!.07}
|
|
Offset : DWord; {!!.07}
|
|
Size : DWord; {!!.07}
|
|
CRC : DWord; {!!.07}
|
|
Sig4 : DWord; {!!.07}
|
|
Sig5 : DWord; {!!.07}
|
|
Sig6 : DWord; {!!.07}
|
|
end;
|
|
|
|
TExeStatus = (
|
|
exeSuccess, {no error}
|
|
exeSizeError, {the file size has changed}
|
|
exeIntegrityError, {CRC does not match}
|
|
exeNotStamped, {the exe has not been stamped}
|
|
exeAccessDenied {share violation} {!!.05}
|
|
);
|
|
|
|
type
|
|
TCheckedExeEvent =
|
|
procedure(Sender : TObject; Status : TExeStatus)
|
|
of object;
|
|
|
|
TOgProtectExe = class(TComponent)
|
|
protected {private}
|
|
{property variables}
|
|
FAutoCheck : Boolean;
|
|
FCheckSize : Boolean;
|
|
|
|
{event variables}
|
|
FOnChecked : TCheckedExeEvent;
|
|
|
|
{property methods}
|
|
function GetAbout : string; {!!.08}
|
|
procedure SetAbout(const Value : string); {!!.08}
|
|
|
|
protected
|
|
procedure DoOnChecked(Status : TExeStatus);
|
|
dynamic;
|
|
procedure Loaded;
|
|
override;
|
|
|
|
public
|
|
constructor Create(AOwner : TComponent);
|
|
override;
|
|
function CheckExe(Report : Boolean) : TExeStatus;
|
|
{-test the exe file for tampering}
|
|
function StampExe(const FileName : string ; EraseMarker : Boolean) : Boolean;
|
|
{-stamp exe with crc and file size. optionally erase search markers}
|
|
function UnStampExe(const FileName : string) : Boolean;
|
|
{-writes uninitialized signature record. marker must not have been erased}
|
|
|
|
published
|
|
{properties}
|
|
property AutoCheck : Boolean
|
|
read FAutoCheck
|
|
write FAutoCheck
|
|
default DefAutoCheck;
|
|
|
|
property CheckSize : Boolean
|
|
read FCheckSize
|
|
write FCheckSize
|
|
default DefCheckSize;
|
|
|
|
property About : string {!!.08}
|
|
read GetAbout {!!.08}
|
|
write SetAbout {!!.08}
|
|
stored False;
|
|
|
|
{events}
|
|
property OnChecked : TCheckedExeEvent
|
|
read FOnChecked
|
|
write FOnChecked;
|
|
end;
|
|
|
|
|
|
function IsExeTampered(CheckSize : Boolean) : TExeStatus;
|
|
{-return one of the possible TExeResult states}
|
|
function ProtectExe(const FileName : string ; EraseMarker : Boolean) : Boolean;
|
|
{-stamp exe with crc and file size. optionally erase search markers}
|
|
function UnprotectExe(const FileName : string) : Boolean;
|
|
{-writes uninitialized signature record. marker must not have been erased}
|
|
|
|
{checksum/CRC routines}
|
|
procedure UpdateChecksum(var Sum : LongInt; const Buf; BufSize : LongInt);
|
|
{$IFDEF Win32}
|
|
function FileCRC32(const FileName : string) : DWord; {!!.07}
|
|
{$ELSE}
|
|
function FileCRC32(const FileName : string) : DWord;//LongInt;
|
|
{$ENDIF}
|
|
procedure UpdateCRC32(var CRC : DWord; const Buf; BufSize : LongInt); {!!.07}
|
|
|
|
|
|
implementation
|
|
|
|
|
|
{signature = '!~~@CRC32@~~' used before and after}
|
|
const
|
|
StoredSignature : TSignatureRec = (
|
|
Sig1:$407E7E21; Sig2:$33435243; Sig3:$7E7E4032;
|
|
Offset:1; Size:2; CRC:3;
|
|
Sig4:$407E7E21; Sig5:$33435243; Sig6:$7E7E4032);
|
|
|
|
{CRC32 lookup table}
|
|
const
|
|
CRC32Table: array[0..255] of DWord = ( {!!.07}
|
|
$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);
|
|
|
|
|
|
{*** TOgProtectExe ***}
|
|
|
|
constructor TOgProtectExe.Create(AOwner : TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
|
|
FAutoCheck := DefAutoCheck;
|
|
FCheckSize := DefCheckSize;
|
|
end;
|
|
|
|
function TOgProtectExe.CheckExe(Report : Boolean) : TExeStatus;
|
|
begin
|
|
Result := IsExeTampered(FCheckSize);
|
|
|
|
if Report then
|
|
DoOnChecked(Result);
|
|
end;
|
|
|
|
procedure TOgProtectExe.DoOnChecked(Status : TExeStatus);
|
|
begin
|
|
if Assigned(FOnChecked) then
|
|
FOnChecked(Self, Status);
|
|
end;
|
|
|
|
function TOgProtectExe.GetAbout : string; {!!.08}
|
|
begin
|
|
Result := OgVersionStr;
|
|
end;
|
|
|
|
procedure TOgProtectExe.Loaded;
|
|
begin
|
|
inherited Loaded;
|
|
|
|
if FAutoCheck then
|
|
CheckExe(True);
|
|
end;
|
|
|
|
procedure TOgProtectExe.SetAbout(const Value : string); {!!.08}
|
|
begin
|
|
end;
|
|
|
|
function TOgProtectExe.StampExe(const FileName : string ; EraseMarker : Boolean) : Boolean;
|
|
begin
|
|
Result := ProtectExe(FileName, EraseMarker);
|
|
end;
|
|
|
|
function TOgProtectExe.UnStampExe(const FileName : string) : Boolean;
|
|
begin
|
|
Result := UnprotectExe(FileName);
|
|
end;
|
|
|
|
|
|
{$IFDEF Win32}
|
|
function IsExeTampered(CheckSize : Boolean) : TExeStatus;
|
|
{-return one of the possible TExeResult states}
|
|
var
|
|
Fh : THandle;
|
|
FileMap : THandle;
|
|
Memory : PByteArray;
|
|
CRC : DWord; {!!.07}
|
|
Buf : array [0..MAX_PATH - 1] of AnsiChar;
|
|
begin
|
|
Result := exeIntegrityError;
|
|
|
|
{check if exe has been stamped}
|
|
if (StoredSignature.Offset = 1) and (StoredSignature.Size = 2) and
|
|
(StoredSignature.CRC = 3) then begin
|
|
Result := exeNotStamped;
|
|
Exit;
|
|
end;
|
|
|
|
Windows.GetModuleFileName(HInstance, Buf, SizeOf(Buf));
|
|
Fh := CreateFile(Buf, GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE,
|
|
nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
|
if (Fh <> INVALID_HANDLE_VALUE) then begin {!!.07}
|
|
if CheckSize and (StoredSignature.Size <> Windows.GetFileSize(Fh, nil)) then
|
|
Result := exeSizeError
|
|
else begin
|
|
FileMap := CreateFileMapping(Fh, nil, PAGE_READONLY, 0, 0, nil);
|
|
if (FileMap <> 0) then begin
|
|
Memory := MapViewOfFile(FileMap, FILE_MAP_READ, 0, 0, 0);
|
|
if (Memory <> nil) then begin
|
|
CRC := $FFF00FFF; {special CRC init}
|
|
UpdateCRC32(CRC, Memory^, StoredSignature.Offset);
|
|
UpdateCRC32(CRC, Memory^[StoredSignature.Offset + SizeOf(TSignatureRec)],
|
|
StoredSignature.Size - (StoredSignature.Offset + SizeOf(TSignatureRec)));
|
|
if (StoredSignature.CRC = not CRC) then
|
|
Result := exeSuccess;
|
|
UnmapViewOfFile(Memory);
|
|
end;
|
|
CloseHandle(FileMap);
|
|
end;
|
|
end;
|
|
CloseHandle(Fh);
|
|
end else begin {!!.05}
|
|
if GetLastError = ERROR_ACCESS_DENIED then {!!.05}
|
|
Result := exeAccessDenied; {!!.05}
|
|
end; {!!.05}
|
|
end;
|
|
{$ELSE}
|
|
function IsExeTampered(CheckSize : Boolean) : TExeStatus;
|
|
{-return one of the possible TExeResult states}
|
|
const
|
|
BufSize = 4096;
|
|
var
|
|
Fh : Integer;
|
|
TotalRead : LongInt;
|
|
BytesToRead : LongInt;
|
|
BytesRead : LongInt;
|
|
Size : LongInt;
|
|
Buf : PAnsiChar;
|
|
CRC : Dword;//LongInt;
|
|
begin
|
|
Result := exeIntegrityError;
|
|
|
|
{check if exe has been stamped}
|
|
if (StoredSignature.Offset = 1) and (StoredSignature.Size = 2) and {!!.07}
|
|
(StoredSignature.CRC = 3) then begin {!!.07}
|
|
Result := exeNotStamped;
|
|
Exit;
|
|
end;
|
|
|
|
Buf := StrAlloc(BufSize);
|
|
try
|
|
//GetModuleFileName(HInstance, Buf, BufSize-1);
|
|
//Buf := ParamStr(0);
|
|
Fh := FileOpen(ParamStr(0), fmOpenRead or fmShareDenyWrite);
|
|
if (Fh >= 0 {HFILE_ERROR}) then begin
|
|
Size := FileSeek(Fh, 0, 2); {get file size}
|
|
FileSeek(Fh, 0, 0); {reset to beginning of file}
|
|
if CheckSize and (StoredSignature.Size <> Size) then
|
|
Result := exeSizeError
|
|
else begin
|
|
CRC := $FFF00FFF; {special CRC init}
|
|
TotalRead := 0;
|
|
{read and compute crc up to the signature record}
|
|
while (TotalRead < StoredSignature.Offset) do begin
|
|
if (TotalRead + BufSize <= StoredSignature.Offset) then
|
|
BytesToRead := BufSize
|
|
else
|
|
BytesToRead := (StoredSignature.Offset - TotalRead);
|
|
BytesRead := FileRead(Fh, Buf^, BytesToRead);
|
|
Inc(TotalRead, BytesRead);
|
|
UpdateCRC32(DWord(CRC), Buf^, BytesRead);
|
|
end;
|
|
{jump past signature record}
|
|
FileSeek(Fh, SizeOf(StoredSignature), 1);
|
|
repeat
|
|
BytesRead := FileRead(Fh, Buf^, BufSize);
|
|
Inc(TotalRead, BytesRead);
|
|
UpdateCRC32(DWord(CRC), Buf^, BytesRead);
|
|
until (BytesRead < BufSize);
|
|
if (StoredSignature.CRC = not CRC) then
|
|
Result := exeSuccess;
|
|
end;
|
|
FileClose(Fh);
|
|
end else begin {!!.05}
|
|
if Fh = -5 then {!!.05}
|
|
Result := exeAccessDenied; {!!.05}
|
|
end; {!!.05}
|
|
|
|
finally
|
|
StrDispose(Buf);
|
|
end;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
{$IFDEF Win32}
|
|
function ProtectExe(const FileName : string; EraseMarker : Boolean) : Boolean;
|
|
{-stamp exe with crc and file size. optionally erase search markers}
|
|
var
|
|
Fh : THandle;
|
|
FileMap : THandle;
|
|
Memory : PByteArray;
|
|
I, Size : LongInt;
|
|
Sig : PSignatureRec;
|
|
begin
|
|
Result := False;
|
|
|
|
Fh := CreateFile(PAnsiChar(FileName), GENERIC_READ or GENERIC_WRITE, 0,
|
|
nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
|
if (Fh <> INVALID_HANDLE_VALUE) then begin
|
|
Size := Windows.GetFileSize(Fh, nil);
|
|
|
|
FileMap := CreateFileMapping(Fh, nil, PAGE_READWRITE, 0, 0, nil);
|
|
if (FileMap <> 0) then begin
|
|
Memory := MapViewOfFile(FileMap, FILE_MAP_WRITE, 0, 0, 0);
|
|
if (Memory <> nil) then begin
|
|
for I := 0 to (Size - SizeOf(TSignatureRec)) - 1 do begin
|
|
if (PSignatureRec(@Memory[I]).Sig1 = $407E7E21) and
|
|
(PSignatureRec(@Memory[I]).Sig2 = $33435243) and
|
|
(PSignatureRec(@Memory[I]).Sig3 = $7E7E4032) and
|
|
(PSignatureRec(@Memory[I]).Sig4 = $407E7E21) and
|
|
(PSignatureRec(@Memory[I]).Sig5 = $33435243) and
|
|
(PSignatureRec(@Memory[I]).Sig6 = $7E7E4032) then begin
|
|
|
|
{found it}
|
|
Sig := @Memory^[I];
|
|
|
|
if EraseMarker then begin
|
|
Sig.Sig1 := Sig.Sig1 xor timeGetTime;
|
|
Sig.Sig2 := Sig.Sig2 xor timeGetTime;
|
|
Sig.Sig3 := Sig.Sig3 xor timeGetTime;
|
|
Sig.Sig4 := Sig.Sig4 xor timeGetTime;
|
|
Sig.Sig5 := Sig.Sig5 xor timeGetTime;
|
|
Sig.Sig6 := Sig.Sig6 xor timeGetTime;
|
|
end;
|
|
|
|
Sig.Offset := I;
|
|
Sig.Size := Size;
|
|
Sig.CRC := $FFF00FFF; {special CRC init}
|
|
|
|
{compute crc ignoring the signature record}
|
|
UpdateCRC32(Sig.CRC, Memory^, Sig.Offset);
|
|
UpdateCRC32(Sig.CRC, Memory^[Sig.Offset + SizeOf(TSignatureRec)],
|
|
Sig.Size - (Sig.Offset + SizeOf(TSignatureRec)));
|
|
Sig.CRC := not Sig.CRC;
|
|
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
end;
|
|
UnmapViewOfFile(Memory);
|
|
end;
|
|
CloseHandle(FileMap);
|
|
end;
|
|
CloseHandle(Fh);
|
|
end;
|
|
end;
|
|
{$ELSE}
|
|
function ProtectExe(const FileName : string; EraseMarker : Boolean) : Boolean;
|
|
{-stamp exe with crc and file size. optionally erase search markers}
|
|
const
|
|
BufSize = 4096; {must be larger than the size of the signature record}
|
|
var
|
|
Fh : THandle;
|
|
I, Size : LongInt;
|
|
Sig : TSignatureRec;
|
|
Buf : PAnsiChar;
|
|
CRC : Dword;//LongInt;
|
|
TotalRead : LongInt;
|
|
BytesRead : LongInt;
|
|
begin
|
|
Result := False;
|
|
|
|
Buf := StrAlloc(BufSize);
|
|
try
|
|
Fh := FileOpen(FileName, fmOpenReadWrite or fmShareDenyWrite);
|
|
if (Fh >= 0 {HFILE_ERROR}) then begin
|
|
Size := FileSeek(Fh, 0, 2);
|
|
FileSeek(Fh, 0, 0); {reset to beginning of file}
|
|
CRC := $FFF00FFF; {special CRC init}
|
|
TotalRead := 0;
|
|
repeat
|
|
BytesRead := FileRead(Fh, Buf^, BufSize);
|
|
|
|
{search if not found}
|
|
if not Result then begin
|
|
for I := 0 to BytesRead - SizeOf(TSignatureRec) - 1 do begin
|
|
if (PSignatureRec(@Buf[I])^.Sig1 = $407E7E21) and
|
|
(PSignatureRec(@Buf[I])^.Sig2 = $33435243) and
|
|
(PSignatureRec(@Buf[I])^.Sig3 = $7E7E4032) and
|
|
(PSignatureRec(@Buf[I])^.Sig4 = $407E7E21) and
|
|
(PSignatureRec(@Buf[I])^.Sig5 = $33435243) and
|
|
(PSignatureRec(@Buf[I])^.Sig6 = $7E7E4032) then begin
|
|
|
|
Result := True; {found it}
|
|
|
|
Sig := PSignatureRec(@Buf[I])^;
|
|
if EraseMarker then begin
|
|
Sig.Sig1 := Sig.Sig1 xor timeGetTime;
|
|
Sig.Sig2 := Sig.Sig2 xor timeGetTime;
|
|
Sig.Sig3 := Sig.Sig3 xor timeGetTime;
|
|
Sig.Sig4 := Sig.Sig4 xor timeGetTime;
|
|
Sig.Sig5 := Sig.Sig5 xor timeGetTime;
|
|
Sig.Sig6 := Sig.Sig6 xor timeGetTime;
|
|
end;
|
|
|
|
Sig.Offset := TotalRead + I;
|
|
Sig.Size := Size;
|
|
|
|
{update crc up to the start of the signature record}
|
|
UpdateCRC32(DWord(CRC), Buf^, I);
|
|
{update crc for the remaing potion of the buffer (after the signature record)}
|
|
UpdateCRC32(DWord(CRC), Buf[I+SizeOf(TSignatureRec)],
|
|
BytesRead-(I+SizeOf(TSignatureRec)));
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
if not Result then begin
|
|
UpdateCRC32(DWord(CRC), Buf^, BytesRead-SizeOf(TSignatureRec));
|
|
{back up by size of TSignatureRec to insure that split record is found}
|
|
FileSeek(Fh, -SizeOf(TSignatureRec), 1);
|
|
Inc(TotalRead, BytesRead-SizeOf(TSignatureRec));
|
|
end;
|
|
until (BytesRead < BufSize) or Result;
|
|
|
|
{scan remaining portion of file}
|
|
if Result then begin
|
|
repeat
|
|
BytesRead := FileRead(Fh, Buf^, BufSize);
|
|
UpdateCRC32(DWord(CRC), Buf^, BytesRead);
|
|
until (BytesRead < BufSize);
|
|
end;
|
|
|
|
{save signature record back to the exe file}
|
|
if Result then begin
|
|
Sig.CRC := not CRC;
|
|
FileSeek(Fh, Sig.Offset, 0);
|
|
FileWrite(Fh, Sig, SizeOf(TSignatureRec))
|
|
end;
|
|
|
|
FileClose(Fh);
|
|
end;
|
|
finally
|
|
StrDispose(Buf);
|
|
end;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
|
|
{$IFDEF Win32}
|
|
function UnprotectExe(const FileName : string) : Boolean;
|
|
{-writes uninitialized signature record. marker must not have been erased}
|
|
var
|
|
Fh : THandle;
|
|
FileMap : THandle;
|
|
Memory : PByteArray;
|
|
I, Size : LongInt;
|
|
Sig : PSignatureRec;
|
|
begin
|
|
Result := False;
|
|
|
|
Fh := CreateFile(PAnsiChar(FileName), GENERIC_READ or GENERIC_WRITE, 0,
|
|
nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
|
if (Fh <> INVALID_HANDLE_VALUE) then begin
|
|
Size := Windows.GetFileSize(Fh, nil);
|
|
|
|
FileMap := CreateFileMapping(Fh, nil, PAGE_READWRITE, 0, 0, nil);
|
|
if (FileMap <> 0) then begin
|
|
Memory := MapViewOfFile(FileMap, FILE_MAP_WRITE, 0, 0, 0);
|
|
if (Memory <> nil) then begin
|
|
for I := 0 to (Size - SizeOf(TSignatureRec)) - 1 do begin
|
|
if (PSignatureRec(@Memory[I]).Sig1 = $407E7E21) and
|
|
(PSignatureRec(@Memory[I]).Sig2 = $33435243) and
|
|
(PSignatureRec(@Memory[I]).Sig3 = $7E7E4032) and
|
|
(PSignatureRec(@Memory[I]).Sig4 = $407E7E21) and
|
|
(PSignatureRec(@Memory[I]).Sig5 = $33435243) and
|
|
(PSignatureRec(@Memory[I]).Sig6 = $7E7E4032) then begin
|
|
|
|
{found it}
|
|
Sig := @Memory^[I];
|
|
|
|
{restore to uninitialized state}
|
|
Sig^.Offset := 1; {!!.08}
|
|
Sig^.Size := 2; {!!.08}
|
|
Sig^.CRC := 3; {!!.08}
|
|
|
|
Result := True;
|
|
Break;
|
|
end;
|
|
end;
|
|
UnmapViewOfFile(Memory);
|
|
end;
|
|
CloseHandle(FileMap);
|
|
end;
|
|
CloseHandle(Fh);
|
|
end;
|
|
end;
|
|
{$ELSE}
|
|
function UnprotectExe(const FileName : string) : Boolean;
|
|
{-writes uninitialized signature record. marker must not have been erased}
|
|
const
|
|
BufSize = 4096; {must be larger than the size of the signature record}
|
|
var
|
|
Fh : THandle;
|
|
I : LongInt;
|
|
Sig : TSignatureRec;
|
|
Buf : PAnsiChar;
|
|
Offset : LongInt;
|
|
BytesRead : LongInt;
|
|
TotalRead : LongInt;
|
|
begin
|
|
Result := False;
|
|
|
|
Buf := StrAlloc(BufSize);
|
|
try
|
|
Fh := FileOpen(FileName, fmOpenReadWrite or fmShareDenyWrite);
|
|
if (Fh >= 0 {HFILE_ERROR}) then begin
|
|
FileSeek(Fh, 0, 0); {reset to beginning of file}
|
|
TotalRead := 0;
|
|
repeat
|
|
BytesRead := FileRead(Fh, Buf^, BufSize);
|
|
|
|
{search if not found}
|
|
if not Result then begin
|
|
for I := 0 to BytesRead - SizeOf(TSignatureRec) - 1 do begin
|
|
if (PSignatureRec(@Buf[I])^.Sig1 = $407E7E21) and
|
|
(PSignatureRec(@Buf[I])^.Sig2 = $33435243) and
|
|
(PSignatureRec(@Buf[I])^.Sig3 = $7E7E4032) and
|
|
(PSignatureRec(@Buf[I])^.Sig4 = $407E7E21) and
|
|
(PSignatureRec(@Buf[I])^.Sig5 = $33435243) and
|
|
(PSignatureRec(@Buf[I])^.Sig6 = $7E7E4032) then begin
|
|
|
|
{found it}
|
|
Sig := PSignatureRec(@Buf[I])^;
|
|
|
|
{save position in file}
|
|
Offset := TotalRead + I;
|
|
Result := True;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
if not Result then begin
|
|
{back up by size of TSignatureRec to insure that split record is found}
|
|
FileSeek(Fh, -SizeOf(TSignatureRec), 1);
|
|
Inc(TotalRead, BytesRead-SizeOf(TSignatureRec));
|
|
end;
|
|
until (BytesRead < BufSize) or Result;
|
|
|
|
{save signature record back to the exe file}
|
|
if Result then begin
|
|
{restore to uninitialized state}
|
|
Sig.Offset := 1; {!!.08}
|
|
Sig.Size := 2; {!!.08}
|
|
Sig.CRC := 3; {!!.08}
|
|
|
|
FileSeek(Fh, Offset, 0);
|
|
FileWrite(Fh, Sig, SizeOf(TSignatureRec))
|
|
end;
|
|
|
|
FileClose(Fh);
|
|
end;
|
|
finally
|
|
StrDispose(Buf);
|
|
end;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
|
|
{checksum/CRC routines}
|
|
|
|
procedure UpdateChecksum(var Sum : LongInt; const Buf; BufSize : LongInt);
|
|
var
|
|
Bytes : TByteArray absolute Buf;
|
|
I : LongInt;
|
|
begin
|
|
for I := 0 to BufSize - 1 do
|
|
Sum := Sum + Bytes[I];
|
|
end;
|
|
|
|
{$IFDEF Win32}
|
|
function FileCRC32(const FileName : string) : DWord; {!!.07}
|
|
var
|
|
Fh : THandle;
|
|
FileMap : THandle;
|
|
Size : LongInt;
|
|
Memory : PByteArray;
|
|
Buf : array [0..MAX_PATH - 1] of AnsiChar;
|
|
begin
|
|
Result := $FFFFFFFF; {!!.07}
|
|
StrPLCopy(Buf, FileName, SizeOf(Buf)-1);
|
|
Fh := CreateFile(Buf, GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE,
|
|
nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
|
if (Fh <> INVALID_HANDLE_VALUE) then begin {!!.07}
|
|
Size := Windows.GetFileSize(Fh, nil);
|
|
FileMap := CreateFileMapping(Fh, nil, PAGE_READONLY, 0, 0, nil);
|
|
if (FileMap <> 0) then begin
|
|
Memory := MapViewOfFile(FileMap, FILE_MAP_READ, 0, 0, 0);
|
|
if (Memory <> nil) then begin
|
|
Result := $FFF00FFF; {special CRC init}
|
|
UpdateCRC32(Result, Memory^, Size);
|
|
UnmapViewOfFile(Memory);
|
|
end;
|
|
CloseHandle(FileMap);
|
|
end;
|
|
CloseHandle(Fh);
|
|
end;
|
|
end;
|
|
{$ELSE}
|
|
function FileCRC32(const FileName : string) : DWord;//LongInt;
|
|
const
|
|
BufSize = 4096;
|
|
var
|
|
Fh : Integer;
|
|
BytesRead : LongInt;
|
|
Buf : PAnsiChar;
|
|
begin
|
|
Buf := StrAlloc(BufSize);
|
|
try
|
|
StrPLCopy(Buf, FileName, BufSize-1);
|
|
Fh := FileOpen(StrPas(Buf), fmOpenRead or fmShareDenyWrite);
|
|
if (Fh >= 0 {HFILE_ERROR}) then begin
|
|
Result := $FFF00FFF; {special CRC init}
|
|
repeat
|
|
BytesRead := FileRead(Fh, Buf^, BufSize);
|
|
UpdateCRC32(DWord(Result), Buf^, BytesRead);
|
|
until (BytesRead < BufSize);
|
|
FileClose(Fh);
|
|
end;
|
|
finally
|
|
StrDispose(Buf);
|
|
end;
|
|
end;
|
|
{$ENDIF}
|
|
|
|
procedure UpdateCRC32(var CRC : DWord; const Buf; BufSize : LongInt); {!!.07}
|
|
var
|
|
Bytes : TByteArray absolute Buf;
|
|
I : LongInt;
|
|
B : Byte;
|
|
begin
|
|
for I := 0 to BufSize - 1 do begin
|
|
B := TLongIntRec(CRC).LoLo xor Bytes[I];
|
|
CRC := (CRC shr 8) xor CRC32Table[B];
|
|
end;
|
|
end;
|
|
|
|
end.
|