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

📄 lion-tutorial28.htm

📁 内有一些代码
💻 HTM
📖 第 1 页 / 共 2 页
字号:
      structure.<br>
      dwContinueStatus specifies how to continue the thread that reported the 
      debug event. There are two possible values:<b> DBG_CONTINUE</b> and <b>DBG_EXCEPTION_NOT_HANDLED</b>. 
      For all other debug events, those two values do the same thing: resume the 
      thread. The exception is the <b>EXCEPTION_DEBUG_EVENT</b>. If the thread 
      reports an exception debug event, it means an exception occurred in the 
      debuggee thread. If you specify <b>DBG_CONTINUE</b>, the thread will ignore 
      its own exception handling and continue with the execution. In this scenario, 
      your program must examine and resolve the exception itself before resuming 
      the thread with <b>DBG_CONTINUE</b> else the exception will occur again 
      and again and again.... If you specify <b>DBG_EXCEPTION_NOT_HANDLED</b>, 
      your program is telling Windows that it didn't handle the exception: Windows 
      should use the default exception handler of the debuggee to handle the exception. 
      <br>
      In conclusion, if the debug event refers to an exception in the debuggee 
      process, you should call <b>ContinueDebugEvent</b> with <b>DBG_CONTINUE</b> 
      flag if your program already removed the cause of exception. Otherwise, 
      your program must call <b>ContinueDebugEvent</b> with <b>DBG_EXCEPTION_NOT_HANDLED</b> 
      flag. Except in one case which you must always use <b>DBG_CONTINUE</b> flag: 
      the first <b>EXCEPTION_DEBUG_EVENT</b> which has the value <b>EXCEPTION_BREAKPOINT</b> 
      in the ExceptionCode member. When the debuggee is going to execute its very 
      first instruction, your program will receive the exception debug event. 
      It's actually a debug break (int 3h). If you respond by calling <b>ContinueDebugEvent 
      </b>with <b>DBG_EXCEPTION_NOT_HANDLED</b> flag, Windows NT will refuse to 
      run the debuggee (because no one cares for it). You must always use <b>DBG_CONTINUE</b> 
      flag in this case to tell Windows that you want the thread to go on.</p>
  </li>
  <li><b>Continue this cycle in an infinite loop until the debuggee process exits</b>. 
    Your program must be in an infinite loop much like a message loop until the 
    debuggee exits. The loop looks like this: 
    <p><b>.while TRUE<br>
      &nbsp;&nbsp;&nbsp; invoke WaitForDebugEvent, addr DebugEvent, INFINITE<br>
      &nbsp;&nbsp;&nbsp;.break .if DebugEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT<br>
      &nbsp;&nbsp;&nbsp;&lt;Handle the debug events&gt;<br>
      &nbsp;&nbsp;&nbsp;invoke ContinueDebugEvent, DebugEvent.dwProcessId, DebugEvent.dwThreadId, 
      DBG_EXCEPTION_NOT_HANDLED <br>
      .endw </b><br>
    </p>
    <p>Here's the catch: Once you start debugging a program, you just can't detach 
      from the debuggee until it exits.</p>
  </li>
</ol>
<p>Let's summarize the steps again:</p>
<ol>
  <li><b>Create a process or attach your program to a running process</b>.</li>
  <li><b>Wait for debugging events</b></li>
  <li><b>Do whatever your program want to do in response to the debug event</b>.</li>
  <li><b>Let the debuggee continues execution</b>.</li>
  <li><b>Continue this cycle in an infinite loop until the debuggee process exits</b></li>
</ol>
<h3>Example:</h3>
<p>This example debugs a win32 program and shows important information such as 
  the process handle, process Id, image base and so on.</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>Analysis:</h3>
<p>The program fills the OPENFILENAME structure and then calls GetOpenFileName 
  to let the user choose a program to be debugged.</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>When the user chose one, it calls <b>CreateProcess</b> to load the program. 
  It calls <b>GetStartupInfo</b> to fill the <b>STARTUPINFO</b> structure with 
  its default values. Note that we use <b>DEBUG_PROCESS</b> combined with <b>DEBUG_ONLY_THIS_PROCESS</b> 
  flags in order to debug only this program, not including its child processes.</p>
<p>.while TRUE <br>
  &nbsp;&nbsp;&nbsp;invoke WaitForDebugEvent, addr DBEvent, INFINITE <br>
</p>
<p>When the debuggee is loaded, we enter the infinite debug loop, calling <b>WaitForDebugEvent.</b> 
  <b>WaitForDebugEvent</b> will not return until a debug event occurs in the debuggee 
  because we specify <b>INFINITE</b> as its second parameter. When a debug event 
  occurred, <b>WaitForDebugEvent </b>returns and DBEvent is filled with information 
  about the debug event.</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>We first check the value in <b>dwDebugEventCode</b>. If it's<b> EXIT_PROCESS_DEBUG_EVENT,</b> 
  we display a message box saying &quot;The debuggee exits&quot; and then get 
  out of the debug loop.</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>If the value in <b>dwDebugEventCode</b> is <b>CREATE_PROCESS_DEBUG_EVENT</b>, 
  then we display several interesting information about the debuggee in a message 
  box. We obtain those information from <b>u.CreateProcessInfo</b>. CreateProcessInfo 
  is a structure of type <b>CREATE_PROCESS_DEBUG_INFO</b>. You can get more info 
  about this structure from Win32 API reference. </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>If the value in <b>dwDebugEventCode</b> is <b>EXCEPTION_DEBUG_EVENT</b>, we 
  must check further for the exact type of exception. It's a long line of nested 
  structure reference but you can obtain the kind of exception from <b>ExceptionCode</b> 
  member. If the value in <b>ExceptionCode</b> is <b>EXCEPTION_BREAKPOINT</b> 
  and it occurs for the first time (or if we are sure that the debuggee has no 
  embedded int 3h), we can safely assume that this exception occured when the 
  debuggee was going to execute its very first instruction. When we are done with 
  the processing, we must call <b>ContinueDebugEvent</b> with <b>DBG_CONTINUE</b> 
  flag to let the debuggee run. Then we go back to wait for the next debug event.</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>If the value in <b>dwDebugEventCode</b> is <b>CREATE_THREAD_DEBUG_EVENT</b> 
  or <b>EXIT_THREAD_DEBUG_EVENT</b>, we display a message box saying so.</p>
<p> &nbsp;&nbsp; invoke ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, 
  DBG_EXCEPTION_NOT_HANDLED <br>
  .endw </p>
<p>Except for the<b> EXCEPTION_DEBUG_EVENT</b> case above, we call <b>ContinueDebugEvent</b> 
  with <b>DBG_EXCEPTION_NOT_HANDLED</b> flag to resume the debuggee.</p>
<p>invoke CloseHandle,pi.hProcess <br>
  invoke CloseHandle,pi.hThread </p>
<p>When the debuggee exits, we are out of the debug loop and must close both process 
  and thread handles of the debuggee. Closing the handles doesn't mean we are 
  killing the process/thread. It just means we don't want to use those handles 
  to refer to the process/thread anymore. <strong> </strong></p>
<hr size="1">
<div align="center"> This article come from Iczelion's asm page, Welcom to <a href="http://asm.yeah.net">http://asm.yeah.net</a></div>

</body>
</html>

⌨️ 快捷键说明

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