This class creates a hook with a Static procedure
From: Alexander Muylaert (ask_at_hotmail.com)
Date: 06/28/04
- Next message: Alexander Muylaert: "Re: This class creates a hook with a Static procedure"
- Previous message: Hallvard Vassbotn: "Re: Replace TControl.SetVisible and TControl.SetEnabled"
- Next in thread: Alexander Muylaert: "Re: This class creates a hook with a Static procedure"
- Reply: Alexander Muylaert: "Re: This class creates a hook with a Static procedure"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Mon, 28 Jun 2004 10:45:11 +0200
Hi
I've written a class that hooks a static procedure.
It should work transparent. When the original code is called it should call
my procedure en then it should call the original. It call's my code. But
my theorie of copying the original code to something a buffer, doesn't seem
to work.
Can somebody please check what is wrong please, It would help me a lot.
First unit contains the source, the second is test code.
Kind regards and many thanks
Alexander
{***************************************************************************
**
Name : unit_SecurityHacks
Author : amuylaer
Copyright : (c) Peopleware
Description : This unit contains hacks required by the security
component.
History :
Date By Description
---- -- -----------
28/06/2004 AMuylaert Initial creation of the Unit.
****************************************************************************
*}
unit unit_SecurityHacks;
interface
uses Windows;
type
{
Use this class to hack/hook a static procedure
the procedure needs to be at least 10 bytes.
If you have no idea what this does, get the f**k out of this unit.
}
TStaticHack = class(TObject)
private
FOrgCode : Pointer;
FOrgSize : Integer;
FOrgCopy : Pointer;
FNewCode : Pointer;
FHacked : Boolean;
private
procedure CopyOriginal;
procedure ReplaceWithHack;
procedure RestoreOriginal;
public
constructor Create(aOrgCode, aNewCode : Pointer; aOrgSize : Integer);
destructor Destroy; override;
procedure Hack;
procedure Restore;
public
property Hacked : Boolean read FHacked;
end;
implementation
uses SysUtils;
{ TStaticHack }
constructor TStaticHack.Create(aOrgCode, aNewCode: Pointer;
aOrgSize: Integer);
begin
if aOrgSize < 10 then begin
raise Exception.Create('Cannot perform this hack on code less then 10
bytes');
end;
FOrgCode := aOrgCode;
FOrgSize := aOrgSize;
FNewCode := aNewCode;
FOrgCopy := nil;
end;
destructor TStaticHack.Destroy;
begin
Restore;
if assigned(FOrgCopy) then FreeMemory(FOrgCopy);
inherited Destroy;
end;
procedure TStaticHack.CopyOriginal;
var
OldProtect, TempProtect : DWord;
begin
{Change page access to pointer, otherwise AV}
if VirtualProtect(FOrgCode, FOrgSize, PAGE_EXECUTE_READWRITE, OldProtect)
then try
{Allocate the buffer}
{ This needs to be virtual memory, since we are changing the MemAccess.
We need a fresh page, because the Virtualprotect changes the thing for
the whole page. }
FOrgCopy := VirtualAlloc(nil, FOrgSize, MEM_COMMIT, PAGE_READWRITE);
{Copy the memory}
Move(FOrgCode^, FOrgCopy^, FOrgSize);
{Give copy execute rights}
if not VirtualProtect(FOrgCopy, FOrgSize, PAGE_EXECUTE, tempProtect)
then begin
raiseLastWin32Error;
end;
finally
{Restore original page access}
VirtualProtect(FOrgCode, FOrgSize, OldProtect, OldProtect);
end else begin
RaiseLastWin32Error;
end;
end;
procedure TStaticHack.ReplaceWithHack;
type
PHack = ^THack;
THack = packed record
OpCodeNew : Byte;
OFFToNew : Integer;
OpCodeOrg : Byte;
OFFToOrg : Integer;
end;
var
OldProtect : DWord;
Temp : Pointer;
begin
{Change page access to pointer, otherwise AV}
if VirtualProtect(FOrgCode, FOrgSize, PAGE_EXECUTE_READWRITE, OldProtect)
then try
{Create a temp buffer with all bytes set to zero}
Temp := AllocMem(FOrgSize);
try
{Prepare hack}
with PHack(Temp)^ do begin
OpCodeNew := $E8; {E8 = CALL}
OFFToNew := PChar(FNewCode) - PChar(FOrgCode) - 5;
OpCodeOrg := $E9; {E9 = JMP
{Something is wrong with this pointer}
OFFToOrg := PChar(FOrgCopy) - PChar(FOrgCode) - 10;
end;
{Replacement}
Move(Temp^, FOrgCode^, FOrgSize);
finally
FreeMem(Temp);
end;
finally
{Restore original page access}
VirtualProtect(FOrgCode, FOrgSize, OldProtect, OldProtect);
end else begin
RaiseLastWin32Error;
end;
end;
procedure TStaticHack.Hack;
var
OldProtect : DWord;
begin
if FHacked then exit;
FHacked := True;
CopyOriginal;
ReplaceWithHack;
end;
procedure TStaticHack.Restore;
begin
if not FHacked then exit;
FHacked := False;
end;
procedure TStaticHack.RestoreOriginal;
var
OldProtect : DWord;
begin
{Change page access to pointer, otherwise AV}
if VirtualProtect(FOrgCode, FOrgSize, PAGE_EXECUTE_READWRITE, OldProtect)
then try
{restore the memory}
Move(FOrgCopy^, FOrgCode^, FOrgSize);
{Free the buffer}
VirtualFree(FOrgCopy, 0, MEM_RELEASE);
FOrgCopy := nil;
finally
{Restore original page access}
VirtualProtect(FOrgCode, FOrgSize, OldProtect, OldProtect);
end else begin
RaiseLastWin32Error;
end;
end;
end.
{--TEST CODE STARTS HERE}
type
TSecurityControlHack = class(TObject)
private
FVisibleHack : TStaticHack;
published
procedure SetVisible(aValue : Boolean);
public
constructor Create;
destructor Destroy; override;
end;
procedure TSecurityControlHack.SetVisible(aValue: Boolean);
begin
{
Warning!! Since this is a dirty hack
The register EAX and therefor "self" doesn't reference to a
TSecurityControlHack
It references to the control!!!
}
beep;
end;
TMakePropertiesPublishedHack = class(TControl)
published
property Visible;
end;
constructor TSecurityControlHack.Create;
var
Prop : PPropInfo;
begin
inherited Create;
{$IFDEF VER150}
{This is written for D7}
Prop := GetPropInfo(TMakePropertiesPublishedHack, 'Visible',
[Low(TTypeKind)..High(TTypeKind)]);
FVisibleHack := TStaticHack.Create( Prop^.SetProc,
MethodAddress('SetVisible'),
60); {we know the length of
TControl.SetVisible = 60 bytes}
FVisibleHack.Hack;
{$ENDIF}
end;
destructor TSecurityControlHack.Destroy;
begin
FVisibleHack.Restore;
FVisibleHack.Free;
inherited Destroy;
end;
- Next message: Alexander Muylaert: "Re: This class creates a hook with a Static procedure"
- Previous message: Hallvard Vassbotn: "Re: Replace TControl.SetVisible and TControl.SetEnabled"
- Next in thread: Alexander Muylaert: "Re: This class creates a hook with a Static procedure"
- Reply: Alexander Muylaert: "Re: This class creates a hook with a Static procedure"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]