【问题标题】:Why is there no accurate C++ decompiler?为什么没有准确的 C++ 反编译器?
【发布时间】:2016-07-31 05:42:03
【问题描述】:

为什么不能创建一个 C++ 反编译器,其功能与为 Java 和 C# 制作的反编译器一样准确?

【问题讨论】:

  • 一个很好的问题。在调查并了解 C++ 如何编译为机器码以及 Java 是如何工作的之后,您应该能够很好地了解其中的原因。
  • 我觉得主要原因是c++没有提供任何运行时反射机制。
  • 看了这么多,这Q&A怎么还不重复?
  • 没有人愿意花费时间和精力来制作一个
  • JVM 字节码更接近源语言,即机器码更接近 C++ 源代码。 C++ 中有许多结构可以编译为相同的目标代码。对于 Java 来说,情况就不是这样了。

标签: c++ reverse-engineering decompiler


【解决方案1】:

有几个原因:

  1. 内联。许多 C++ 代码在优化的构建中被内联。这对任何形式的反编译器都会造成严重破坏。为了弄清楚一个函数是内联的,反编译器必须分析内联代码的细节并将它们匹配起来。并且内联后优化步骤可以使代码非常不同,具体取决于内联的位置。

  2. 模板。模板专门使用 #1,但它们会产生额外的问题。至少从理论上讲,在两个位置内联的函数将编译为相同的汇编指令序列。但是对于使用不同模板参数实例化的模板代码呢?不同的实例化通常必须编译成不同的指令序列。这变得更加困难,因为模板代码可以根据模板参数调用不同的函数集。这些函数本身可以内联。

  3. 编译时执行。模板元编程允许编译器实际执行代码。但是 C++11 的 constexpr 提供了一种更自然的方式来在编译时进行一些计算。显然,编译时函数调用或元函数实例不能成为已编译可执行文件的一部分。只有它们的结果才是(因为这有点意思)。

  4. 缺乏全面的运行时反射。 C# 和 Java 都在其字节码中添加了大量关于原始源代码性质的信息。对象定义很容易检测,对象名称、成员变量类型和名称等也是如此。C++ 编译为机器语言,不需要任何此类信息。而且由于它不是必需的,编译器不会生成它。甚至 ISO C++ 委员会的反射研究小组也专注于编译时反射,这是在运行时无法获得的信息。

    即使std::type_info 也不提供任何东西。原因是,如果编译器没有检测到特定类型将调用typeid,那么编译器不需要为它生成std::type_info 对象。即使是这样,给你的只是一个对象的名称(和一个标识符)。仅此而已。

【讨论】:

    【解决方案2】:

    因为 C++ 编译器通常不会将更多信息放入可执行文件中,而不是绝对必须的(尤其是在发布模式而不是调试版本编译时),因此您需要准确反编译程序的信息根本不存在于可执行文件中。

    当然,可以制作一个 C++ 编译器,在可执行文件中包含所有必要信息(例如,在最简单的实现中,它可以简单地将源代码本身的副本包含在可执行文件中),但这样做会使可执行文件显着变大,并且大多数非开源 C++ 开发人员希望其他人能够反编译可执行文件,因此对该功能的需求并不大。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-01
      • 1970-01-01
      • 2017-07-03
      相关资源
      最近更新 更多