⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lion-tut-c28.htm

📁 内有一些代码
💻 HTM
📖 第 1 页 / 共 2 页
字号:
      &nbsp;&nbsp;&nbsp;&lt;调试事件处理&gt;<br>
      &nbsp;&nbsp;&nbsp;invoke ContinueDebugEvent, DebugEvent.dwProcessId, DebugEvent.dwThreadId, 
      DBG_EXCEPTION_NOT_HANDLED <br>
      .endw </b><br>
    </p>
    <p>就是说,当开始调试程序时,我们的程序不能和debuggee分开直到它结束.</p>
  </li>
</ol>
<p>我们再来总结一下这些步骤:</p>
<ol>
  <li><b>创建一个进程或捆绑我们的程序到运行中的进程上</b>.</li>
  <li><b>等待调试事件</b></li>
  <li><b>响应调试事件</b>.</li>
  <li><b>继续执行debuggee</b>.</li>
  <li><b>继续这一无尽循环直到debuggee进程结束</b></li>
</ol>
<h3>例子:</h3>
<p>这个例子调试一个win32程序并显示诸如进程句柄,进程Id,映象基址等.</p>
<p>.386 <br>
  .model flat,stdcall <br>
  option casemap:none <br>
  include \masm32\include\windows.inc <br>
  include \masm32\include\kernel32.inc <br>
  include \masm32\include\comdlg32.inc <br>
  include \masm32\include\user32.inc <br>
  includelib \masm32\lib\kernel32.lib <br>
  includelib \masm32\lib\comdlg32.lib <br>
  includelib \masm32\lib\user32.lib <br>
  .data <br>
  AppName db "Win32 Debug Example no.1",0 <br>
  ofn OPENFILENAME <> <br>
  FilterString db "Executable Files",0,"*.exe",0 <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db 
  "All Files",0,"*.*",0,0 <br>
  ExitProc db "The debuggee exits",0 <br>
  NewThread db "A new thread is created",0 <br>
  EndThread db "A thread is destroyed",0 <br>
  ProcessInfo db "File Handle: %lx ",0dh,0Ah <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db "Process 
  Handle: %lx",0Dh,0Ah <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db "Thread 
  Handle: %lx",0Dh,0Ah <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db "Image 
  Base: %lx",0Dh,0Ah <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db "Start 
  Address: %lx",0 <br>
  .data? <br>
  buffer db 512 dup(?) <br>
  startinfo STARTUPINFO <> <br>
  pi PROCESS_INFORMATION <> <br>
  DBEvent DEBUG_EVENT <> <br>
  .code <br>
  start: <br>
  mov ofn.lStructSize,sizeof ofn <br>
  mov ofn.lpstrFilter, offset FilterString <br>
  mov ofn.lpstrFile, offset buffer <br>
  mov ofn.nMaxFile,512 <br>
  mov ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or OFN_EXPLORER 
  or OFN_HIDEREADONLY <br>
  invoke GetOpenFileName, ADDR ofn <br>
  .if eax==TRUE <br>
  invoke GetStartupInfo,addr startinfo <br>
  invoke CreateProcess, addr buffer, NULL, NULL, NULL, FALSE, DEBUG_PROCESS+ DEBUG_ONLY_THIS_PROCESS, 
  NULL, NULL, addr startinfo, addr pi <br>
  .while TRUE <br>
  &nbsp;&nbsp;&nbsp;invoke WaitForDebugEvent, addr DBEvent, INFINITE <br>
  &nbsp;&nbsp;&nbsp;.if DBEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke MessageBox, 0, addr ExitProc, addr 
  AppName, MB_OK+MB_ICONINFORMATION <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .break <br>
  &nbsp;&nbsp; .elseif DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke wsprintf, addr buffer, addr ProcessInfo, 
  DBEvent.u.CreateProcessInfo.hFile, DBEvent.u.CreateProcessInfo.hProcess, DBEvent.u.CreateProcessInfo.hThread, 
  DBEvent.u.CreateProcessInfo.lpBaseOfImage, DBEvent.u.CreateProcessInfo.lpStartAddress 
  <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke MessageBox,0, addr buffer, addr 
  AppName, MB_OK+MB_ICONINFORMATION &nbsp;&nbsp;&nbsp;<br>
  &nbsp;&nbsp; .elseif DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT 
  <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;invoke ContinueDebugEvent, 
  DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.continue <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .endif <br>
  &nbsp;&nbsp; .elseif DBEvent.dwDebugEventCode==CREATE_THREAD_DEBUG_EVENT <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke MessageBox,0, addr NewThread, addr 
  AppName, MB_OK+MB_ICONINFORMATION <br>
  &nbsp;&nbsp; .elseif DBEvent.dwDebugEventCode==EXIT_THREAD_DEBUG_EVENT <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke MessageBox,0, addr EndThread, addr 
  AppName, MB_OK+MB_ICONINFORMATION <br>
  &nbsp;&nbsp; .endif <br>
  &nbsp;&nbsp; invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, 
  DBG_EXCEPTION_NOT_HANDLED <br>
  .endw <br>
  invoke CloseHandle,pi.hProcess <br>
  invoke CloseHandle,pi.hThread <br>
  .endif <br>
  invoke ExitProcess, 0 <br>
  end start </p>
<h3>分析:</h3>
<p>程序首先填充OPENFILENAME结构,调用GetOpenFileName让用户选择要调试的程序.</p>
<p>invoke GetStartupInfo,addr startinfo <br>
  invoke CreateProcess, addr buffer, NULL, NULL, NULL, FALSE, DEBUG_PROCESS+ DEBUG_ONLY_THIS_PROCESS, 
  NULL, NULL, addr startinfo, addr pi </p>
<p>当接收用户选择后,调用<b>CreateProcess</b>装载程序.并调用<b>GetStartupInfo</b>以默认值填充<b>STARTUPINFO</b>结构.注意我们将<b>DEBUG_PROCESS</b>标志与<b>DEBUG_ONLY_THIS_PROCESS</b>标志组合来仅调试这个程序,不包括子进程.</p>
<p>.while TRUE <br>
  &nbsp;&nbsp;&nbsp;invoke WaitForDebugEvent, addr DBEvent, INFINITE <br>
</p>
<p>在debuggee被装入后,我们调用<b>WaitForDebugEvent</b>进入无尽的调试循环,<b>WaitForDebugEvent</b>在debuggee中发生调试事件时返回,因为我们指定了<b>INFINITE</b>作为第二个参数.当调试事件发生时, 
  <b>WaitForDebugEvent </b>返回并填充DBEvent结构.</p>
<p>&nbsp;&nbsp;&nbsp;.if DBEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke MessageBox, 0, addr ExitProc, addr 
  AppName, MB_OK+MB_ICONINFORMATION <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .break </p>
<p>我们要先检查<b>dwDebugEventCode</b>的值, 如果是<b>EXIT_PROCESS_DEBUG_EVENT,</b>用一个消息框显示&quot;The 
  debuggee exits&quot; 并退出调试循环.</p>
<p> &nbsp;&nbsp; .elseif DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT 
  <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke wsprintf, addr buffer, addr ProcessInfo, 
  DBEvent.u.CreateProcessInfo.hFile, DBEvent.u.CreateProcessInfo.hProcess, DBEvent.u.CreateProcessInfo.hThread, 
  DBEvent.u.CreateProcessInfo.lpBaseOfImage, DBEvent.u.CreateProcessInfo.lpStartAddress 
  <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke MessageBox,0, addr buffer, addr 
  AppName, MB_OK+MB_ICONINFORMATION &nbsp;&nbsp;&nbsp;</p>
<p>如果<b>dwDebugEventCode</b> 的值为<b>CREATE_PROCESS_DEBUG_EVENT</b>,我们就在消息框中显示一些感兴趣的底层信息.这些信息从<b>u.CreateProcessInfo</b>获得. 
  CreateProcessInfo是一个<b>CREATE_PROCESS_DEBUG_INFO</b>类型的结构体.你可以查阅Win32 API获得它的更多信息e. 
</p>
<p> &nbsp;&nbsp; .elseif DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT 
  <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;invoke ContinueDebugEvent, 
  DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.continue <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .endif </p>
<p>如果<b>dwDebugEventCode</b> 的值为<b>EXCEPTION_DEBUG_EVENT</b>,我们就要更进一步检查异常类型.它是一大堆的结构嵌套,但我们可以从<b>ExceptionCode</b>成员获得异常类型.如果<b>ExceptionCode</b>的值为 
  <b>EXCEPTION_BREAKPOINT</b>并且是第一次发生(或者我们已知道deuggee中没有int 3h指令),我们可以安全地假定在debuggee要执行第一条指令时发生这一异常.在我们完成这些处理后,就可以用 
  <b>DBG_CONTINUE</b>调用<b>ContinueDebugEvent</b>来继续执行debuggee.接着我们继续等待下一个调试事件的发生.</p>
<p> &nbsp;&nbsp; .elseif DBEvent.dwDebugEventCode==CREATE_THREAD_DEBUG_EVENT <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke MessageBox,0, addr NewThread, addr 
  AppName, MB_OK+MB_ICONINFORMATION <br>
  &nbsp;&nbsp; .elseif DBEvent.dwDebugEventCode==EXIT_THREAD_DEBUG_EVENT <br>
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; invoke MessageBox,0, addr EndThread, addr 
  AppName, MB_OK+MB_ICONINFORMATION <br>
  &nbsp;&nbsp; .endif </p>
<p>如果<b>dwDebugEventCode</b> 的值为<b>CREATE_THREAD_DEBUG_EVENT</b>或<b>EXIT_THREAD_DEBUG_EVENT</b>, 
  我们的程序显示一个消息框.</p>
<p> &nbsp;&nbsp; invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, 
  DBG_EXCEPTION_NOT_HANDLED <br>
  .endw </p>
<p>除了上面讨论过的<b> EXCEPTION_DEBUG_EVENT</b>,用<b>DBG_EXCEPTION_NOT_HANDLED</b>标志调用<b>ContinueDebugEvent</b>函数恢复debuggee的执行.</p>
<p>invoke CloseHandle,pi.hProcess <br>
  invoke CloseHandle,pi.hThread </p>
<p>当debuggee结束时,我们就跳出了调试循环,这时要关闭 debuggee的线程和进程句柄.关闭这些句柄并不意味着要关闭这些进程和线程.只是说不再用这些句柄罢了. 
</p>
<HR SIZE=1>
<DIV align=center> 
  <SCRIPT language=JavaScript1.1 src="../lion-tut-c13.files/textclick"></SCRIPT>
  <BR>
</DIV>
<!-- 10:1 文本广告交换 --> 
<DIV align=center> 
  <SCRIPT language=JavaScript1.1 src="../lion-tut-c13.files/c21.htm"></SCRIPT>
  <!-- 10:1 文本广告交换 --></DIV>
<HR SIZE=1>
<DIV align=center>校对:LuoYunBin's Win32 ASM Page, <A 
href="http://asm.yeah.net/">http://asm.yeah.net</A></DIV>
</BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -