Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7933415
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 3, 20262026-06-03T21:19:35+00:00 2026-06-03T21:19:35+00:00

I’m trying to redirect the TObject.AfterConstruction to another procedure using the code bellow, but

  • 0

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

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-03T21:19:36+00:00Added an answer on June 3, 2026 at 9:19 pm

    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.

    unit ObjectCounter;
    
      {  Develop by rodrigofrezino@gmail.com
         Stackoverflow: http://stackoverflow.com/users/225010/saci
         Please, any bug let me know}
    
    interface
    
      procedure SaveInstancesToFile;
    
    implementation
    
    uses
      Windows, SysUtils, Classes, TypInfo;
    
    type
    
      PClassVars = ^TClassVars;
      TClassVars = class(TObject)
      private
        class var ListClassVars: TList;
      public
        InstanceCount: integer;
        BaseClassName: string;
        constructor Create;
    
        class procedure SaveToDisk;
      end;
    
      PJump = ^TJump;
      TJump = packed record
        OpCode: Byte;
        Distance: Pointer;
      end;
    
      TObjectHack = class(TObject)
      private
        class procedure SetClassVars(AClassVars: TClassVars);
        class function GetClassVars: TClassVars;
    
        procedure IncCounter;
        procedure DecCounter;
        procedure OldFreeInstace;
      public
        class function InitInstance(Instance: Pointer): TObject;
      end;
    
    var
      FOldFreeInstance: Pointer;
    
    procedure SaveInstancesToFile;
    begin
      TClassVars.SaveToDisk;
    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 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;
    
    procedure OldAfterConstruction;
    asm
      call TObject.InitInstance;
    end;
    
    { TCriticalSectionHack }
    procedure TObjectHack.DecCounter;
    begin
      if (Self.ClassType <> TClassVars) then
        Dec(GetClassVars.InstanceCount);
      OldFreeInstace;
    end;
    
    class function TObjectHack.GetClassVars: TClassVars;
    begin
      Result := PClassVars(Integer(Self) + vmtAutoTable)^;
    end;
    
    class procedure TObjectHack.SetClassVars(AClassVars: TClassVars);
    begin
      AClassVars.BaseClassName := Self.ClassName;
      PatchCodeDWORD(PDWORD(Integer(Self) + vmtAutoTable), DWORD(AClassVars));
    end;
    
    procedure RegisterClassVarsSupport(const Classes: array of TObjectHack);
    var
      LClass: TObjectHack;
      LRestoreProtection: DWORD;
      LIgnore: DWORD;
      LVMT: Pointer;
    begin
      for LClass in Classes do
        if LClass.GetClassVars = nil then
        begin
          LClass.SetClassVars(TClassVars.Create);
    
          //Change de mvt to object mvt
          LVMT := PPointer(Integer(TObject) + vmtFreeInstance)^;
          if VirtualProtect(LVMT, SizeOf(LVMT^), PAGE_EXECUTE_READWRITE, LRestoreProtection) then
          begin
            LVMT :=  @TObjectHack.DecCounter;
            VirtualProtect(LVMT, SizeOf(LVMT^), LRestoreProtection, LIgnore);
            FlushInstructionCache(GetCurrentProcess, LVMT, SizeOf(LVMT^));
          end;
        end
        else
          raise Exception.CreateFmt('Class %s has automated section or duplicated registration.', [LClass.ClassName]);
    end;
    
    procedure TObjectHack.IncCounter;
    begin
      if (Self.ClassType = TClassVars) then
        Exit;
    
      if GetClassVars = nil then
        RegisterClassVarsSupport(Self);
    
      Inc(GetClassVars.InstanceCount);
    end;
    
    class function TObjectHack.InitInstance(Instance: Pointer): TObject;
    asm
            PUSH    EBX
            PUSH    ESI
            PUSH    EDI
            MOV     EBX,EAX
            MOV     EDI,EDX
            STOSD
            MOV     ECX,[EBX].vmtInstanceSize
            XOR     EAX,EAX
            PUSH    ECX
            SHR     ECX,2
            DEC     ECX
            REP     STOSD
            POP     ECX
            AND     ECX,3
            REP     STOSB
            MOV     EAX,EDX
            MOV     EDX,ESP
    @@0:    MOV     ECX,[EBX].vmtIntfTable
            TEST    ECX,ECX
            JE      @@1
            PUSH    ECX
    @@1:    MOV     EBX,[EBX].vmtParent
            TEST    EBX,EBX
            JE      @@2
            MOV     EBX,[EBX]
            JMP     @@0
    @@2:    CMP     ESP,EDX
            JE      @@5
    @@3:    POP     EBX
            MOV     ECX,[EBX].TInterfaceTable.EntryCount
            ADD     EBX,4
    @@4:    MOV     ESI,[EBX].TInterfaceEntry.VTable
            TEST    ESI,ESI
            JE      @@4a
            MOV     EDI,[EBX].TInterfaceEntry.IOffset
            MOV     [EAX+EDI],ESI
    @@4a:   ADD     EBX,TYPE TInterfaceEntry
            DEC     ECX
            JNE     @@4
            CMP     ESP,EDX
            JNE     @@3
    @@5:    MOV     EBX,EAX
            CALL    TObjectHack.IncCounter
            MOV     EAX,EBX
            POP     EDI
            POP     ESI
            POP     EBX
    end;
    
    procedure TObjectHack.OldFreeInstace;
    asm
      call FOldFreeInstance;
    end;
    
    procedure InitFreeInstance;
    begin
      FOldFreeInstance := PPointer(Integer(TObject) + vmtFreeInstance)^;
    end;
    
    { TClassVars }
    
    constructor TClassVars.Create;
    begin
      ListClassVars.Add(Self);
    end;
    
    class procedure TClassVars.SaveToDisk;
    var
      LStringList: TStringList;
      i: Integer;
    begin                               
      LStringList := TStringList.Create;
      try
        LStringList.Add('CLASS | NUMBER OF INSTANCES');
        for i := 0 to ListClassVars.Count -1 do
          LStringList.Add(TClassVars(ListClassVars.Items[I]).BaseClassName + '|' + IntToStr(TClassVars(ListClassVars.Items[I]).InstanceCount));
    
        LStringList.SaveToFile(ExtractFilePath(ParamStr(0)) + 'test.txt');
      finally
        FreeAndNil(LStringList);
      end;
    end;
    
    initialization
      TClassVars.ListClassVars := TList.Create;
      InitFreeInstance;
      AddressPatch(GetMethodAddress(@OldAfterConstruction), @TObjectHack.InitInstance);
    
    end.
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I am trying to understand how to use SyndicationItem to display feed which is
Basically, what I'm trying to create is a page of div tags, each has
I'm new to using the Perl treebuilder module for HTML parsing and can't figure
link Im having trouble converting the html entites into html characters, (&# 8217;) i
That's pretty much it. I'm using Nokogiri to scrape a web page what has
I want to count how many characters a certain string has in PHP, but
For some reason, after submitting a string like this Jack’s Spindle from a text
I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function
I am reading a book about Javascript and jQuery and using one of the
I am trying to render a haml file in a javascript response like so:

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.