I’m trying to redirect the TObject.AfterConstruction to another procedure using the code bellow, but after a time a lot of exceptions start raise. Note: I use this kind of redirect to a lot of others solutions.
unit Unit109;
interface
uses
Windows;
implementation
uses
SyncObjs, SysUtils;
type
PJump = ^TJump;
TJump = packed record
OpCode: Byte;
Distance: Pointer;
end;
TObjectHack = class(TObject)
public
procedure AfterConstruction;
end;
function GetMethodAddress(AStub: Pointer): Pointer;
const
CALL_OPCODE = $E8;
begin
if PBYTE(AStub)^ = CALL_OPCODE then
begin
Inc(Integer(AStub));
Result := Pointer(Integer(AStub) + SizeOf(Pointer) + PInteger(AStub)^);
end
else
Result := nil;
end;
procedure AddressPatch(const ASource, ADestination: Pointer);
const
JMP_OPCODE = $E9;
SIZE = SizeOf(TJump);
var
NewJump: PJump;
OldProtect: Cardinal;
begin
if VirtualProtect(ASource, SIZE, PAGE_EXECUTE_READWRITE, OldProtect) then
begin
NewJump := PJump(ASource);
NewJump.OpCode := JMP_OPCODE;
NewJump.Distance := Pointer(Integer(ADestination) - Integer(ASource) - 5);
FlushInstructionCache(GetCurrentProcess, ASource, SizeOf(TJump));
VirtualProtect(ASource, SIZE, OldProtect, @OldProtect);
end;
end;
procedure OldAfterConstruction;
asm
call TObject.AfterConstruction;
end;
{ TCriticalSectionHack }
procedure TObjectHack.AfterConstruction;
begin
end;
initialization
AddressPatch(GetMethodAddress(@OldAfterConstruction), @TObjectHack.AfterConstruction);
end.
Maybe the AfterConstruction is stored in VMT (vmtAfterConstruction = -28) and it must by changed other way ? like:
PatchCodeDWORD(PDWORD(Integer(Self) + vmtAfterConstruction), DWORD(@TObjectHack.AfterConstruction));
procedure PatchCodeDWORD(ACode: PDWORD; AValue: DWORD);
var
LRestoreProtection, LIgnore: DWORD;
begin
if VirtualProtect(ACode, SizeOf(ACode^), PAGE_EXECUTE_READWRITE, LRestoreProtection) then
begin
ACode^ := AValue;
VirtualProtect(ACode, SizeOf(ACode^), LRestoreProtection, LIgnore);
FlushInstructionCache(GetCurrentProcess, ACode, SizeOf(ACode^));
end;
end;
I tried the both ways, with no success, someone can give me a help ?
If some one would like to read about this kinds of approaches:
- http://hallvards.blogspot.com.br/2007/05/hack17-virtual-class-variables-part-i.html
- http://hallvards.blogspot.com.br/2006/03/hack-8-explicit-vmt-calls.html
- http://hallvards.blogspot.com.br/2007/03/hack14-changing-class-of-object-at-run.html
Tks
EDITED – Now working to increase and decrease the number of items.
To make it work is just to put the unit as the first unit of your dpr.
Now, I’ll just optimize some methods and put here the outputs I want. (I’ll not reedit the post, not necessary)
But if you’d like to use, fell free to test and report bugs.
I put a simple out put if you’d like to test, the procedure SaveInstancesToFile, it creates a test.txt file in your application path with the output of counters.