Win32除錯API 第三部分(轉)
在本章中,我們將繼續探討win32除錯api。特別地,我們將學習如何去跟蹤被除錯程式.
下載 例子.
理論:
如果你以前使用過偵錯程式,那麼你應對跟蹤比較熟悉。當"跟蹤"一個程式時,程式在每執行一條指令後將會停止,這使你有機會去檢查暫存器/記憶體中的值。這種單步執行的官方定義為跟蹤(tracing)。
單步執行的特色是由CPU本身提供的。標誌暫存器的第8位稱為陷阱標誌trap flag。如果該位設定,則CPU執行於單步模式。CPU將在每條指令後產生一個debug異常。當debug 異常產生後,陷阱標誌自動清除。利用win32除錯api,我們也可以單步執行被除錯程式。方法如下:
呼叫GetThreadContext, 指定 ContextFlags為CONTEXT_CONTROL, 來獲得標誌暫存器的值
設定CONTEXT結構成員標誌暫存器regFlag中的陷阱標誌位
呼叫 SetThreadContext
等待調式事件。被除錯程式將按單步模式執行,在每執行一條指令後,我們將得到除錯 事件,u.Exception.pExceptionRecord.ExceptionCode值為EXCEPTION_SINGLE_STEP
如果要跟蹤下一條指令,需要再次設定陷阱標誌位。
例:
.386
.model flat,stdcall
option casemap:none
include masm32includewindows.inc
include masm32includekernel32.inc
include masm32includecomdlg32.inc
include masm32includeuser32.inc
includelib masm32libkernel32.lib
includelib masm32libcomdlg32.lib
includelib masm32libuser32.lib
.data
AppName db "Win32 Debug Example no.4",0
ofn OPENFILENAME <>
FilterString db "Executable Files",0,"*.exe",0
db "All Files",0,"*.*",0,0
ExitProc db "The debuggee exits",0Dh,0Ah
db "Total Instructions executed : %lu",0
TotalInstruction dd 0
.data?
buffer db 512 dup(?)
startinfo STARTUPINFO <>
pi PROCESS_INFORMATION <>
DBEvent DEBUG_EVENT <>
context CONTEXT <>
.code
start:
mov ofn.lStructSize,SIZEOF ofn
mov ofn.lpstrFilter, OFFSET FilterString
mov ofn.lpstrFile, OFFSET buffer
mov ofn.nMaxFile,512
mov ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or OFN_EXPLORER or OFN_HIDEREADONLY
invoke GetOpenFileName, ADDR ofn
.if eax==TRUE
invoke GetStartupInfo,addr startinfo
invoke CreateProcess, addr buffer, NULL, NULL, NULL, FALSE, DEBUG_PROCESS+ DEBUG_ONLY_THIS_PROCESS, NULL, NULL, addr startinfo, addr pi
.while TRUE
invoke WaitForDebugEvent, addr DBEvent, INFINITE
.if DBEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT
invoke wsprintf, addr buffer, addr ExitProc, TotalInstruction
invoke MessageBox, 0, addr buffer, addr AppName, MB_OK+MB_ICONINFORMATION
.break
.elseif DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT .if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT
mov context.ContextFlags, CONTEXT_CONTROL
invoke GetThreadContext, pi.hThread, addr context
or context.regFlag,100h
invoke SetThreadContext,pi.hThread, addr context
invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE
.continue
.elseif DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_SINGLE_STEP
inc TotalInstruction
invoke GetThreadContext,pi.hThread,addr context or context.regFlag,100h
invoke SetThreadContext,pi.hThread, addr context
invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId,DBG_CONTINUE
.continue
.endif
.endif
invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED
.endw
.endif
invoke CloseHandle,pi.hProcess
invoke CloseHandle,pi.hThread
invoke ExitProcess, 0
end start
分析:
該程式先顯示一個開啟檔案對話方塊,當使用者選擇了一個可執行檔案,它將單步執行該程式,並記錄執行的指令數,直到被除錯程式退出執行。
.elseif DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT .if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT
利用該機會來設定被除錯程式為單步執行模式。記住,在執行被除錯程式的第一條指令前 windows將傳送一個EXCEPTION_BREAKPOINT訊息。
mov context.ContextFlags, CONTEXT_CONTROL
invoke GetThreadContext, pi.hThread, addr context
呼叫GetThreadContext,以被除錯程式的當前暫存器內容來填充CONTEXT 結構 特別地,我們需要標誌暫存器的當前值。
or context.regFlag,100h
設定標誌暫存器映象的陷阱位(第8位)
invoke SetThreadContext,pi.hThread, addr context
invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE
.continue
然後呼叫SetThreadContext去覆蓋CONTEXT的值。再以DBG_CONTINUE呼叫 ContinueDebugEvent 來恢復被除錯程式的執行。
.elseif DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_SINGLE_STEP
inc TotalInstruction
當除錯程式中一條指令執行後,我們將接收到EXCEPTION_DEBUG_EVENT的除錯事件, 必須要檢查u.Exception.pExceptionRecord.ExceptionCode的值。如果該值為 EXCEPTION_SINGLE_STEP,那麼,該除錯事件是單步執行模式造成的。在這種情況 下,TotalInstruction加一,因為我們確切地知道此時被除錯程式執行了一條指令。
invoke GetThreadContext,pi.hThread,addr context or context.regFlag,100h
invoke SetThreadContext,pi.hThread, addr context
invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId,DBG_CONTINUE
.continue
由於陷阱標誌在debug異常後自動清除了,如果我們需要繼續保持單步執行模式,則必須設定陷阱標誌位。
警告: 不要用本教程中的此例子來除錯大程式: 跟蹤是很慢的。你或許需要等待10 多分鐘才能關閉被除錯程式。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10172717/viewspace-928779/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Win32除錯API 第二部分(轉)Win32除錯API
- Win32除錯API學習心得(一) (轉)Win32除錯API
- win32除錯API學習心得(三) (轉)Win32除錯API
- Win32除錯API學習心得(二) (轉)Win32除錯API
- Win32除錯API的另類應用Win32除錯API
- Billy Belceb 病毒編寫教程for Win32 ----Win32 反除錯Win32除錯
- 計一次Win32 api程式顯示混亂問題的除錯經歷Win32API除錯
- Delphi Win32 API 使用的特殊情況 (轉)Win32API
- 139.API(除錯介面--開啟/關閉除錯)API除錯
- [Win32]一個偵錯程式的實現(五)除錯符號Win32除錯符號
- ASP.Net除錯之三板斧:第三招 (轉)ASP.NET除錯
- win32平臺下研究除錯SSL通訊機制Win32除錯
- Win32學習筆記 第三章 HelloWin (轉)Win32筆記
- Win32常用API講解Win32API
- react + Laravel Debugbar API 除錯ReactLaravelAPI除錯
- 10.0 探索API除錯事件原理API除錯事件
- Win32 API 登錄檔類的編制以及使用 (轉)Win32API
- Java除錯教程--多執行緒除錯(轉)Java除錯執行緒
- DLL的除錯 (轉)除錯
- 軟體除錯 (轉)除錯
- 機器學習最困難的部分:超引數除錯機器學習除錯
- perl除錯哲學(轉)除錯
- dbx除錯過程 (轉)除錯
- vc除錯經驗 (轉)除錯
- Bochs 除錯技術(轉)除錯
- 除錯最長的一幀(第三天)除錯
- 常用Win32 API函式簡介Win32API函式
- Get All IE Info from win32 apiWin32API
- [譯] 除錯 RxJS 第1部分: 工具篇除錯JS
- 核心除錯神器SystemTap 轉摘除錯
- [轉載]uiautomator埠除錯UI除錯
- NO MFC - 使用 .log 除錯程式 (轉)除錯
- 本地除錯PERL CGI程式(轉)除錯
- 用GDB除錯程式(二) (轉)除錯
- 用GDB除錯程式(四) (轉)除錯
- 用GDB除錯程式(三) (轉)除錯
- [譯] Xcode 和 LLDB 高階除錯教程:第 3 部分XCodeLLDB高階除錯
- [譯] Xcode 和 LLDB 高階除錯教程:第 1 部分XCodeLLDB高階除錯