2012-04-19 172 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。

然後你只需處理一步一步,直到你得到你所需要的。