Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 德尔菲反编译_Delphi_Reverse Engineering_Exe_Decompiling - Fatal编程技术网

Delphi 德尔菲反编译

Delphi 德尔菲反编译,delphi,reverse-engineering,exe,decompiling,Delphi,Reverse Engineering,Exe,Decompiling,与使用其他编程语言/编译器构建的其他可执行文件相比,为什么反编译delphi exe如此简单?您的说法是错误的。Delphi并不比其他主流编译器生成的代码更容易反编译 对于.net语言来说,有 本文介绍了C++语言 解释Python/Perl/Ruby等 如果您能够证明反编译Delphi可执行文件的结果的质量明显高于其他广泛使用的语言,那么您的问题将具有更大的份量。以下几点有助于逆转Delphi程序: 您将获得完整的表单数据,包括事件处理程序方法的名称 所有具有发布的可见性的成员都将元数据

与使用其他编程语言/编译器构建的其他可执行文件相比,为什么反编译delphi exe如此简单?

您的说法是错误的。Delphi并不比其他主流编译器生成的代码更容易反编译

  • 对于.net语言来说,有
  • 本文介绍了C++语言
  • 解释Python/Perl/Ruby等

如果您能够证明反编译Delphi可执行文件的结果的质量明显高于其他广泛使用的语言,那么您的问题将具有更大的份量。

以下几点有助于逆转Delphi程序:

  • 您将获得完整的表单数据,包括事件处理程序方法的名称
  • 所有具有
    发布的
    可见性的成员都将元数据与RTTI一起使用
  • 编译器在优化方面非常糟糕。它不会对整个程序进行优化,汇编通常是对原始源代码的直接翻译,只进行了少量优化。(至少在我使用的版本中,从那时起可能已经有所改进)
  • 所有类,甚至那些使用RTTI关闭编译的类,都有一定级别的元数据可用。特别是可以获得
    类的名称和继承结构。对于在调试器中碰巧看到的类的任何实例,都可以获得它的VMT,从而获得它的类名
Delphi使用描述表单内容的文本文件,并按名称连接事件处理程序。这种方法显然需要足够的元数据来反序列化from的文本表示,并通过名称连接eventhandlers

一些其他GUI工具包使用的另一种方法是自动生成代码,用于初始化表单并用代码连接事件处理程序。由于此代码直接使用指向EventHandler的指针,并直接分配给属性/调用设置器,因此它不需要任何元数据。这样做的副作用是倒车变得更困难

创建一个程序,将dfm文件转换为一系列硬编码指令,从而创建表单,应该不会太难。所以像DeDe这样的工具再也不能正常工作了。但这在实践中并没有给你带来多少好处


但是,确定哪个evenhandler对应于哪个控件/事件仍然相当容易。特别是因为像调情这样的东西可以识别大多数库函数。因此,您只需中断感兴趣的代码,然后进入用户代码。

在Delphi中,唯一更容易的事情是检索VCL。 使用DeDe之类的反编译器后,您将获得应用程序用户界面,但没有任何逻辑。 因此,如果您只想检索表单和按钮-Delphi比其他编译器更容易,但是如果您想知道单击按钮后发生了什么,您需要使用ollydbg或其他(调试器/反汇编程序),就像其他创建可执行文件的语言一样。

战壕故事:反编译一个小型Delphi DLL 我自己也参加过一次Delphi反编译会议。这是一个听起来虚假的“我失去了我的资料来源”的事情,我真的失去了一个小小的Firebird UDF库的资料来源。现在我没有做得更好了,我没有马上开始反编译,因为库太小了,我知道重写会快得多

此DLL导出的函数如下所示:

function udf_do_some_math(Number1, Number2:Currency): Currency;
在做了合理的事情,重写了函数,做了一些回归测试之后,我发现了一些模糊的情况,新函数的结果与旧函数的结果不一样!问题是,新函数的结果是正确的,旧的DLL包含一个错误,我不得不重现这个错误-使用这个函数,一致性比准确性更重要

再次,做了理智的事情,并试图“猜测”错误。我知道这是一个取整的问题,但就是搞不清楚它是什么。最后,我决定尝试使用反编译器。毕竟这是一个很小的库,入口点很简单,我不需要重新编译代码,也不需要100%的反编译:我只需要足够的时间来找出旧的BUG,这样我就可以复制它了

反编译失败我尝试了很多不同的反编译器,包括一些“商业”的。大多数都产生了表面上看起来不错的数据,但还不足以找出旧的bug。最有希望的一个,具有VCL和RTL版本特定知识的一个给出了最严重的失败:当然,它找出了RTL调用,给出了它们的名称,,但找不到导出的函数!我感兴趣的一个函数没有显示在入口点列表中,它应该是直接的,因为它是一个导出的函数

此反编译尝试应该很容易,因为:

  • 代码相当简单,而且不是很多
  • 它是一个带有导出函数的DLL,没有事件驱动exe所期望的复杂性
  • 我对可重新编译的代码不感兴趣,我只是想找到一个旧的bug,这样我就可以重现它
  • 我并没有要求Pascal代码,汇编程序已经足够好了
  • 我确切地知道代码在做什么,以及它是如何做的。这不是神秘的第三方代码
我的解决方案 在反编译器失败后,我转向自己信任的DelphiIDE进行调试。我编写了一个小的Delphi程序,直接从DLL中导入函数,创建了一个假的Firbird内存管理器DLL,这样我的DLL就可以加载,用我知道会产生不良结果的参数调用我的旧函数,使用调试器分步进入代码,并密切关注FPU寄存器。在几次失败的尝试之后,我终于注意到一个值从FPU堆栈中弹出为整数,它不应该是整数,所以我有了错误:我错误地定义了一个整数局部变量,我应该在其中使用Currency。用这个武装起来