Delphi 如何获取VMT中的条目数(虚拟方法)?

Delphi 如何获取VMT中的条目数(虚拟方法)?,delphi,hook,virtual-functions,vmt,Delphi,Hook,Virtual Functions,Vmt,在正偏移量时,VMT存储指向所有用户定义的虚拟方法的指针。 我需要编写一些代码来钩住VMT。 我这样做的方式是获取指向祖先类中虚拟方法的指针。 让我们说:TCustomForm.showmodel。然后我在VMT的TCustomForm中查找偏移量。有了这个偏移量,我转到TMyForm并修改它的VMT以指向我需要的函数 我想概括一下这个方法,为了做到这一点,我想知道VMT保存的条目总数,这样我就不会搜索到最后 如何获得VMT(用户可定义部分)的大小 通过RTL源进行挖掘我认为这是获得计数的方法:

在正偏移量时,VMT存储指向所有用户定义的虚拟方法的指针。
我需要编写一些代码来钩住VMT。 我这样做的方式是获取指向祖先类中虚拟方法的指针。
让我们说:
TCustomForm.showmodel
。然后我在VMT的
TCustomForm
中查找偏移量。有了这个偏移量,我转到
TMyForm
并修改它的VMT以指向我需要的函数

我想概括一下这个方法,为了做到这一点,我想知道VMT保存的条目总数,这样我就不会搜索到最后


如何获得VMT(用户可定义部分)的大小

通过RTL源进行挖掘我认为这是获得计数的方法:

function GetVMTCount(AClass: TClass): integer;
var
  p: pointer;
  VirtualMethodCount: word;
begin
  p := PPointer(PByte(AClass) + vmtMethodTable)^;
  VirtualMethodCount:= PWord(p)^;
  //Size of the VMT in bytes
  Result:= VirtualMethodCount * SizeOf(Pointer) - vmtSelfPtr;
  //Number of entries in the VMT
  Result:= Result div SizeOf(Pointer);
end;

如果需要,请随时纠正我。

通过RTL源代码挖掘我认为这是获得计数的方法:

function GetVMTCount(AClass: TClass): integer;
var
  p: pointer;
  VirtualMethodCount: word;
begin
  p := PPointer(PByte(AClass) + vmtMethodTable)^;
  VirtualMethodCount:= PWord(p)^;
  //Size of the VMT in bytes
  Result:= VirtualMethodCount * SizeOf(Pointer) - vmtSelfPtr;
  //Number of entries in the VMT
  Result:= Result div SizeOf(Pointer);
end;

如果需要,请随时纠正我。

一种在不太了解VMT结构的情况下执行此操作的方法,因此在VMT结构再次更改时不太容易中断,就是使用Rtti进行此操作
TRttiInstanceType
知道关联类的
VmtSize

因此,使用
VmtSize
和作为
指针的VMT条目

function GetVirtualMethodCount(AClass: TClass): Integer;
var
  AContext: TRttiContext;
  AType: TRttiType;
begin
  AType := AContext.GetType(AClass);
  Result := (AType as TRttiInstanceType).VmtSize div SizeOf(Pointer);
end;
但是,这也将包括从基类继承的所有条目。包括负偏移处的
TObject
。但是可以从给定的基类中减去所有条目,例如
TObject
。以下是一种提供了可变基类的方法:

function GetVirtualMethodCountMinusBase(AClass: TClass; ABaseClass: TClass): Integer;
var
  AContext: TRttiContext;
  AType, ABaseType: TRttiType;
begin
  AType := AContext.GetType(AClass);
  ABaseType := AContext.GetType(ABaseClass);
  Result := ((AType as TRttiInstanceType).VmtSize - (ABaseType as TRttiInstanceType).VmtSize) div SizeOf(Pointer);
end;

:当使用绝地时,
JclSysUtils
中有一个名为
GetVirtualMethodCount
的函数。虽然我不确定这是否是最新的和正确的

在不了解VMT结构的情况下执行此操作的一种方法是使用Rtti进行此操作,因此当VMT结构再次更改时,不太容易发生中断
TRttiInstanceType
知道关联类的
VmtSize

因此,使用
VmtSize
和作为
指针的VMT条目

function GetVirtualMethodCount(AClass: TClass): Integer;
var
  AContext: TRttiContext;
  AType: TRttiType;
begin
  AType := AContext.GetType(AClass);
  Result := (AType as TRttiInstanceType).VmtSize div SizeOf(Pointer);
end;
但是,这也将包括从基类继承的所有条目。包括负偏移处的
TObject
。但是可以从给定的基类中减去所有条目,例如
TObject
。以下是一种提供了可变基类的方法:

function GetVirtualMethodCountMinusBase(AClass: TClass; ABaseClass: TClass): Integer;
var
  AContext: TRttiContext;
  AType, ABaseType: TRttiType;
begin
  AType := AContext.GetType(AClass);
  ABaseType := AContext.GetType(ABaseClass);
  Result := ((AType as TRttiInstanceType).VmtSize - (ABaseType as TRttiInstanceType).VmtSize) div SizeOf(Pointer);
end;

:当使用绝地时,
JclSysUtils
中有一个名为
GetVirtualMethodCount
的函数。虽然我不确定这是否是最新的和正确的

我可能记错了,但在System.Rtti中有TVirtualMethodInterceptor类。ProxyClass的创建可能会帮助您,因为它创建了VMT副本,其中的一些代码可能会帮助您。我记得像vmtSize这样的方法。@LURD,这个问题只有不正确的答案,正如Stephan在对这个答案的评论中指出的那样:在内置汇编程序中,很容易找到实际的索引。有一个VMTOFFSET“宏”,它将虚拟方法的偏移量返回到VMT中。但没有人能告诉你VMT的大小。我猜这不会存储在任何地方(除了编译器的内部数据)。编译器只使用正确的偏移量(或索引),从不通过VMT进行访问。您是否已经在System.pas中查看了MethodAddress的代码?它显示了方法的数量存储为VMT的第一个字(16位),指针存储在TClass结构中的偏移量vmtMethodTable处,每个对象的第一个DWORD指向该偏移量。我可能记错了,但在System.Rtti中有TVirtualMethodInterceptor类。ProxyClass的创建可能会帮助您,因为它创建了VMT副本,其中的一些代码可能会帮助您。我记得像vmtSize这样的方法。@LURD,这个问题只有不正确的答案,正如Stephan在对这个答案的评论中指出的那样:在内置汇编程序中,很容易找到实际的索引。有一个VMTOFFSET“宏”,它将虚拟方法的偏移量返回到VMT中。但没有人能告诉你VMT的大小。我猜这不会存储在任何地方(除了编译器的内部数据)。编译器只使用正确的偏移量(或索引),从不通过VMT进行访问。您是否已经在System.pas中查看了MethodAddress的代码?它显示方法的数量存储为VMT的第一个字(16位),指针存储在TClass结构中的偏移量vmtMethodTable处,每个对象的第一个DWORD指向该偏移量。