调试事件的派发

Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html

调试事件的派发

一、异常事件采集派发

  查看这个案例 》一个简单的创建被调试进程的案例《,其中异常事件一共七种,调试器与被调试程序之间的通信就是根据内核的 DEBUG_OBJECT 来实现的。

  被调试程序发生的各种调试事件都会被放到 DEBUG_OBJECT.EventList 中,之后挂起,等待被调试程序收集。

 

二、以附加形式的调试事件派发

  1)假消息发送的大体流程

  当以附加形式,因为进程线程各种模块早已经被创建,这时只能模拟假消息发送。

  

 

  2)假消息不会被断下

  我们看WRK DbgkpQueueMessage源码时,发现其调用 KeWaitForSingleObject 是有条件的,当DEBUG_EVENT.flag 为 DEBUG_EVENT_NOWAIT 时并不会调用 KeWaitForSingleObject。

  而假消息被创建时就是 DEBUG_EVENT_NOWAIT

  原因也很好理解:因为线程进程模块早已被加载,这只是模拟过程,当然无法被断下

 1     if ((Flags&DEBUG_EVENT_NOWAIT) == 0) {
 2         ExReleaseFastMutex (&DbgkpProcessDebugPortMutex);
 3         if (NT_SUCCESS (Status)) {
 4             // 等待事件返回
 5             // 被调试进程在等待,之前转换为被调试进程的内存地址了。        
 6             KeWaitForSingleObject (&DebugEvent->ContinueEvent,
 7                                    Executive,
 8                                    KernelMode,
 9                                    FALSE,
10                                    NULL);
11             
12             // 拿到状态与要处理的事件,然后返回。
13             Status = DebugEvent->Status;
14             *ApiMsg = DebugEvent->ApiMsg;

 

 

三、当以调试选项创建进程时的调试事件派发

  这个相比于前面的“附加形式”,难度就小的多了。

  我们只需要在其进程创建的毕竟之路上判断其进程的DebugPort是否有值,如果有值则为调试状态,此时发送调试事件

  1)DbgkpSendApiMessage 函数

  在“加载模块”,“异常派发”,“创建线程”等等会引发调试事件的毕竟之路上会安排发送给调试器的函数,它们存在不同的形式。

  但是无论是什么种类,其仅负责构建ApiMsg信息,最终还是调用DbgkpSendApiMessage信息。

  可以参见如下函数引用:

  

  在创建线程时安排的调试信息发送函数

  

 

   2)DbgkpSendApiMessage 函数的详细介绍

  该函数的作用如下图,看WRK源码也很好理解

  

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;
}
posted @ 2019-11-19 23:43  OneTrainee  阅读(500)  评论(0编辑  收藏  举报