当前位置:网站首页>Debugging -- debugging objects and events

Debugging -- debugging objects and events

2022-06-09 04:36:00 Silent feather summer

Write it at the front

   This series is my word by word code , Including examples and experimental screenshots . Due to the complexity of the system kernel , Therefore, there may be errors or incompleteness , If there is a mistake , Welcome criticism and correction , This tutorial will be updated for a long time . If you have good advice , Welcome to feedback . It's not easy to code words , If this article helps you , If you have spare money , You can reward and support my creation . If you want to reprint , Please attach my reprint information to the back of the article , And declare my personal information and my blog address , but I must be informed in advance .

If you look from the middle , Please read... Carefully Yu xiakan Win system kernel —— sketch , Easy to learn this tutorial .

   Before viewing this tutorial , Ask a few questions , Have you prepared the basic knowledge ? Have you learned the chapter on protection mode ? Have you finished the exercise ? If not, don't continue .


Gorgeous dividing line


Debug object

   We all know that in Gao 2G The space is shared , The debug process and the debugged process are connected through the kernel object , The schematic diagram is as follows :

   How to call between the debugger and the debugged program API Build a connection ? One is through CreateProcess The debugging flag on the parameter is used to create a process , The other is DebugActiveProcess, Attach the running process directly . because DebugActiveProcess Relatively simple , This function is used for introduction , The following is its execution process :

graph TD kernel32!DebugActiveProcess --> 1[kernel32!DbgUiConnectToDbg] -..-> ntdll!ZwCreateDebugObject --> nt!NtCreateDebugObject 1 --> kernel32!DbgUiDebugActiveProcess -..-> ntdll!DbgUiDebugActiveProcess --> ntdll!NtDebugActiveProcess --> nt!NtDebugActiveProcess --> nt!DbgkpSetProcessDebugObject

   The complete detailed process will be summarized and improved . Let's first look at what the so-called debug object is :

typedef struct _DEBUG_OBJECT {
    //
    // Event thats set when the EventList is populated.
    //
    KEVENT EventsPresent;
    //
    // Mutex to protect the structure
    //
    FAST_MUTEX Mutex;
    //
    // Queue of events waiting for debugger intervention
    //
    LIST_ENTRY EventList;
    //
    // Flags for the object
    //
    ULONG Flags;
} DEBUG_OBJECT, *PDEBUG_OBJECT;

   Be careful , There is no... In the structure symbol , This is from WRK To obtain the .
  DEBUG_OBJECT What is the function of this , It is the bridge between the debugger process and the debugged process , If this bridge is demolished , They can't communicate , You can't debug :

   Next, let's look at how it built the bridge :

BOOL __stdcall DebugActiveProcess(DWORD dwProcessId)
{
  int res; // eax
  BOOL result; // eax
  void *handle; // esi
  int res_1; // edi

  res = DbgUiConnectToDbg();                    //  Create structure , Link to the debug object 
  if ( res >= 0 )
  {
    result = ProcessIdToHandle(dwProcessId);
    handle = result;
    if ( result )
    {
      res_1 = DbgUiDebugActiveProcess(result);
      NtClose(handle);
      if ( res_1 >= 0 )
      {
        result = 1;
      }
      else
      {
        BaseSetLastNTError(res_1);
        result = 0;
      }
    }
  }
  else
  {
    BaseSetLastNTError(res);
    result = 0;
  }
  return result;
}

   This function calls DbgUiConnectToDbg, It is important for us to guess this function by its name , Let's follow them :

int __stdcall DbgUiConnectToDbg()
{
  int result; // ecx
  OBJECT_ATTRIBUTES attr; // [esp+0h] [ebp-18h] BYREF

  result = 0;
  if ( !NtCurrentTeb()->DbgSsReserved[1] )
  {
    attr.Length = 24;
    attr.RootDirectory = 0;
    attr.Attributes = 0;
    attr.ObjectName = 0;
    attr.SecurityDescriptor = 0;
    attr.SecurityQualityOfService = 0;
    result = ZwCreateDebugObject(&NtCurrentTeb()->DbgSsReserved[1], 0x1F000Fu, &attr, 1u);
  }
  return result;
}

   It can be seen that , This function creates a debug object , And put it in TEB Of DbgSsReserved[1] member , That is, the offset 0xF24 Location , At this time, the connection between the debugger and the debugging object is established .
   Let's start to establish a relationship between the debugged object and the debugged object , Let's see DbgUiDebugActiveProcess function :

int __stdcall DbgUiDebugActiveProcess(HANDLE Handle)
{
  int res; // esi

  res = NtDebugActiveProcess(Handle, NtCurrentTeb()->DbgSsReserved[1]);
  if ( res >= 0 )
  {
    res = DbgUiIssueRemoteBreakin(Handle);
    if ( res < 0 )
      DbgUiStopDebugging(Handle);
  }
  return res;
}

   You can see , This function will call NtDebugActiveProcess Make connections , Here is the pseudocode :

NTSTATUS __stdcall NtDebugActiveProcess(HANDLE Process, HANDLE DebugObject)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]

  AccessMode = KeGetCurrentThread()->PreviousMode;
  result = ObReferenceObjectByHandle(Process, 0x800u, PsProcessType, AccessMode, &Process, 0);
  if ( result >= 0 )
  {
    process = Process;
    if ( Process == KeGetCurrentThread()->ApcState.Process || Process == PsInitialSystemProcess )
    {
      res = STATUS_ACCESS_DENIED;
    }
    else
    {
      res = ObReferenceObjectByHandle(DebugObject, 2u, DbgkDebugObjectType, AccessMode, &Process, 0);
      if ( res >= 0 )
      {
        if ( ExAcquireRundownProtection(&process->RundownProtect) )
        {
          v5 = DbgkpPostFakeProcessCreateMessages(&process->Pcb, Process, &DebugObject);
          res = DbgkpSetProcessDebugObject(process, Process, v5, DebugObject);
          ExReleaseRundownProtection(&process->RundownProtect);
        }
        else
        {
          res = STATUS_PROCESS_IS_TERMINATING;
        }
        ObfDereferenceObject(Process);
      }
    }
    ObfDereferenceObject(process);
    result = res;
  }
  return result;
}

   With pre knowledge , I will not repeat the previous process , Let's focus on DbgkpSetProcessDebugObject In this function :

NTSTATUS
DbgkpSetProcessDebugObject (
    IN PEPROCESS Process,
    IN PDEBUG_OBJECT DebugObject,
    IN NTSTATUS MsgStatus,
    IN PETHREAD LastThread
    )
/*++

Routine Description:

    Attach a debug object to a process.

Arguments:

    Process     - Process to be debugged
    DebugObject - Debug object to attach
    MsgStatus   - Status from queing the messages
    LastThread  - Last thread seen in attach loop.

Return Value:

    NTSTATUS - Status of call.

--*/
{
    NTSTATUS Status;
    PETHREAD ThisThread;
    LIST_ENTRY TempList;
    PLIST_ENTRY Entry;
    PDEBUG_EVENT DebugEvent;
    BOOLEAN First;
    PETHREAD Thread;
    BOOLEAN GlobalHeld;
    PETHREAD FirstThread;

    PAGED_CODE ();

    ThisThread = PsGetCurrentThread ();

    InitializeListHead (&TempList);

    First = TRUE;
    GlobalHeld = FALSE;

    if (!NT_SUCCESS (MsgStatus)) {
        LastThread = NULL;
        Status = MsgStatus;
    } else {
        Status = STATUS_SUCCESS;
    }

    //
    // Pick up any threads we missed
    //
    if (NT_SUCCESS (Status)) {

        while (1) {
            //
            // Acquire the debug port mutex so we know that any new threads will
            // have to wait to behind us.
            //
            GlobalHeld = TRUE;

            ExAcquireFastMutex (&DbgkpProcessDebugPortMutex);

            //
            // If the port has been set then exit now.
            //
            if (Process->DebugPort != NULL) {
                Status = STATUS_PORT_ALREADY_SET;
                break;
            }
            //
            // Assign the debug port to the process to pick up any new threads
            //
            Process->DebugPort = DebugObject;

            //
            // Reference the last thread so we can deref outside the lock
            //
            ObReferenceObject (LastThread);

            //
            // Search forward for new threads
            //
            Thread = PsGetNextProcessThread (Process, LastThread);
            if (Thread != NULL) {

                //
                // Remove the debug port from the process as we are
                // about to drop the lock
                //
                Process->DebugPort = NULL;

                ExReleaseFastMutex (&DbgkpProcessDebugPortMutex);

                GlobalHeld = FALSE;

                ObDereferenceObject (LastThread);

                //
                // Queue any new thread messages and repeat.
                //

                Status = DbgkpPostFakeThreadMessages (Process,
                                                      DebugObject,
                                                      Thread,
                                                      &FirstThread,
                                                      &LastThread);
                if (!NT_SUCCESS (Status)) {
                    LastThread = NULL;
                    break;
                }
                ObDereferenceObject (FirstThread);
            } else {
                break;
            }
        }
    }

    //
    // Lock the debug object so we can check its deleted status
    //
    ExAcquireFastMutex (&DebugObject->Mutex);

    //
    // We must not propagate a debug port thats got no handles left.
    //

    if (NT_SUCCESS (Status)) {
        if ((DebugObject->Flags&DEBUG_OBJECT_DELETE_PENDING) == 0) {
            PS_SET_BITS (&Process->Flags, PS_PROCESS_FLAGS_NO_DEBUG_INHERIT|PS_PROCESS_FLAGS_CREATE_REPORTED);
            ObReferenceObject (DebugObject);
        } else {
            Process->DebugPort = NULL;
            Status = STATUS_DEBUGGER_INACTIVE;
        }
    }

    for (Entry = DebugObject->EventList.Flink;
         Entry != &DebugObject->EventList;
         ) {

        DebugEvent = CONTAINING_RECORD (Entry, DEBUG_EVENT, EventList);
        Entry = Entry->Flink;

        if ((DebugEvent->Flags&DEBUG_EVENT_INACTIVE) != 0 && DebugEvent->BackoutThread == ThisThread) {
            Thread = DebugEvent->Thread;

            //
            // If the thread has not been inserted by CreateThread yet then don't
            // create a handle. We skip system threads here also
            //
            if (NT_SUCCESS (Status) && Thread->GrantedAccess != 0 && !IS_SYSTEM_THREAD (Thread)) {
                //
                // If we could not acquire rundown protection on this
                // thread then we need to suppress its exit message.
                //
                if ((DebugEvent->Flags&DEBUG_EVENT_PROTECT_FAILED) != 0) {
                    PS_SET_BITS (&Thread->CrossThreadFlags,
                                 PS_CROSS_THREAD_FLAGS_SKIP_TERMINATION_MSG);
                    RemoveEntryList (&DebugEvent->EventList);
                    InsertTailList (&TempList, &DebugEvent->EventList);
                } else {
                    if (First) {
                         DebugEvent->Flags &= ~DEBUG_EVENT_INACTIVE;
                        KeSetEvent (&DebugObject->EventsPresent, 0, FALSE);
                        First = FALSE;
                    }
                    DebugEvent->BackoutThread = NULL;
                    PS_SET_BITS (&Thread->CrossThreadFlags,
                                 PS_CROSS_THREAD_FLAGS_SKIP_CREATION_MSG);

                }
            } else {
                RemoveEntryList (&DebugEvent->EventList);
                InsertTailList (&TempList, &DebugEvent->EventList);
            }

            if (DebugEvent->Flags&DEBUG_EVENT_RELEASE) {
                DebugEvent->Flags &= ~DEBUG_EVENT_RELEASE;
                ExReleaseRundownProtection (&Thread->RundownProtect);
            }

        }
    }

    ExReleaseFastMutex (&DebugObject->Mutex);

    if (GlobalHeld) {
        ExReleaseFastMutex (&DbgkpProcessDebugPortMutex);
    }

    if (LastThread != NULL) {
        ObDereferenceObject (LastThread);
    }

    while (!IsListEmpty (&TempList)) {
        Entry = RemoveHeadList (&TempList);
        DebugEvent = CONTAINING_RECORD (Entry, DEBUG_EVENT, EventList);
        DbgkpWakeTarget (DebugEvent);
    }

    if (NT_SUCCESS (Status)) {
        DbgkpMarkProcessPeb (Process);
    }

    return Status;
}

   Because the result of pseudo code is similar to it , Renaming is complicated , Just use WRK Okay . Then you focus on the key code :

//
// Assign the debug port to the process to pick up any new threads
//
Process->DebugPort = DebugObject;

   In this way, the debugged process establishes a relationship with the debugged object .

Collection of debugging events

   Since the debugger process and the debugged process are connected through the debug object , If you want to communicate, you need to debug events ,DEBUG_OBJECT Of EventList Store debugging events .
   A debug event cannot be just one , The following is its enumeration :

typedef enum _DBGKM_APINUMBER
{
    DbgKmExceptionApi = 0,  // abnormal 
    DbgKmCreateThreadApi = 1,   // Create thread 
    DbgKmCreateProcessApi = 2,  // Create a process 
    DbgKmExitThreadApi = 3, // Thread to exit 
    DbgKmExitProcessApi = 4,    // Process exits 
    DbgKmLoadDllApi = 5,    // load DLL
    DbgKmUnloadDllApi = 6,  // uninstall DLL
    DbgKmErrorReportApi = 7,    // obsolete 
    DbgKmMaxApiNumber = 8,  // Maximum 
} DBGKM_APINUMBER; 

   front 7 The first is the kind of debugging events we can use , How are these debug events collected ?
   In the creation process 、 Thread function , Will go through the following process :

graph LR PspUserThreadStartup --> DbgkCreateThread --> DbgkpSendApiMessage

   On exiting a thread 、 In the function of the process , Will go through the following process :

graph LR PspExitThread --> DbgkExitThread/DbgkExitProcess --> DbgkpSendApiMessage

   In the function that loads the module , Will go through the following process :

graph LR NtMapViewOfSection --> DbgkMapViewOfSection --> DbgkpSendApiMessage

   In the function that unloads the module , Will go through the following process :

graph LR NtUnMapViewOfSection --> DbgkUnMapViewOfSection --> DbgkpSendApiMessage

   In an abnormal function , Will go through the following process :

graph LR KiDispatchException --> DbgkForwardException --> DbgkpSendApiMessage

   All of this is DbgkpSendApiMessage To implement the collection of debugging events , Let's take a look at the code :

NTSTATUS
DbgkpSendApiMessage(
    IN OUT PDBGKM_APIMSG ApiMsg,
    IN BOOLEAN SuspendProcess
    )

/*++

Routine Description:

    This function sends the specified API message over the specified
    port. It is the caller's responsibility to format the API message
    prior to calling this function.

    If the SuspendProcess flag is supplied, then all threads in the
    calling process are first suspended. Upon receipt of the reply
    message, the threads are resumed.

Arguments:

    ApiMsg - Supplies the API message to send.

    SuspendProcess - A flag that if set to true, causes all of the
        threads in the process to be suspended prior to the call,
        and resumed upon receipt of a reply.

Return Value:

    NTSTATUS.

--*/

{
    NTSTATUS st;
    PEPROCESS Process;

    PAGED_CODE();

    if ( SuspendProcess ) {
        SuspendProcess = DbgkpSuspendProcess();
    }

    ApiMsg->ReturnedStatus = STATUS_PENDING;

    Process = PsGetCurrentProcess();

    PS_SET_BITS (&Process->Flags, PS_PROCESS_FLAGS_CREATE_REPORTED);

    st = DbgkpQueueMessage (Process, PsGetCurrentThread (), ApiMsg, 0, NULL);

    ZwFlushInstructionCache (NtCurrentProcess (), NULL, 0);
    if ( SuspendProcess ) {
        DbgkpResumeProcess();
    }

    return st;
}

   By cross reference , We found the caller who called the function :

  PDBGKM_APIMSG It's a structure , Store message structure , Each message has its own message structure . Let's take a look at its members :

typedef struct _DBGKM_APIMSG {
    PORT_MESSAGE h;
    DBGKM_APINUMBER ApiNumber;
    NTSTATUS ReturnedStatus;
    union {
        DBGKM_EXCEPTION Exception;
        DBGKM_CREATE_THREAD CreateThread;
        DBGKM_CREATE_PROCESS CreateProcessInfo;
        DBGKM_EXIT_THREAD ExitThread;
        DBGKM_EXIT_PROCESS ExitProcess;
        DBGKM_LOAD_DLL LoadDll;
        DBGKM_UNLOAD_DLL UnloadDll;
    } u;
} DBGKM_APIMSG, *PDBGKM_APIMSG;

  SuspendProcess Parameter indicates whether to suspend other threads in the process except itself , such as int3, But some operations such as loading modules are not required .
   in summary ,DbgkSendApiMessage It is the main entry for debugging event collection , If you hang a hook here , The debugger will not be able to debug .
   All the remaining details about the collection of debugging events will be introduced in the summary and promotion chapter .

Handling of debugging events

   Handling of debugging events , We simply use API Implement a debugger , Here is the passage CreateProcess Implemented debugger :

#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
    char filename[]= "C:\\WINDOWS\\NOTEPAD.EXE";
    STARTUPINFO si ={sizeof(STARTUPINFO)};
    PROCESS_INFORMATION pi ;
    bool isContinue = true;
    DEBUG_EVENT dbgEvent;
        
    BOOL ret =CreateProcess(NULL,filename,NULL,NULL,FALSE,DEBUG_PROCESS|DEBUG_ONLY_THIS_PROCESS,NULL,NULL,&si,&pi);

    if (ret)
    {
        while (isContinue)
        {
            ret = WaitForDebugEvent(&dbgEvent,INFINITE);
            if (!ret)
            {
                printf("WaitForDebugEvent  error :%d",GetLastError());
                break;
            }

            switch (dbgEvent.dwDebugEventCode)
            {
            case EXCEPTION_DEBUG_EVENT:
                puts("EXCEPTION_DEBUG_EVENT");
                break;
            case CREATE_THREAD_DEBUG_EVENT:
                puts("CREATE_THREAD_DEBUG_EVENT");
                break;
            case CREATE_PROCESS_DEBUG_EVENT:
                puts("CREATE_PROCESS_DEBUG_EVENT");
                break;
            case EXIT_THREAD_DEBUG_EVENT:
                puts("EXIT_THREAD_DEBUG_EVENT");
                break;
            case EXIT_PROCESS_DEBUG_EVENT:
                puts("EXIT_PROCESS_DEBUG_EVENT");
                break;
            case LOAD_DLL_DEBUG_EVENT:
                puts("LOAD_DLL_DEBUG_EVENT");
                break;     
            case UNLOAD_DLL_DEBUG_EVENT:
                puts("UNLOAD_DLL_DEBUG_EVENT");
                break;
            case OUTPUT_DEBUG_STRING_EVENT:
                puts("OUTPUT_DEBUG_STRING_EVENT");
                break;
            default:
                break;
            }

            ret = ContinueDebugEvent(dbgEvent.dwProcessId,dbgEvent.dwThreadId,DBG_CONTINUE);

        }
    }
    else
    {
        printf(" Failed to create process :%d\n",GetLastError());
    }
        
    system("pause");
    return 0;
}

   After compiling and running , Its output is as follows :

CREATE_PROCESS_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
EXCEPTION_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT

   If you are careful, you may find EXCEPTION_DEBUG_EVENT, Our Notepad works normally , No exception occurred , Why is there this one ? Let's see what the address is , Modify the code area as follows :

case EXCEPTION_DEBUG_EVENT:
    printf("EXCEPTION_DEBUG_EVENT:0x%X\n",dbgEvent.u.Exception.ExceptionRecord.ExceptionAddress);
    break;

   Compile and run again , give the result as follows :

CREATE_PROCESS_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
EXCEPTION_DEBUG_EVENT:0x7C92120E
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT

  0x7C92120E This address must be in Dll Inside , This is the so-called system breakpoint , It's in LdrpInitializeProcess Functionally implemented , Here is the key pseudocode :

if ( peb->BeingDebugged )
{
  DbgBreakPoint();
  ShowSnaps = (peb->NtGlobalFlag & 2) != 0;
}

   Let's review the process of creating a process :

  1. mapping EXE file
  2. Create kernel objects EPROCESS
  3. mapping ntdll.dll
  4. Create a thread kernel object ETHREAD
  5. System startup thread , mapping DLL(ntdll.LdrInitializeThunk) Thread start execution

  LdrInitializeThunk Will determine whether this is the first thread created , If so, it will call LdrpInitializeProcess, And then determine PEB Of BeingDebugged Member to decide whether to drop the system breakpoint . meanwhile , We can de debug through this implementation .
   Let's take a look at how the debugger reaches the system breakpoint :

   Next , We do it in an additional form , The experimental code is as follows :

#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
    bool isContinue = true;
    DEBUG_EVENT dbgEvent;
    int pid;

    puts(" Please enter the... Of the debugging process  PID:");
    scanf("%d",&pid);
        
    BOOL ret =DebugActiveProcess(pid);

    if (ret)
    {
        while (isContinue)
        {
            ret = WaitForDebugEvent(&dbgEvent,INFINITE);
            if (!ret)
            {
                printf("WaitForDebugEvent  error :%d",GetLastError());
                break;
            }

            switch (dbgEvent.dwDebugEventCode)
            {
            case EXCEPTION_DEBUG_EVENT:
                puts("EXCEPTION_DEBUG_EVENT");
                break;
            case CREATE_THREAD_DEBUG_EVENT:
                puts("CREATE_THREAD_DEBUG_EVENT");
                break;
            case CREATE_PROCESS_DEBUG_EVENT:
                puts("CREATE_PROCESS_DEBUG_EVENT");
                break;
            case EXIT_THREAD_DEBUG_EVENT:
                puts("EXIT_THREAD_DEBUG_EVENT");
                break;
            case EXIT_PROCESS_DEBUG_EVENT:
                puts("EXIT_PROCESS_DEBUG_EVENT");
                break;
            case LOAD_DLL_DEBUG_EVENT:
                puts("LOAD_DLL_DEBUG_EVENT");
                break;     
            case UNLOAD_DLL_DEBUG_EVENT:
                puts("UNLOAD_DLL_DEBUG_EVENT");
                break;
            case OUTPUT_DEBUG_STRING_EVENT:
                puts("OUTPUT_DEBUG_STRING_EVENT");
                break;
            default:
                break;
            }

            ret = ContinueDebugEvent(dbgEvent.dwProcessId,dbgEvent.dwThreadId,DBG_CONTINUE);

        }
    }
    else
    {
        printf("DebugActiveProcess  Failure :%d\n",GetLastError());
    }
        
    system("pause");
    return 0;
}

   This debugging opens the Notepad , give the result as follows :

 Please enter the... Of the debugging process  PID:
1088
CREATE_PROCESS_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
LOAD_DLL_DEBUG_EVENT
CREATE_THREAD_DEBUG_EVENT
EXCEPTION_DEBUG_EVENT:0x7C92120E
EXIT_THREAD_DEBUG_EVENT

   This time you will find it strange , Now that we have all created threads , Why are there loads DLL, Create thread , What about the system breakpoint message ? Because these messages are false . This function is through DbgkpPostFakeProcessCreateMessages Realized :

iNTSTATUS
DbgkpPostFakeProcessCreateMessages (
    IN PEPROCESS Process,
    IN PDEBUG_OBJECT DebugObject,
    IN PETHREAD *pLastThread
    )
/*++

Routine Description:

    This routine posts the faked initial process create, thread create and mudule load messages

Arguments:

    ProcessHandle     - Handle to a process to be debugged
    DebugObjectHandle - Handle to a debug object

Return Value:

    None.

--*/
{
    NTSTATUS Status;
    KAPC_STATE ApcState;
    PETHREAD Thread;
    PETHREAD LastThread;

    PAGED_CODE ();

    //
    // Attach to the process so we can touch its address space
    //
    KeStackAttachProcess(&Process->Pcb, &ApcState);

    Status = DbgkpPostFakeThreadMessages (Process,
                                          DebugObject,
                                          NULL,
                                          &Thread,
                                          &LastThread);

    if (NT_SUCCESS (Status)) {
        Status = DbgkpPostFakeModuleMessages (Process, Thread, DebugObject);
        if (!NT_SUCCESS (Status)) {
            ObDereferenceObject (LastThread);
            LastThread = NULL;
        }
        ObDereferenceObject (Thread);
    } else {
        LastThread = NULL;
    }

    KeUnstackDetachProcess(&ApcState);

    *pLastThread = LastThread;

    return Status;
}

   I won't go into details , So much about this article .

Next

   Debugging —— Breakpoints and single steps

原网站

版权声明
本文为[Silent feather summer]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/03/202203021700455239.html