首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Delphi反编译

Delphi反编译
EN

Stack Overflow用户
提问于 2011-05-26 03:53:07
回答 5查看 16.9K关注 0票数 3

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

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-05-26 04:20:35

有几件事可以帮助我们逆转delphi程序:

  • 你可以得到完整的表单数据,包括事件处理方法的名称,
  • 所有具有published可见性的成员都有使用RTTI
  • 的元数据,编译器在优化方面做得很差。它不做整个程序的优化,汇编通常是原始源的直接翻译,只有很小的优化。(至少在我使用的版本中是这样的,从那以后可能会有所改进)
  • 所有的类,甚至那些关闭了RTTI编译的类都有一些元数据可用。特别是,可以获得classes的名称和继承结构。对于你碰巧在调试器中看到的类的任何实例,你都可以得到它的VMT,从而得到它的类名。

Delphi使用描述表单内容的文本文件,并按名称挂钩事件处理程序。这种方法显然需要足够的元数据来反序列化from的文本表示,并通过名称连接eventhandlers。

其他一些GUI工具包使用的另一种选择是自动生成代码,该代码初始化表单并用代码挂钩事件处理程序。由于此代码直接使用指向eventhandlers的指针,并直接分配给属性/调用setter,因此不需要任何元数据。这有一个副作用,那就是反转变得有点困难。

创建一个程序,将dfm文件转换为一系列硬编码的指令来创建表单,应该不会太难。因此,像DeDe这样的工具将不再能很好地工作。但在实践中,这并不会给你带来太多好处。

但是找出哪个事件处理程序对应于哪个控件/事件还是相当容易的。特别是因为像FLIRT这样的东西可以识别大多数库函数。因此,您只需要对您感兴趣的一个断点,然后进入用户代码。

票数 17
EN

Stack Overflow用户

发布于 2011-05-26 04:01:07

你所做的陈述是错误的。Delphi并不比其他主流编译器生成的代码更容易反编译。

.net languages的

如果您能够证明反编译Delphi可执行文件的结果比其他广泛使用的语言的质量要高得多,那么您的问题就会更有分量。

票数 18
EN

Stack Overflow用户

发布于 2011-05-26 12:16:56

来自战场的故事:反编译一个很小的Delphi DLL

我自己也经历过一次Delphi反编译会话。这是那些听起来像是“我失去了我的源码”的事情之一,我真的丢失了一个小小的Firebird UDF库的源码。现在我并没有做得更好,我没有直接开始反编译,因为这个库太小了,我知道重写会快得多。

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

代码语言:javascript
复制
function udf_do_some_math(Number1, Number2:Currency): Currency;

在做了正确的事情,重写了函数,并做了一些回归测试之后,我发现了一些模糊的角落--新函数的结果与旧函数的结果不同!问题是,新函数的结果是正确的,旧的DLL包含一个错误,我不得不重现错误-这个函数的一致性比准确性更重要。

再一次,我做了一件明智的事情,并试图“猜测”这个BUG。我知道这是一个四舍五入的问题,但就是不能弄清楚它是什么。最后,我决定给出我尝试过的反编译器。毕竟这只是一个很小的库,入口点很简单,我真的不需要可重新编译的代码,也不需要100%的反编译:我只需要足够的代码来找出旧的BUG,这样我就可以重新生成它!

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

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

  • 代码相当简单,而且不是很多。
  • 它是一个带有导出函数的动态链接库,没有你期望从事件驱动的可执行文件中看到的复杂性。
  • 我对可重新编译的代码不感兴趣,我只想找到一个旧的bug,这样我就可以重现它。
  • 我没有要求Pascal代码,汇编程序已经足够好了。

< code >H118我确切地知道代码在做什么,它是如何做的。这不是神秘的第三方代码。

我的解决方案

在反编译器失败后,我转向了我自己值得信赖的Delphi IDE进行调试。我写了一个小的Delphi程序,直接从DLL导入函数,创建了一个假的Firbird内存管理器DLL,这样我的DLL就可以加载了,用我知道会产生坏结果的参数调用我的旧函数,使用调试器逐步进入代码,并密切关注FPU寄存器。经过几次失败的尝试后,我终于注意到从FPU堆栈中弹出了一个整型值,而它不应该是integer,所以我有了我的BUG:我错误地定义了一个Integer局部变量,而我应该使用Currency。有了这些知识,我能够重现这个bug。

票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6130078

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档