我该如何修补Delphi类的私有方法?

16

我已经阅读了下面这些问题和答案:

如何更改外部声明函数的实现(detour)

在Delphi中修补例程调用

但是我无法想出如何修补位于另一个单元中的类的私有方法

请查看此示例,我想要修补Bar过程。

Unit ThidParty;
Interface
   Type
      TFoo =Class
        private
           procedure Bar;
       end;

我认为关键是找到获取私有方法地址的方式。

那么,我如何对 Delphi 类的私有方法进行修补?


据我所知,这是不可能的,因为私有方法/过程不是VMT的一部分,因此无法通过RTTI等方式访问。也许可以通过黑客手段实现,但这需要您反汇编其他单元,然后进行一些指针算术和一些汇编操作才能到达那里... - Yahia
参见如何访问Delphi类的严格保护属性?。David提到的类助手。 - LU RD
2个回答

23
以下解决方案适用于Delphi Seattle及其之前的版本。您可以使用类助手来破解该类:

Unit1

type
  TTest = class
  private
    procedure Foo;
  end;

第二单元

type
  TMyTestHelper = class helper for TTest
    function GetFooAddress: Pointer;
  end;

function TMyTestHelper.GetFooAddress: Pointer;
var
  MethodPtr: procedure of object;
begin
  MethodPtr := Self.Foo;
  Result := TMethod(MethodPtr).Code;
end;

function FooAddress: Pointer;
begin
  Result := TTest(nil).GetFooAddress;//don't need to instantiate an object
end;

FooAddress的返回值传递给您的某个补丁函数,您就可以愉快地完成了。

然而,从Delphi 10.1 Berlin开始,这不再起作用!类帮助程序不能再访问strict protected、strict private或private成员。实际上,这是Embarcadero在Berlin修复的编译器错误,而不是一项“功能”。您没那么幸运了。


2
编译器里有个漏洞,这不是问题吗?如果被修复了怎么办? - Andreas Hausladen
1
@David:不幸的是,DCP包含了私有符号,但它在BPL中并没有被导出。因此编译器会很高兴地编译它,但在运行时,由于缺少符号,您的应用程序将无法启动。这就是为什么这是编译器中的漏洞。 - Andreas Hausladen
1
@Stefan:我改口了。看起来编译器确实会在BPL中导出所有私有方法。 - Andreas Hausladen
2
这被认为是一个错误,从Delphi 10.1 Berlin开始,使用类助手不再可以访问私有成员。 - LU RD
1
好的,仍然有一个可能的解决方案:TMethod(MethodPtr).Code := @TTest.Foo; - LU RD
显示剩余12条评论

0

只需使用类拦截重新定义方法,它可以在 Rad 10.4 之前工作。


你的答案可以通过提供额外的支持信息来改进。请[编辑]以添加更多细节,比如引用或文档,以便其他人可以确认你的答案是否正确。你可以在帮助中心找到有关如何撰写好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接