標籤:
http://bbs.pediy.com/showthread.php?p=1354999
標 題: 【原創】使用IDA PRO+OllyDbg+PEview 追蹤windows API 動態連結程式庫函數的調用過程。 作 者: shayi 時 間: 2015-02-12,05:19:54 鏈 接: http://bbs.pediy.com/showthread.php?t=197829
使用IDA PRO+OllyDbg+PEview 追蹤windows API 動態連結程式庫函數的調用過程。
(本文同步更新至我的51blog上,我最初是在那裡發布的,由於引用該處的圖片,因此帶有浮水印,該貼原始出處如下: http://shayi1983.blog.51cto.com/4681835/1613615 )
首先用文字編輯器寫一個C++來源程式名為StackFrame.cpp ,代碼如下:
代碼:#include "stdio.h"long add(long a, long b){ long x = a, y = b; return (x + y);}int main(int argc, char* argv[]){ long a = 1, b = 2; printf("%d\n", add(a, b)); return 0;}使用visual C++ IDE 對該源檔案執行編譯,彙編,連結一系列的操作後,最終產生的二進位可執行檔(PE格式)名為StackFrame.exe 回顧上述源碼,main函數調用了標準C庫函數printf列印資訊,我們想要知道, visual C++ 編譯器是如何?printf庫函數的,並且StackFrame.exe採用的是靜態連結還是動態連結,如果是後者,那麼printf又調用了哪些位於動態連結程式庫中的windows API函數?抑或是“動靜”兼用? 要解答這些疑問,首先使用IDA PRO開啟StackFrame.exe ,它會自動尋找程式進入點,這是由編譯器自動產生的啟動代碼,用於初始化我們編寫的main函數執行前的環境,以及執行main函數退出後的收尾工作。 一般而言,只要反組譯碼的對象不是經過加殼或者插入了模糊代碼,IDA PRO可以輕鬆識別程式進入點與main函數,這裡為了簡化分析流程,我們直接進入main函數的反組譯碼程式碼片段,如下所示:
我們通過上面一系列的IDA PRO可以看到,地址 0x00404063處的call指令想要調用EnterCriticalSection函數,後者的地址嘗試以call的運算元0x0040A018給出,但是這個地址處的值,即EnterCriticalSection函數的最終地址,需要作業系統載入器載入StackFrame.exe檔案時才能確定,因此我們對磁碟上的檔案反組譯碼時,無法確定動態連結程式庫中函數的地址。 下面以PEview工具查看StackFrame.exe在磁碟上的“真實”面貌(而不是由IDA PRO “類比”的運行時地址空間面貌) 之所以要先使用PEview工具,是因為後面的動態調試中,會與此處的資訊對比,來加深理解程式在磁碟上與在記憶體中的異同。 使用PEview工具開啟StackFrame.exe ,我們的重點是定位到PE檔案中的匯入表,因為無論是作業系統載入器,反組譯碼器,還是動態調試器,都依賴該表來解析匯入的動態連結程式庫與其中的函數。
我們嘗試在原始PE檔案中,計算並找出call ds:EnterCriticalSection 指令對應的位元組序列,其實這沒有想象中困難,而且在這裡提出計算方法的原因是,後面會用同樣的計算手法來判斷Ollydbg中追蹤到的EnterCriticalSection函數的實際地址, 該地址究竟屬於kernel32.dll還是ntdll.dll?(因為有時Ollydbg給出的資訊並不十分準確)屆時會用到下面的計算方法。
首先,回到IDA PRO,開啟StackFrame.exe的程式段視窗,如下所示:
前面指出,地址 0x00404063處的call指令想要調用EnterCriticalSection函數,因此計算 404063 - 401000 = 3063 , 3063 + 400 = 3463 3463這個值就是該指令位元組碼在StackFrame.exe的位置,下面驗證:
接下來,使用Ollydbg開啟StackFrame.exe進行動態調試,我們的目標在於定位EnterCriticalSection函數的入口處,並且單步跟進,查看其中的機器碼,然後使用PEview工具,以上面的計算方法,驗證Ollydbg給出的該函數所屬的動態連結程式庫檔案資訊是否準確,如下所示:
上面驗證了StackFrame.exe 在運行時調用的共用庫函數,與它在磁碟檔案上的匯入表中描述的行為一致。 最後,我們驗證EnterCriticalSection這個 windows API函確實位於ntdll.dll這個動態連結程式庫中,作為本案例的結尾。 首先,可以訪問微軟MSDN網站,尋找關於EnterCriticalSection函數的資訊: https://msdn.microsoft.com/zh-cn/library/windows/desktop/ms682608(v=vs.85).aspx
最後總結一下: stack.exe使用“部分”靜態連結,其中多數的代碼為庫代碼, 這包含由“編譯器庫”添加的,處理常式初始化的啟動代碼與程式退出善後的結束代碼, 以及程式中調用的庫函數,如printf等函數的代碼。 由於 printf 函數需要在螢幕列印資訊,涉及更底層的系統I/O操作,因此它需要調用封裝這些系統功能的 windows API 函數, 除了windows API 函數所在的DLL(kernel32.dll,ntdll.dll)作為動態連結程式庫在運行時載入以外, 所有其它被調用函數的二進位目標代碼都被連結器複製一份副本,然後連結到最終的可執行檔stack.exe中, 因此,stack.exe包含的庫代碼數量遠多於程式員自行編寫的代碼數量。 使用靜態連結的程式,很容易通過IDA PRO的全域函數調用拓撲圖識別出來,如下所示:
上面只是拋磚引玉,類似的將IDA PRO,Ollydbg,PEview,甚至WinHex,PEiD等工具結合起來應用,交叉驗證的例子不勝枚舉,通過熟練使用這些工具,不僅能提高逆向工程的效率與準確度,更重要的是,我們對處理器指令集體繫結構,作業系統記憶體管理,以及動態連結的機制,編譯器,連結器的運行原理等等系統底層機理的認識又提升了一個檔次。 最後,限於個人知識水平有限,文中若有錯誤以及誤導之處,還請提出指正,不勝感激。 有任何問題,看法,也歡迎提出討論。
*轉載請註明來自看雪論壇@PEdiy.com |
| |
此帖於 2015-02-12 16:03:59 被 shayi 最後編輯 [公告]如果你覺得有人語言挑釁,請點每帖右上方的“舉報”按鈕! |
共 8 位會員 感謝 shayi 發表的文章: |
dolphinzhu (2015-03-03), hbcld (2015-02-27), hrpirip (2015-02-26), Lnairan (2015-02-25), springkang[DFCG (2015-03-14), 學gg (2015-02-23), 雪衫 (2015-03-04), 馬來 (2015-06-07) |
lihuakx 初級會員 資 料:註冊日期: Feb 2015文章: 1 精華: 0現金: 50 Kx致謝數: 0獲感謝文章數:0 獲會員感謝數:0 |
寫的很清楚哦。 |
| |
[招生]15PB軟體安全培訓開始接受第009期報名(10.06開課)! |
shayi
普通會員 資 料:註冊日期: Jul 2012文章: 99 精華: 1現金: 93 Kx致謝數: 0獲感謝文章數:7 獲會員感謝數:28 |
補充一下,前面在查看絕大部分使用靜態連結的程式中,整個函數的調用拓撲,非常淩亂,我們甚至找不到main函數與最終的DLL函數入口 下面這張來自於 IDA PRO 的函數遞迴調用圖,把範圍縮小到了我們追蹤的從main()到 EnterCriticalSection() 的整個過程,驗證了前面在StackFrame的代碼節中的尋找工作:
|
| |
此帖於 2015-02-14 00:16:50 被 shayi 最後編輯 [招生]15PB軟體安全培訓開始接受第009期報名(10.06開課)! |
shayi
普通會員 資 料:註冊日期: Jul 2012文章: 99 精華: 1現金: 93 Kx致謝數: 0獲感謝文章數:7 獲會員感謝數:28 |
下面這張圖是用於產生的函數調用設定:
|
使用IDA PRO+OllyDbg+PEview 追蹤windows API 動態連結程式庫函數的調用過程