如何获取delphi生成的EXE的VMT表的地址(位置)

如何获取delphi生成的EXE的VMT表的地址(位置),delphi,Delphi,我需要列举用delphi编写的外部应用程序中使用的类 ,因此我需要访问VMT表才能获得该信息,但我找不到任何关于如何在exe(由delphi生成)文件中查找VMT(虚拟方法表)位置(地址)的文档。请注意,运行时类型信息与仅VMT不同。如果您需要类型信息(如方法和类型的名称),则该信息是RTTI而不是VMT;如果可以访问VMT(可以通过类类型的RTTI访问类型,见下文),则VMT将包含指向方法的指针列表,而不包含方法名称、参数信息等。Delphi不会为每个类/接口创建IDispatch之类的信息

我需要列举用delphi编写的外部应用程序中使用的类
,因此我需要访问VMT表才能获得该信息,但我找不到任何关于如何在exe(由delphi生成)文件中查找VMT(虚拟方法表)位置(地址)的文档。

请注意,运行时类型信息与仅VMT不同。如果您需要类型信息(如方法和类型的名称),则该信息是RTTI而不是VMT;如果可以访问VMT(可以通过类类型的RTTI访问类型,见下文),则VMT将包含指向方法的指针列表,而不包含方法名称、参数信息等。Delphi不会为每个类/接口创建IDispatch之类的信息

到Delphi2007为止,您没有所有类型的列表,以后的版本可能是相同的,但我不确定。如果你有一个映射文件,你可以从中获得一些数据,或者你可以使用一些启发式搜索文件:Delphi中的类型总是在前面加上指向self的指针(例如指向PTypeInfo的PPTypeInfo)。由于PTypeinfo也有一个特定的格式,您可以通过扫描可执行文件很容易地检测到这些格式

一旦找到PTypeInfo,您就可以解析后面的数据,生成typename,然后得到TypeData。对于这里的类类型,您可以找到包含可能偏移量处VMT的类的指针。包含已发布方法/属性的类型将在类型数据之后具有这些方法/属性。您可以在UnitTypeInfo中找到结构的所有详细信息

除了在映射文件中,您永远找不到所有方法的所有地址;只有带有RTTI的方法(例如已发布的方法)具有带名称的地址。只有一组选定的类型具有RTTI(稍后的Delphi具有新的RTTI信息,但我不知道它们在模块中的构造)


祝你好运。

请注意,运行时类型信息不同,只有VMT。如果您需要类型信息(如方法和类型的名称),则该信息是RTTI而不是VMT;如果可以访问VMT(可以通过类类型的RTTI访问类型,见下文),则VMT将包含指向方法的指针列表,而不包含方法名称、参数信息等。Delphi不会为每个类/接口创建IDispatch之类的信息

到Delphi2007为止,您没有所有类型的列表,以后的版本可能是相同的,但我不确定。如果你有一个映射文件,你可以从中获得一些数据,或者你可以使用一些启发式搜索文件:Delphi中的类型总是在前面加上指向self的指针(例如指向PTypeInfo的PPTypeInfo)。由于PTypeinfo也有一个特定的格式,您可以通过扫描可执行文件很容易地检测到这些格式

一旦找到PTypeInfo,您就可以解析后面的数据,生成typename,然后得到TypeData。对于这里的类类型,您可以找到包含可能偏移量处VMT的类的指针。包含已发布方法/属性的类型将在类型数据之后具有这些方法/属性。您可以在UnitTypeInfo中找到结构的所有详细信息

除了在映射文件中,您永远找不到所有方法的所有地址;只有带有RTTI的方法(例如已发布的方法)具有带名称的地址。只有一组选定的类型具有RTTI(稍后的Delphi具有新的RTTI信息,但我不知道它们在模块中的构造)


祝你好运。

一个.exe文件中没有一个VMT。每个类都有自己的VMT。实际上,没有可靠的方法来枚举可执行文件中的类。我假设可执行文件只是一个文件。唯一的方法是分析这些数据是如何存储在.exe文件中的


但是,即使.exe正在运行,并且您有权访问其中一个对象,您也只能找到该对象类的VMT(位于对象的偏移量0处)。这也将允许您访问该类的基类,但仅此而已。

一个.exe文件中没有一个VMT。每个类都有自己的VMT。实际上,没有可靠的方法来枚举可执行文件中的类。我假设可执行文件只是一个文件。唯一的方法是分析这些数据是如何存储在.exe文件中的


但是,即使.exe正在运行,并且您有权访问其中一个对象,您也只能找到该对象类的VMT(位于对象的偏移量0处)。这也将允许您访问类的基类,但仅此而已。

是的,在某种程度上这是可能的

为了描述它,您需要的是一种类浏览器,用于EXE文件,类似于IDE使用pascal单元的方式

  • 是这一概念最好的高级应用之一

  • 太多(包括源代码?)

Revendepro的源代码说明了解决此问题的方法

摘自http://www.ggoossen.net/revendepro/findingClasses.html (现在似乎是死链接):



//将父类添加到列表中。
重复
加:=假;
对于J:=PossClasses.Count-1到0
开始
//尝试在类列表中查找父类
如果FindClass(TClass(possclass[J]).ClassParent)为nil,则
开始
//类列表中的类
添加(类[J]);
删除(J);
加:=真;
终止
//尝试在其他包中查找父类。
对于K:=0到高(PEF)do
如果PEFiles[K].Classes.FindClass(TClass(possclass[J]).ClassParent)为零,则
开始
//类列表中的类
添加(类[J]);
删除(J);
加:=真;
打破
终止
终止
直到没有添加;

免责声明:我从未测试过这些代码。

是的,在某种程度上这是可能的

描述它,什么
  I := Code - vmtSelfPtr;
  while I < Code + CodeSize do
  begin
    // vmtSelfPtr must point to itself.
    if PPChar(I + vmtSelfPtr)^ = I then
    begin
        if PPChar(I + vmtParent)^ = nil then
        try
          // If no classParent then class can be object
          if (not UsePackages) and (TClass(I).ClassName = 'TObject') then
            // if class if object add it to classes.
            Add(TClass(I))
        except
          on EAccessViolation do
        end
        else
          // className must be in the code section.
          // classParent must be in the code section or the import section (when it is imported).
          if (PPChar(I + vmtClassName)^ <= Code + CodeSize) and
             (PPChar(I + vmtClassName)^ >= Code) and
             (((PPChar(I + vmtParent)^ <= Code + CodeSize) and
               (PPChar(I + vmtParent)^ >= Code)) or
              ((PPChar(I + vmtParent)^ <= ImportStart + ImportSize) and
               (PPChar(I + vmtParent)^ >= ImportStart))) then
          // Add possible class to possible class list.
          PossClasses.Add(I);
    end;
    Inc(I, 4);
  end;
   // Can't be more then 1 TObject.
  if (not TPEFileClass(PEFileClass).UsePackages) and (Count > 1) then
    raise EDecompilerError.Create('There can only be one TObject.');
  // If no classParent then class can be object
  if TClass(I).ClassName = 'TObject' then
    Add(TClass(I)) // if class if object add it to classes.
    // Add Classes to the list which parent is in the list.
  repeat
    Added := False;
    for J := PossClasses.Count -1 downto 0 do
    begin
      // Try to find parent class in classList
      if FindClass(TClass(PossClasses[J]).ClassParent) <> nil then
      begin
        // Class in class list
        Add(PossClasses[J]);
        PossClasses.Delete(J);
        Added := True;
      end;
      // Try to find parent class in a other package.
      for K := 0 to High(PEFiles) do
        if PEFiles[K].Classes.FindClass(TClass(PossClasses[J]).ClassParent) <> nil then
        begin
          // Class in class list
          Add(PossClasses[J]);
          PossClasses.Delete(J);
          Added := True;
          Break;
        end;
    end;
  until not Added;