Win32除錯API學習心得(二) (轉)

worldblog發表於2007-08-16
Win32除錯API學習心得(二) (轉)[@more@]

上一章講解了如何用來開啟一個被除錯,並給出了一個簡單的例子,這一章將祥細講解除錯訊息包含的內容. 類似於訊息處理中的訊息結構TMessage一樣,除錯事件也有自己特定的事件結構,那就是TDeb ugEvent, TDeEvent在中的定義為:  TDebugEvent = _DEBUG_EVENT;  _DEBUG_EVENT = record  dwDebugEventCode: D;  dwProcessId: DWORD;  dwThreadId: DWORD;  case Integer of  0: (Exception: TExceptionDebugInfo);  1: (CreateThread: TCreateThreadDebugInfo);  2: (CreateProcessInfo: TCreateProcessDebugInfo);  3: (ExitThread: TExitThreadDebugInfo);  4: (ExitProcess: TExitThreadDebugInfo);  5: (LoadDll: TLoadDLLDebugInfo);  6: (UnloadDll: TUnloadDLLDebugInfo);  7: (DebugString: TOutputDebugStringInfo);  8: (RipInfo: TRIPInfo);  end; 這個結構很複雜,包含了三個基本型別和一個聯合型別的資料.dwProcessId和dwThreadId指明瞭產生除錯事件的程式和執行緒的ID,dwDebugEventCode指明瞭產生了何種除錯事件,可能的取值如下表(摘自<<>>): 1.CREATE_PROCESS_DEBUG_EVENT:程式被建立.當被除錯程式剛被建立(還未執行) 或我們的程式剛以DebugActiveProcess捆綁到一個執行中的程式時該事件發生. 這是我們的程式應該獲得的第一個事件.  2.EXIT_PROCESS_DEBUG_EVENT:被除錯程式退出時產生此訊息.  3.CREATE_THEAD_DEBUG_EVENT:當一個新執行緒在被除錯程式中建立或我們的程式首次捆綁到執行中的程式時該事件發生.要注意的是當被除錯程式的主執行緒被建立時不會收到該通知.  4.EXIT_THREAD_DEBUG_EVENT:被除錯程式中的執行緒退出時事件發生.被除錯程式的主執行緒退出時不會收到該通知.我們可以認為被除錯程式的主執行緒與被除錯程式是同義詞. 因此, 當我們的程式看到CREATE_PROCESS_DEBUG_EVENT標誌時,對主執行緒來說,就是CREATE_THREAD_DEBUG_E VENT標誌.  5.LOAD_DLL_DEBUG_EVENT:被除錯程式裝入一個DLL.當PE裝載器第一次分解指向DLL的連結時 ,我們將收到這一事件. (當CreateProcess裝入 被除錯程式時)並且當被除錯程式呼叫Lo adLibrary時也會發生.  6.UNLOAD_DLL_DEBUG_EVENT:一個DLL從被除錯程式中解除安裝時此事件發生.  7.EXCEPTION_DEBUG_EVENT:在被除錯程式中發生異常時事件發生.異常實際上是一個除錯中斷 (int 3h).如果想恢復被除錯程式事,以 G_CONTINUE 標誌呼叫ContinueDebugEvent .  不要使用DBG_EXCEPTION_NOT_HANDLED 標誌否則被除錯程式會在NT下拒絕執行(下執行得很好).  8.OUTPUT_DEBUG_STRING_EVENT:當被除錯程式呼叫DebugOutputString函式向我們的程式傳送訊息字串時該事件發生.  9.RIP_EVENT:除錯發生錯誤. 根據dwDebugEventCode的不同,應呼叫聯合中相應的結構來獲得相關的除錯資訊.例如我們有個名為Debug的TDebguEvent的結構,在呼叫WaitForDebugEvent(Debug, INFINITE)後接收到除錯資訊時,並且dwDebugEventCode的值為CREATE_PROCESS_DEBUG_EVENT,我們就可以透過仿問D ebug.CreateProcessInfo.hProcess來獲得剛建立的被除錯程式的程式控制程式碼. 下面將祥細講解TDebugEvent結構中可能包括的每個結構的含義.因為沒有相關的祥細資料,大部分結果是靠測試所得,如有錯漏敬請指正. 一.CreateProcessInfo結構: 對應的除錯訊息CREATE_PROCESS_DEBUG_EVENT. CreateProcessInfo.hFile:被除錯程式的EXE被對映到中的記憶體檔案對映控制程式碼,可以透過開啟這個控制程式碼(用OpenFileMap和MapViewOfFile)來讀取此EXE檔案的相關資訊.如引入引出表等. CreateProcessInfo.hProcess:被除錯程式的程式控制程式碼,如果要使用ReadProcessMemory和Wri teProcessMemory等函式來修改被除錯程式,就需要用到這個控制程式碼,可以用一個變數儲存起來供以後使用. CreateProcessInfo.hThread:主執行緒控制程式碼. CreateProcessInfo.lpBaseOfImage:可檔案被裝載到虛似地址空間中的基址. CreateProcessInfo.dwDebugInfoFileOffset:除錯資訊在可執行檔案中的偏移地址(一般為0 ,即沒有除錯資訊). CreateProcessInfo.nDebugInfoSize:除錯資訊的長度. CreateProcessInfo.lpThreadLocalBase:主執行緒基址. CreateProcessInfo.lpStartAddress:主執行緒的執行緒函式地址. CreateProcessInfo.lpImageName:檔案映像名,注意這是一個RVA地址(相對虛擬地址). CreateProcessInfo.fUnicode:如果此值大於0,則lpImageName指向的檔名為UNICODE碼. 二.ExitProcess結構: 對應的除錯訊息EXIT_PROCESS_DEBUG_EVENT. ExitProcess.dwExitCode:即被除錯程式呼叫ExitProcess函式時傳入的退出程式碼. 三.CreateThread結構: 對應的除錯訊息CREATE_THEAD_DEBUG_EVENT. CreateThread.hThread:新建執行緒的控制程式碼.執行緒控制程式碼,如果以後會涉及到對執行緒的操作,如掛起執行緒等,則可以用一個TList來儲存程式ID(TDebugEvent.dwThreadId)和相對應的控制程式碼.再在其它除錯事件發生時,根據dwThreadId得到執行緒控制程式碼. CreateThread.lpThreadLocalBase:新執行緒的基址. CreateThread.lpStartAddress:新執行緒的執行緒函式地址. 四.ExitThread結構: 對應的除錯訊息EXIT_THREAD_DEBUG_EVENT. ExitThread.dwExitCode:即退出的執行緒呼叫ExitThread函式時傳入的退出程式碼. 五.LoadDll結構: 對應的除錯訊息LOAD_DLL_DEBUG_EVENT. LoadDll.hFile:被載入的DLL檔案對映到記憶體中的記憶體檔案對映控制程式碼,可以透過開啟這個控制程式碼來讀取此DLL檔案的相關資訊. LoadDll.lpBaseOfDll:DLL檔案被裝載到虛似地址空間中的基址.這個地址加上DLL檔案引出的函式的地址,就是這個函式在記憶體中的地址. LoadDll.dwDebugInfoFileOffset:除錯資訊在DLL檔案中的偏移地址. LoadDll.nDebugInfoSize:除錯資訊的長度. LoadDll.lpImageName:DLL檔名的地址,是一個RVA地. LoadDll.fUnicode:如果此值大於0,則lpImageName指向的檔名為UNICODE碼. 六.UnLoadDll結構: 對應的除錯訊息UNLOAD_DLL_DEBUG_EVENT. UnloadDll.lpBaseOfDll:解除安裝的DLL檔案的基址,可以透過在處理LOAD_DLL_DEBUG_EVENT訊息中儲存DLL資訊和對應的基址的方法,來得到解除安裝的DLL資訊. 七.Exception結構: 對應的除錯訊息EXCEPTION_DEBUG_EVENT. Exception.ExceptionRecord: 這是一個TExceptionRecord結構,裡面包含了被除錯程式產生的中斷或異常的程式碼,產生的中斷或異常的地址等資訊. 八.DebugString結構: 對應的除錯訊息OUTPUT_DEBUG_STRING_EVENT. DebugString.lpDebugStringData:被除錯程式呼叫DebugOutputString函式傳送的訊息字串的地址. DebugString.nDebugStringLength:被除錯程式呼叫DebugOutputString函式傳送的訊息字串的長度. DebugString.fUnicode:如果此值大於0,則訊息字串為UNICODE碼. 九.RipInfo結構: 對應的除錯訊息RIP_EVENT. RipInfo.dwError:錯誤程式碼. RipInfo.dwType:錯誤型別. 瞭解了以上的知識,我們就可以在偵錯程式中監視這些除錯訊息,並獲得我們感興趣的資訊.但這僅僅實現了對被除錯除錯程式的監視.下一章將講解如何修改被除錯程式. 附:一個監視目標程式啟動,載入DLL,退出的例子,並演示瞭如何讀取RVA地址,獲得載入的DLL 檔名的方法.請到下面的地址.



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-962136/,如需轉載,請註明出處,否則將追究法律責任。

相關文章