5

今天我决定使用 IDA Pro 反编译一个用 Visual C++ 编写的简单“Hello world”程序。

以我以前的知识,我确信我不会在可执行入口点找到对 printf 的立即调用,我是对的。发现很多代码不是我写的,是编译器在编译过程中添加的。

我想更好地了解在编译过程中添加了哪些代码。它有什么作用?有没有什么“技巧”可以快速找到“main”并跳过反汇编生成的所有不必要的代码?

我能找到的最好的是在这篇文章中:http: //www.codeproject.com/Articles/4210/C-Reverse-Disassembly,说使用Visual C++编译的可执行文件的执行顺序如下:

  1. Crtl启动

  2. 主要的

  3. CrtlCleanUp

请问我可以得到更详细的答案吗?

4

2 回答 2

4

您可能会遇到 c++ 标准要求的各种内容。

最重要的是,需要有代码在调用 main 之前处理主翻译单元中任何静态的构造,以及在 main 离开之后处理它们的破坏的函数。此外,该标准需要一个函数,该函数atexit允许您注册要在 main 返回后调用的附加函数。

因此,启动代码至少需要能够构建函数的数据结构,这些函数将在从 main 返回时被调用。这是一个动态数据结构,因为它需要由程序添加到运行时,并且调用的顺序与注册相反(因此通常您需要一个可以轻松添加到您步行的地方的数据结构)。

但此外,该标准要求在该翻译单元中执行任何函数之前,在其他翻译单元中创建静态。通常,编译器会简单地安排链接器中的所有内容,以便在 main 之前调用所有内容,但这不是必需的。那些以不同方式做事的编译器需要在其他链接的翻译单元代码中为初始化例程提供 thunk,该代码将在第一次函数调用时调用。

如果您使用任何标准库,这就是相当多的工作。请记住,std::cout 是一个静态对象(静态生命周期,而不是静态链接 - 令人困惑的重载单词 alert)。因此,这意味着建立与您的控制台的通信,该控制台将调用您的平台所需的任何 API。标准中有很多这样的对象。

然后,可能会有特定于您的平台和/或编译器的东西以某种有用的方式准备过程,或解析环境变量,或加载“标准”动态/共享库或类似的东西。

通常,exit 只是遍历该列表并以某种方式将 main 的返回值提供给环境,因为大多数现代操作系统会自行清理,但除此之外可能还有系统特定的东西。

于 2012-04-19T17:10:33.063 回答
2

今天的编译器创建了大量的可执行文件,所以即使你找到了入口点,你也需要一段时间来理解并找到你真正需要的部分。

在您使用 hello world 应用程序的情况下,您可以在函数列表对话框中使用 IDA find entry point(我不记得确切的名称)。但同样我不推荐这种方法,除非应用程序非常小。

我使用的方法我称之为“自下而上的方法”(c)

我将从分析应用程序的当前行为开始,而不涉及任何工具。这是非常重要的一步,可以节省大量时间,因为您将知道您在寻找什么以及何时发生。然后确定“弱点”,如字符串、可以使用静态分析工具 (IDA) 找到的常量值。

下一步是反汇编应用程序并查找那些“弱点”(IDA 中的字符串模块),然后从它们使用的函数中找到对它们的引用(您可以在新的 IDA 版本中使用图形层次视图)

如果您仍然无法了解它的工作原理或从许多地方调用此代码,您不知道您需要哪个。您可以从运行时分析开始并使用调试器(softice?:)),如 ollydbg。这将向您展示静态分析中不可见的东西,例如虚函数/函数指针:调用 EAX。

然后你只需一步一步地处理,直到你得到你需要的。

于 2012-04-19T17:46:04.713 回答