【问题标题】:Obtaining source code from the binary从二进制文件中获取源代码
【发布时间】:2015-05-26 22:26:01
【问题描述】:

难道不能从它的二进制文件中获取源代码吗? 既然编译就是将高级语言(源代码)转化为低级语言(机器码)的过程,难道我们不能把这个过程倒过来就可以得到源代码吗?如果不是,为什么?

【问题讨论】:

    标签: compilation binary


    【解决方案1】:

    假设我给你数字3,并告诉你我是通过将两个数字相加得到的。你能告诉我3 是两个数字的和吗?这是不可能的,因为 sum 是一个单向函数——不可能从它的输出中恢复它的参数。我可以从 -55 和 58 获得它,即使 为你 1 和 2 仍然可以得到相同的答案。

    编译类似。有无数个 C++ 程序会生成任何特定的机器代码输出(或多或少)。

    您当然可以反转编译过程并生成 C 或 C++ 代码,这些代码至少会产生具有相同语义(含义)但可能不是逐字节相同的机器代码。此类工具在不同程度上存在。

    所以是的,这是可能的,但是由于源代码中的很多信息必然会丢失,因此您将取回的代码不会产生深入了解原始源代码的设计。对于任何大型项目,你得到的都是做同样事情的代码,但对人类来说几乎是不可读的。它会是一些非常非常模糊的 C/C++。

    为什么会丢失信息?因为高级语言的全部意义在于它们应该对人类有效地处理。源代码越高级和易于理解,它与编译器完成时产生的机器代码的差异就越大。作为软件设计师,您的主要目标是利用编译器和其他代码生成工具将高级想法和概念转换为机器代码。两者之间的差距越大,关于高级设计的信息就越多。

    请记住,编译器唯一需要保留的是代码的语义(含义)。只要显示代码正在按照您的意思执行,一切都很好。例如,现代编译器可以预先执行部分代码并仅存储操作的结果,前提是根据某些指标这样做是“有意义的”。假设您的整个程序如下所示:

    #include <iostream>
    #include <cmath>
    int main() {
      std::cout << sin(1)+cos(2) << std::endl;
      return 0;
    }
    

    假设是 Unix 系统,编译器完全有权生成执行 两个 系统调用的机器代码:写入标准输出、使用常量缓冲区和退出。反编译此类代码后,您可以获得:

    #include <unistd.h>
    #include <cstdlib>
    int main() {
      write(0, "0.425324\n", 9);
      exit(0);
    }
    

    【讨论】:

    • 非常感谢您的详细回答。抱歉,我无法为这个答案投票(我是 stackoverflow 的新用户,我没有足够的积分)。
    猜你喜欢
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-11
    • 1970-01-01
    • 2012-11-27
    • 1970-01-01
    相关资源
    最近更新 更多