Write to memory to replace class (TMyEdit) with another (TEdit) at run time
const vmtNewInstance = System.vmtNewInstance; var AClassInstance: TClass; OldInstance: Pointer; function GetNewInstance: TObject; begin Result := AClassInstance.NewInstance; end; function GetVirtualMethod(AClass: TClass; const VmtOffset: Integer): Pointer; begin Result := PPointer(Integer(AClass) + VmtOffset)^; end; procedure SetVirtualMethod(AClass: TClass; const VmtOffset: Integer; const Method: Pointer); var WrittenBytes: DWORD; PatchAddress: PPointer; begin PatchAddress := Pointer(Integer(AClass) + VmtOffset); WriteProcessMemory(GetCurrentProcess, PatchAddress, @Method, SizeOf(Method), WrittenBytes); end; initialization OldInstance := GetVirtualMethod(TMyEdit, vmtNewInstance); AClassInstance := TMyEdit; SetVirtualMethod(StdCtrls.TEdit, vmtNewInstance, @GetNewInstance); finalization SetVirtualMethod(StdCtrls.TEdit, vmtNewInstance, OldInstance);
This works great, but how to write an OOP approach? Here is my attempt:
type TVirtualMethod = class FInstance: Pointer; FTarget: TClass; public constructor Create(const SourceClass, DestClass: TClass); destructor Free; end; { TVirtualMethod } var ASource: TClass; function GetNewInstance: TObject; begin Result := ASource.NewInstance; end; constructor TVirtualMethod.Create(const SourceClass, DestClass: TClass); var WrittenBytes: DWORD; PatchAddress: PPointer; begin ASource := SourceClass; FInstance := PPointer(Integer(ASource) + vmtNewInstance)^; FTarget := DestClass; PatchAddress := Pointer(Integer(DestClass) + vmtNewInstance); WriteProcessMemory(GetCurrentProcess, PatchAddress, @GetNewInstance, SizeOf(GetNewInstance), WrittenBytes); end; destructor TVirtualMethod.Free; var WrittenBytes: DWORD; PatchAddress: PPointer; begin PatchAddress := Pointer(Integer(FTarget) + vmtNewInstance); WriteProcessMemory(GetCurrentProcess, PatchAddress, @FInstance, SizeOf(FInstance), WrittenBytes); end; var v1: TVirtualMethod; initialization v1 := TVirtualMethod.Create(TMyEdit, TEdit); finalization v1.Free;
It compiles well, but it writes in memory.
source share