彙編教程:Win32調試API(3)

來源:互聯網
上載者:User

在本章中,我們將繼續探討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 \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\user32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\user32.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 多分鐘才能關閉被偵錯工具。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.