2012-04-19 190 views
5

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

我以前的知识,我相信我会找不到直接调用的可执行文件入口点给printf,我是对的。 我发现了很多代码,这些代码在编译过程中不是由我编写的,而是由编译器添加的。

我想更好地理解在编译过程中添加的代码。 它是做什么的? 是否有任何“技巧”快速找到“主”,并跳过反汇编生成的所有不必要的代码?

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

  1. CrtlStartUp

  2. 主要

  3. CrtlCleanUp

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

+5

非常的编译器和平台特定的。我怀疑你会得到你想要的确切答案。 – Matt 2012-04-19 16:51:28

+1

我推荐[此帖](http://stackoverflow.com/a/9952374/176769)作为一个路线图,任何反向工程师导师崇拜者的人。 – karlphillip 2012-04-19 16:53:56

+1

我在逆向工程方面没有经验,但是不能简单地在main的开始处设置调试器断点以获取相对地址?或者,也可以在可执行文件的对象转储中查找main? – bjhend 2012-04-19 16:55:02

回答

4

您可能会遇到C++标准所要求的各种各样的东西。

最重要的是,需要有代码来处理之前主要在主翻译单元的任何静态的建筑被称为,并且主要的树叶后处理销毁的功能。此外,该标准需要一个功能atexit,允许您注册主返回后调用的其他功能。

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

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

如果您使用任何标准库,这是相当多的工作。请记住,std :: cout是一个静态对象(静态生命期,而不是静态链接 - 易混淆重载的单词警报)。所以这意味着建立与你的控制台的通信,这将有你的平台所需的任何API。标准中有很多这样的对象。

然后,有可能是特定于您的平台和/或编译器,准备在一些有效的方式处理,或解析环境变量,或负载“标准”动态/共享库,或类似的东西的东西。

通常,出口刚刚会走路该名单并以某种方式提供的main函数的返回值的环境,因为大多数现代操作系统后自行清理,但有可能是系统具体的东西,除了这一点。

2

现今的编译器创建可执行大规模所以,即使你会发现入口点它会带你一段时间来理解并得到你真正需要的部分。

在你的情况与世界你好应用程序,你可以使用IDA找到函数列表对话框中输入点(我不记得确切的名称)。但是我再次不推荐这种方法,除非应用程序非常小。

我用我称之为“下往上办法”(C)

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

下一步是拆卸程序,寻找那些“弱点”(在IDA串模块),然后找到他们所使用的功能(你可以使用新的IDA版本的图形层次视图)

对它们的引用

如果你还不知道它是如何工作的,或者这个代码从很多地方调用,你不知道你需要什么。您可以从运行时分析开始并使用调试器(softice?:)),如ollydbg。这会向你展示静态分析不可见的东西,比如虚函数/函数指针,例如:call EAX。

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