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

📄 lion-tutorial28.htm

📁 内有一些代码
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<html>

<head>
<link rel="stylesheet" href="../../asm.css">

<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>Iczelion's win32 asm tutorial</title>
</head>

<body bgcolor="#FFFFFF" background="../../images/back01.jpg">
<p align="center">Tutorial 28: Win32 Debug API Part 1</p>
<hr size="1">
In this tutorial, you'll learn what Win32 offers to developers regarding debugging 
primitives. You'll know how to debug a process when you're finished with this 
tutorial. <br>
Download <b><a href="files/tut28.zip" style="text-decoration:none">the example</a></b>. 
<h3>Theory:</h3>
<p>Win32 has several APIs that allow programmers to use some of the powers of 
  a debugger. They are called Win32 Debug APIs or primitives. With them, you can:</p>
<ul>
  <li>Load a program or attach to a running program for debugging</li>
  <li>Obtain low-level information about the program you're debugging, such as 
    process ID, address of entrypoint, image base and so on.</li>
  <li>Be notified of debugging-related events such as when a process/thread starts/exits, 
    DLLs are loaded/unloaded etc.</li>
  <li>Modify the process/thread being debugged</li>
</ul>
<p>In short, you can code a simple debugger with those APIs. Since this subject 
  is vast, I divide it into several managable parts: this tutorial being the first 
  part. I'll explain the basic concepts and general framework for using Win32 
  Debug APIs in this tutorial.<br>
  The steps in using Win32 Debug APIs are:</p>
<ol>
  <li><b>Create a process or attach your program to a running process</b>. This 
    is the first step in using Win32 Debug APIs. Since your program will act as 
    a debugger, you need a program to debug. The program being debugged is called 
    a debuggee. You can acquire a debuggee in two ways: 
    <ul>
      <li>You can create the debuggee process yourself with <b>CreateProcess</b>. 
        In order to create a process for debugging, you must specify the <b>DEBUG_PROCESS</b> 
        flag. This flag tells Windows that we want to debug the process. Windows 
        will send notifications of important debugging-related events (debug events) 
        that occur in the debuggee to your program. The debuggee process will 
        be immediately suspended until your program is ready. If the debuggee 
        also creates child processes, Windows will also send debug events that 
        occur in all those child processes to your program as well. This behavior 
        is usually undesirable. You can disable this behavior by specifying <b>DEBUG_ONLY_THIS_PROCESS</b> 
        flag in combination of <b>DEBUG_PROCESS</b> flag. </li>
      <li>You can attach your program to a running process with <b>DebugActiveProcess.</b></li>
    </ul>
  </li>
  <li><b>Wait for debugging events</b>. After your program acquired a debuggee, 
    the debuggee's primary thread is suspended and will continue to be suspended 
    until your program calls <b>WaitForDebugEvent</b>. This function works like 
    other WaitForXXX functions, ie. it blocks the calling thread until the waited-for 
    event occurs. In this case, it waits for debug events to be sent by Windows. 
    Let's see its definition: 
    <p><b>WaitForDebugEvent proto lpDebugEvent:DWORD, dwMilliseconds:DWORD</b></p>
    <p><b>lpDebugEvent</b> is the address of a <b>DEBUG_EVENT</b> structure that 
      will be filled with information about the debug event that occurs within 
      the debuggee.</p>
    <p><b>dwMilliseconds</b> is the length of time in milliseconds this function 
      will wait for the debug event to occur. If this period elapses and no debug 
      event occurs,<b> WaitForDebugEvent</b> returns to the caller. On the other 
      hand, if you specify<b> INFINITE </b>constant in this argument, the function 
      will not return until a debug event occurs.</p>
    <p>Now let's examine the DEBUG_EVENT structure in more detail.</p>
    <p><b>DEBUG_EVENT STRUCT <br>
      &nbsp;&nbsp;&nbsp;dwDebugEventCode dd ? <br>
      &nbsp;&nbsp;&nbsp;dwProcessId dd ? <br>
      &nbsp;&nbsp;&nbsp;dwThreadId dd ? <br>
      &nbsp;&nbsp;&nbsp;u DEBUGSTRUCT <> <br>
      DEBUG_EVENT ENDS </b></p>
    <p><b>dwDebugEventCode</b> contains the value that specifies what type of 
      debug event occurs. In short, there can be many types of events, your program 
      needs to check the value in this field so it knows what type of event occurs 
      and responds appropriately. The possible values are:</p>
  </li>
  <table border="1" cellspacing="2" cellpadding="2" align="center">
    <tr bgcolor="#009999"> 
      <th><b>Value</b></th>
      <th>Meanings</th>
    </tr>
    <tr> 
      <td><b>CREATE_PROCESS_DEBUG_EVENT</b></td>
      <td>A process is created. This event will be sent when the debuggee process 
        is just created (and not yet running) or when your program just attaches 
        itself to a running process with <b>DebugActiveProcess</b>. This is the 
        first event your program will receive.</td>
    </tr>
    <tr> 
      <td><b>EXIT_PROCESS_DEBUG_EVENT</b></td>
      <td>A process exits.</td>
    </tr>
    <tr> 
      <td><b>CREATE_THEAD_DEBUG_EVENT</b></td>
      <td>A new thread is created in the debuggee process or when your program 
        first attaches itself to a running process. Note that you'll not receive 
        this notification when the primary thread of the debuggee is created. 
      </td>
    </tr>
    <tr> 
      <td height="131"><b>EXIT_THREAD_DEBUG_EVENT</b></td>
      <td height="131">A thread in the debuggee process exits. Your program will 
        not receive this event for the primary thread. In short, you can think 
        of the primary thread of the debuggee as the equivalent of the debuggee 
        process itself. Thus, when your program sees <b>CREATE_PROCESS_DEBUG_EVENT</b>, 
        it's actually the <b>CREATE_THREAD_DEBUG_EVENT</b> for the primary thread.</td>
    </tr>
    <tr> 
      <td><b>LOAD_DLL_DEBUG_EVENT</b></td>
      <td>The debuggee loads a DLL. You'll receive this event when the PE loader 
        first resolves the links to DLLs (you call <b>CreateProcess</b> to load 
        the debuggee) and when the debuggee calls LoadLibrary.</td>
    </tr>
    <tr> 
      <td><b>UNLOAD_DLL_DEBUG_EVENT</b></td>
      <td>A DLL is unloaded from the debuggee process. </td>
    </tr>
    <tr> 
      <td><b>EXCEPTION_DEBUG_EVENT</b></td>
      <td>An exception occurs in the debuggee process. <b>Important:</b> This 
        event will occur once just before the debuggee starts executing its first 
        instruction. The exception is actually a debug break (int 3h). When you 
        want to resume the debuggee, call <b>ContinueDebugEvent </b>with<b> DBG_CONTINUE 
        </b>flag. Don't use <b>DBG_EXCEPTION_NOT_HANDLED</b> flag else the debuggee 
        will refuse to run under NT (on Win98, it works fine).</td>
    </tr>
    <tr> 
      <td><b>OUTPUT_DEBUG_STRING_EVENT</b></td>
      <td>This event is generated when the debuggee calls <b>DebugOutputString</b> 
        function to send a message string to your program. </td>
    </tr>
    <tr> 
      <td><b>RIP_EVENT</b></td>
      <td>System debugging error occurs</td>
    </tr>
  </table>
  <p><b>dwProcessId</b> and <b>dwThreadId</b> are the process and thread Ids of 
    the process that the debug event occurs. You can use these values as identifiers 
    of the process/thread you're interested in. Remember that if you use <b>CreateProcess</b> 
    to load the debuggee, you also get the process and thread IDs of the debuggee 
    in the <b>PROCESS_INFO</b> structure. You can use these values to differentiate 
    between the debug events occurring in the debuggee and its child processes 
    (in case you didn't specify <b>DEBUG_ONLY_THIS_PROCESS </b>flag).</p>
  <p> <b>u</b> is a union that contains more information about the debug event. 
    It can be one of the following structures depending on the value of <b>dwDebugEventCode</b> 
    above. </p>
  <table border="1" cellspacing="2" cellpadding="2" align="center">
    <tr bgcolor="#009900"> 
      <th><b>value in dwDebugEventCode</b></th>
      <th>Interpretation of u</th>
    </tr>
    <tr> 
      <td><b>CREATE_PROCESS_DEBUG_EVENT</b></td>
      <td> A <b>CREATE_PROCESS_DEBUG_INFO</b> structure named <b>CreateProcessInfo</b></td>
    </tr>
    <tr> 
      <td><b>EXIT_PROCESS_DEBUG_EVENT</b></td>
      <td>An <b>EXIT_PROCESS_DEBUG_INFO structure named</b> ExitProcess</td>
    </tr>
    <tr> 
      <td><b>CREATE_THREAD_DEBUG_EVENT</b></td>
      <td>A <b>CREATE_THREAD_DEBUG_INFO</b> structure named <b>CreateThread</b></td>
    </tr>
    <tr> 
      <td><b>EXIT_THREAD_DEBUG_EVENT</b></td>
      <td>An <b>EXIT_THREAD_DEBUG_EVENT </b>structure named <b>ExitThread</b></td>
    </tr>
    <tr> 
      <td><b>LOAD_DLL_DEBUG_EVENT</b></td>
      <td>A <b>LOAD_DLL_DEBUG_INFO</b> structure named<b> LoadDll</b></td>
    </tr>
    <tr> 
      <td><b>UNLOAD_DLL_DEBUG_EVENT</b></td>
      <td>An <b>UNLOAD_DLL_DEBUG_INFO</b> structure named <b>UnloadDll</b></td>
    </tr>
    <tr> 
      <td><b>EXCEPTION_DEBUG_EVENT</b></td>
      <td>An <b>EXCEPTION_DEBUG_INFO</b> structure named <b>Exception</b></td>
    </tr>
    <tr> 
      <td><b>OUTPUT_DEBUG_STRING_EVENT</b></td>
      <td>An <b>OUTPUT_DEBUG_STRING_INFO </b>structure named <b>DebugString</b></td>
    </tr>
    <tr> 
      <td><b>RIP_EVENT</b></td>
      <td>A <b>RIP_INFO</b> structure named <b>RipInfo</b></td>
    </tr>
  </table>
  <p>I won't go into detail about all those structures in this tutorial, only 
    the <b>CREATE_PROCESS_DEBUG_INFO </b>structure will be covered here. <br>
    Assuming that our program calls <b>WaitForDebugEvent</b> and it returns. The 
    first thing we should do is to examine the value in <b>dwDebugEventCode</b> 
    to see which type of debug event occured in the debuggee process. For example, 
    if the value in <b>dwDebugEventCode</b> is <b>CREATE_PROCESS_DEBUG_EVENT</b>, 
    you can interpret the member in <b>u</b> as <b>CreateProcessInfo</b> and access 
    it with <b>u.CreateProcessInfo</b>. </p>
  <li><b>Do whatever your program want to do in response to the debug event</b>. 
    When <b>WaitForDebugEvent </b>returns, it means a debug event just occurred 
    in the debuggee process or a timeout occurs. Your program needs to examine 
    the value in <b>dwDebugEventCode</b> in order to react to the event appropriately. 
    In this regard, it's like processing Windows messages: you choose to handle 
    some and ignore some. </li>
  <li><b>Let the debuggee continues execution</b>. When a debug event occurs, 
    Windows suspends the debuggee. When you're finished with the event handling, 
    you need to kick the debuggee into moving again. You do this by calling <b>ContinueDebugEvent</b> 
    function. 
    <p><b>ContinueDebugEvent proto dwProcessId:DWORD, dwThreadId:DWORD, dwContinueStatus:DWORD</b></p>
    <p>This function resumes the thread that was previously suspended because 
      a debug event occurred.<br>
      <b>dwProcessId</b> and <b>dwThreadId</b> are the process and thread IDs 
      of the thread that will be resumed. You usually take these two values from 
      the <b>dwProcessId</b> and <b>dwThreadId</b> members of the <b>DEBUG_EVENT</b> 

⌨️ 快捷键说明

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