我需要枚举用delphi编写的外部应用程序中使用的类 ,所以我需要访问VMT表来获取该信息,但我找不到任何关于如何在exe(由delphi生成)文件中找到VMT(虚拟方法表)的位置(地址)的文档。 / p>
答案 0 :(得分:3)
请注意,运行时类型信息与VMT存在差异。如果您需要RTTI而不是VMT的类型信息(如方法和类型的名称);一个VMT,如果你能够到达它(你可以通过一个类型的RTTI类型见下文)将包含一个指向方法的指针列表,没有方法mnames,参数信息等等.Delphi不为每个创建IDispatch等信息和每个类/接口..
直到Delphi 2007你没有所有类型的列表,以后的版本可能是相同的,但我不确定。如果您有一个地图文件,您可以从中获取一些数据,或者您可以使用一些启发式搜索文件:Delphi中的类型总是带有指向self的指针(例如,指向PTypeInfo的指向PPTypeInfo)。由于PTypeinfo也具有特定格式,因此您可以通过扫描可执行文件轻松检测这些格式。
找到PTypeInfo后,您可以解析产生类型名后面的数据,然后解析您拥有TypeData。对于类类型,您可以在类中找到包含可能偏移的VMT的poiter。包含已发布方法/属性的类型将包含类型数据之后的类型。您可以在单位TypInfo中找到结构的所有详细信息。
除了在地图文件中,您永远不会找到所有方法的所有地址;只有RTTI的方法(例如发布的)具有名称的地址。只有一组选定的类型具有RTTI(后来Delphi有新的RTTI信息,但我不知道它们在模块中的构造)。
祝你好运。答案 1 :(得分:3)
.exe文件中没有一个VMT。每个类都有自己的VMT。有,AFAICT,没有可靠的方法来枚举可执行文件中的类。我假设可执行文件只是一个文件。唯一的方法是分析这些数据如何存储在.exe文件中。
但即使.exe正在运行,并且您可以访问其中一个对象,您也只能找到该对象的类的VMT(在对象的偏移0处)。这也可以让你访问类的基类,但这是关于它的。
答案 2 :(得分:1)
是的,这在一定程度上是可能的!
为了描述它,您需要的是 EXE 文件的类浏览器,类似于IDE使用pascal单元的方式。
Interactive Delphi Reconstructor是该概念的最佳高级应用之一。
DeDe 3.50.02 Build 1619(包括源代码?)。
Revendepro 的源代码说明了解决它的方法。
摘自 http://www.ggoossen.net/revendepro/findingClasses.html (现在似乎是一个死链接):
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;
免责声明:我从未测试过这些代码。