首页
社区
课程
招聘
[求助]HOOK NtWaitForDebugEvent 遇到诡异事件
发表于: 2013-3-23 02:20 7975

[求助]HOOK NtWaitForDebugEvent 遇到诡异事件

2013-3-23 02:20
7975
前些日子  hook OD的 NtWaitForDebugEvent 函数,并通过驱动传入参数返回参数,
此钩子在 XP 系统调试成功,无任何异常,但是到了WIN7 却遇到了诡异的事情,在 WIN7挂钩后 附加到进程后 发现开始调用 NtWaitForDebugEvent等函数 没有问题,但是一下断点后
然后在运行,OD就假死了,失去响应,也有时候 附加后 运行大概10秒的时间,OD也假死
反汇编 WIN7 NtWaitForDebugEvent 大概看了下发现和XP没啥太大区别,DBGUI_WAIT_STATE_CHANGE 这个结构 WINDBG 无法查看,大体看了代码里结构的长度
和XP 一样都是60H,蛋疼啊,真心求解,郁闷好几天了,调用约定啥的一些可能问题都排除了
就是不知道咋回事,先谢谢了。。

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (9)
雪    币: 305
活跃值: (61)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
亲,我想你需要这个,去下载ReactOS的源码吧。以下是从 ReactOS\ntoskrnl\dbgk\dbgkobj.c 查到
NTSTATUS
NTAPI
NtWaitForDebugEvent(IN HANDLE DebugHandle,
                    IN BOOLEAN Alertable,
                    IN PLARGE_INTEGER Timeout OPTIONAL,
                    OUT PDBGUI_WAIT_STATE_CHANGE StateChange)
{
    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
    LARGE_INTEGER SafeTimeOut;
    PEPROCESS Process;
    LARGE_INTEGER StartTime;
    PETHREAD Thread;
    BOOLEAN GotEvent;
    LARGE_INTEGER NewTime;
    PDEBUG_OBJECT DebugObject;
    DBGUI_WAIT_STATE_CHANGE WaitStateChange;
    NTSTATUS Status = STATUS_SUCCESS;
    PDEBUG_EVENT DebugEvent = NULL, DebugEvent2;
    PLIST_ENTRY ListHead, NextEntry, NextEntry2;
    PAGED_CODE();
    DBGKTRACE(DBGK_OBJECT_DEBUG, "Handle: %p\n", DebugHandle);

    /* Clear the initial wait state change structure */
    RtlZeroMemory(&WaitStateChange, sizeof(WaitStateChange));

    /* Protect probe in SEH */
    _SEH_TRY
    {
        /* Check if we came with a timeout */
        if (Timeout)
        {
            /* Check if the call was from user mode */
            if (PreviousMode != KernelMode)
            {
                /* Probe it */
                ProbeForReadLargeInteger(Timeout);
            }

            /* Make a local copy */
            SafeTimeOut = *Timeout;
            Timeout = &SafeTimeOut;

            /* Query the current time */
            KeQuerySystemTime(&StartTime);
        }

        /* Check if the call was from user mode */
        if (PreviousMode != KernelMode)
        {
            /* Probe the state change structure */
            ProbeForWrite(StateChange, sizeof(*StateChange), sizeof(ULONG));
        }
    }
    _SEH_HANDLE
    {
        /* Get the exception code */
        Status = _SEH_GetExceptionCode();
    }
    _SEH_END;
    if (!NT_SUCCESS(Status)) return Status;

    /* Get the debug object */
    Status = ObReferenceObjectByHandle(DebugHandle,
                                       DEBUG_OBJECT_WAIT_STATE_CHANGE,
                                       DbgkDebugObjectType,
                                       PreviousMode,
                                       (PVOID*)&DebugObject,
                                       NULL);
    if (!NT_SUCCESS(Status)) return Status;

    /* Clear process and thread */
    Process = NULL;
    Thread = NULL;

    /* Wait on the debug object given to us */
    while (TRUE)
    {
        Status = KeWaitForSingleObject(DebugObject,
                                       Executive,
                                       PreviousMode,
                                       Alertable,
                                       Timeout);
        if (!NT_SUCCESS(Status) ||
            (Status == STATUS_TIMEOUT) ||
            (Status == STATUS_ALERTED) ||
            (Status == STATUS_USER_APC))
        {
            /* Break out the wait */
            break;
        }

        /* Lock the object */
        GotEvent = FALSE;
        ExAcquireFastMutex(&DebugObject->Mutex);

        /* Check if a debugger is connected */
        if (DebugObject->DebuggerInactive)
        {
            /* Not connected */
            Status = STATUS_DEBUGGER_INACTIVE;
        }
        else
        {
            /* Loop the events */
            ListHead = &DebugObject->EventList;
            NextEntry =  ListHead->Flink;
            while (ListHead != NextEntry)
            {
                /* Get the debug event */
                DebugEvent = CONTAINING_RECORD(NextEntry,
                                               DEBUG_EVENT,
                                               EventList);
                DBGKTRACE(DBGK_PROCESS_DEBUG, "DebugEvent: %p Flags: %lx\n",
                          DebugEvent, DebugEvent->Flags);

                /* Check flags */
                if (!(DebugEvent->Flags & (4 | 1)))
                {
                    /* We got an event */
                    GotEvent = TRUE;

                    /* Loop the list internally */
                    NextEntry2 = DebugObject->EventList.Flink;
                    while (NextEntry2 != NextEntry)
                    {
                        /* Get the debug event */
                        DebugEvent2 = CONTAINING_RECORD(NextEntry2,
                                                        DEBUG_EVENT,
                                                        EventList);

                        /* Try to match process IDs */
                        if (DebugEvent2->ClientId.UniqueProcess ==
                            DebugEvent->ClientId.UniqueProcess)
                        {
                            /* Found it, break out */
                            DebugEvent->Flags |= 4;
                            DebugEvent->BackoutThread = NULL;
                            GotEvent = FALSE;
                            break;
                        }

                        /* Move to the next entry */
                        NextEntry2 = NextEntry2->Flink;
                    }

                    /* Check if we still have a valid event */
                    if (GotEvent) break;
                }

                /* Move to the next entry */
                NextEntry = NextEntry->Flink;
            }

            /* Check if we have an event */
            if (GotEvent)
            {
                /* Save and reference the process and thread */
                Process = DebugEvent->Process;
                Thread = DebugEvent->Thread;
                ObReferenceObject(Process);
                ObReferenceObject(Thread);

                /* Convert to user-mode structure */
                DbgkpConvertKernelToUserStateChange(&WaitStateChange,
                                                    DebugEvent);

                /* Set flag */
                DebugEvent->Flags |= 1;
            }
            else
            {
                /* Unsignal the event */
                KeClearEvent(&DebugObject->EventsPresent);
            }

            /* Set success */
            Status = STATUS_SUCCESS;
        }

        /* Release the mutex */
        ExReleaseFastMutex(&DebugObject->Mutex);
        if (!NT_SUCCESS(Status)) break;

        /* Check if we got an event */
        if (!GotEvent)
        {
            /* Check if we can wait again */
            if (SafeTimeOut.QuadPart < 0)
            {
                /* Query the new time */
                KeQuerySystemTime(&NewTime);

                /* Substract times */
                SafeTimeOut.QuadPart += (NewTime.QuadPart - StartTime.QuadPart);
                StartTime = NewTime;

                /* Check if we've timed out */
                if (SafeTimeOut.QuadPart > 0)
                {
                    /* We have, break out of the loop */
                    Status = STATUS_TIMEOUT;
                    break;
                }
            }
        }
        else
        {
            /* Open the handles and dereference the objects */
            DbgkpOpenHandles(&WaitStateChange, Process, Thread);
            ObDereferenceObject(Process);
            ObDereferenceObject(Thread);
            break;
        }
    }

    /* We're done, dereference the object */
    ObDereferenceObject(DebugObject);

    /* Protect write with SEH */
    _SEH_TRY
    {
        /* Return our wait state change structure */
        RtlCopyMemory(StateChange,
                      &WaitStateChange,
                      sizeof(DBGUI_WAIT_STATE_CHANGE));
    }
    _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
    {
        /* Get SEH Exception code */
        Status = _SEH_GetExceptionCode();
    }
    _SEH_END;

    /* Return status */
    return Status;
}
2013-3-23 05:15
0
雪    币: 297
活跃值: (120)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
3
ReactOS给力啊,不知道ReactOS,怎么能进行源码级调试啊?
2013-3-23 12:32
0
雪    币: 6524
活跃值: (4316)
能力值: ( LV10,RANK:163 )
在线值:
发帖
回帖
粉丝
4
-.-  ReactOS直接开源的.
2013-3-23 12:38
0
雪    币: 773
活跃值: (442)
能力值: ( LV9,RANK:200 )
在线值:
发帖
回帖
粉丝
5
楼上的楼上的楼上的哥们 跟那个没关系 我调用的是 系统API 不是重写噢,就是 OD调用 我驱动里的系统 API
然后我把结果传递给OD,这个代码XP 2K3 都是没问题的
2013-3-27 18:58
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
6
Win7是因为参数问题和Mode问题导致的。XP下不用切换Mode执行也没大问题,Win7开始UserMode必须的,没有就死啦死啦的要!~

PreviousMode~~
2013-3-29 11:25
0
雪    币: 773
活跃值: (442)
能力值: ( LV9,RANK:200 )
在线值:
发帖
回帖
粉丝
7
XP 也的切 KERNEL ,不切不好使,WIN7 我早就切了,试验了好多方法就是不行
2013-3-30 22:02
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
8
切成kernel更不成~~必须usermode
2013-3-30 22:36
0
雪    币: 773
活跃值: (442)
能力值: ( LV9,RANK:200 )
在线值:
发帖
回帖
粉丝
9
又试验了几次 ,XP 切 UserMode 调试器就死掉了,切KernelMode 才能正常工作,WIN7 不管你切啥 都死
2013-3-31 13:15
0
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
10
代码贴出来看看,估计是参数弄错尿~
2013-3-31 16:42
0
游客
登录 | 注册 方可回帖
返回
//