Delphi 如何获取VMT中的条目数(虚拟方法)?
在正偏移量时,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。 我这样做的方式是获取指向祖先类中虚拟方法的指针。
让我们说:
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指向该偏移量。