Subversion Repositories userdetect2

Rev

Rev 72 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
68 daniel-mar 1
unit PatchU;
2
 
81 daniel-mar 3
{$WARN UNSAFE_CODE OFF}
4
{$WARN UNSAFE_TYPE OFF}
5
 
68 daniel-mar 6
interface
7
 
8
type
9
  pPatchEvent = ^TPatchEvent;
10
 
11
  // "Asm" opcode hack to patch an existing routine
12
  TPatchEvent = packed record
13
    Jump: Byte;
14
    Offset: Integer;
15
  end;
16
 
17
  TPatchMethod = class
18
  private
19
    PatchedMethod, OriginalMethod: TPatchEvent;
20
    PatchPositionMethod: pPatchEvent;
21
    FIsPatched: boolean;
22
  public
23
    property IsPatched: boolean read FIsPatched;
24
    constructor Create(const aSource, aDestination: Pointer);
25
    destructor Destroy; override;
26
    procedure Restore;
27
    procedure Hook;
28
  end;
29
 
30
implementation
31
 
32
uses
33
  Windows, Sysutils;
34
 
35
{ TPatchMethod }
36
 
37
constructor TPatchMethod.Create(const aSource, aDestination: Pointer);
38
var
39
  OldProtect: Cardinal;
40
begin
41
  PatchPositionMethod := pPatchEvent(aSource);
42
  OriginalMethod := PatchPositionMethod^;
43
  PatchedMethod.Jump := $E9;
44
  PatchedMethod.Offset := Integer(PByte(aDestination)) - Integer(PByte(PatchPositionMethod)) - SizeOf(TPatchEvent);
45
 
46
  if not VirtualProtect(PatchPositionMethod, SizeOf(TPatchEvent), PAGE_EXECUTE_READWRITE, OldProtect) then
47
    RaiseLastOSError;
48
 
49
  Hook;
50
end;
51
 
52
destructor TPatchMethod.Destroy;
53
begin
54
  Restore;
55
  inherited;
56
end;
57
 
58
procedure TPatchMethod.Hook;
59
begin
60
  if FIsPatched then Exit;
61
  FIsPatched := true;
62
  PatchPositionMethod^ := PatchedMethod;
63
end;
64
 
65
procedure TPatchMethod.Restore;
66
begin
67
  if not FIsPatched then Exit;
68
  FIsPatched := false;
69
  PatchPositionMethod^ := OriginalMethod;
70
end;
71
 
72
end.
73