首页
社区
课程
招聘
[求助]windows用这两个之中的哪个函数通知调试器?DbgkpSendApiMessageLpc还是DbgkpSendApiMessage?
发表于: 2009-12-5 19:33 8104

[求助]windows用这两个之中的哪个函数通知调试器?DbgkpSendApiMessageLpc还是DbgkpSendApiMessage?

2009-12-5 19:33
8104
 if (LpcPort) {
        st = DbgkpSendApiMessageLpc(&m,Port,DebugException);
    } else {
        st = DbgkpSendApiMessage(&m,DebugException);
    }


有这样一段代码 应该是在异常产生时试图给调试器发送消息的,我还没弄明白这两个函数的区别。。
一会接着看wrk,
好心的大牛告诉一下:如果我用一个调试器来调试进程,那么当断点异常(比如INT 3)触发时, 操作系统是调用DbgkpSendApiMessageLpc 还是 DbgkpSendApiMessage?


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 722
活跃值: (123)
能力值: ( LV12,RANK:300 )
在线值:
发帖
回帖
粉丝
2
楼主果然本性难移。
1. 问别人问题还遮遮掩掩的,什么“有这一段代码”,连这一段是wrk里的哪个函数的内容都不肯说出来,还要人家搜索。
好吧,这是wrk中的DbgkForwardException函数的代码。

2. 本来自己看看就能明白的东西,硬是不好好看看,这是一个判断,DbgkForwardException函数的代码你要是贴得更全,就很容易看出这个判断的LpcPort是从哪来的,如果你再仔细看KiDispatchException,更不难了解整个流程中哪个时刻是哪个被调用。这个后面详细再讲。

3. 我上次回答时明明告诉你《软件调试》中哪里有对这个过程的讲解和描述,你就是不去看(别跟我说书太贵,不用我提醒你网上有电子版流传吧),你要的答案也就是我接下来说的内容,在那部分都有提到,还是那句话,你好好看了wrk,辅以《软件调试》你就不需要在这发问了。

4. 你自己以前问过一个类似的问题:http://www.debugman.com/read.php?tid=4005
其中你自己引用的一句话:
“若有用户调试器加载,则向进程的DebugPort或 ExceptionPort发送有关异常的LPC消息并判断发送函数的返回状态,若用户调试器继续执行,则返回STATUS_SUCCESS,内核视为异常已解决继续执行。”
就是对DbgkForwardException函数所做的事情的描述,你自己引用过的话,到现在自己看wrk,就对不上号了?

下面从第2点,详细说明一下,同样还是引wrk并参考《软件调试》中的有关表述。

首先,你得把DbgkForwardException函数的代码贴更全了,至少你得能看到LpcPort从哪里来的吧:
//
// Get the address of the destination LPC port.
//

Process = PsGetCurrentProcess();
if (DebugException) {
if (PsGetCurrentThread()->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_HIDEFROMDBG) {
Port = NULL;
} else {
Port = Process->DebugPort;
}
LpcPort = FALSE;
} else {
Port = Process->ExceptionPort;
m.h.u2.ZeroInit = LPC_EXCEPTION;
LpcPort = TRUE;
}

//
// If the destination LPC port address is NULL, then return FALSE.
//

if (Port == NULL) {
return FALSE;
}

//
// Fill in the remainder of the debug LPC message.
//

args->ExceptionRecord = *ExceptionRecord;
args->FirstChance = !SecondChance;

//
// Send the debug message to the destination LPC port.
//

if (LpcPort) {
st = DbgkpSendApiMessageLpc(&m,Port,DebugException);
} else {
st = DbgkpSendApiMessage(&m,DebugException);
}

如果DebugException为TRUE且线程没有指定PS_CROSS_THREAD_FLAGS_HIDEFROMDBG标志,那么LpcPort为FALSE且Port有效,则会调用DbgkpSendApiMessage;
如果DebugException为TRUE但线程指定PS_CROSS_THREAD_FLAGS_HIDEFROMDBG标志,那么不通知调试器直接返回FALSE;
如果DebugException为FALSE,那么说明是要发给ExceptionPort使那里的监听者有一次处理异常的机会,那么LpcPort为TRUE,则会调用DbgkpSendApiMessageLpc。

好了,上面的代码判断逻辑就清楚了,那么到底什么时候DebugException为TRUE什么时候为FALSE呢?看KiDispatchException函数调用DbgkForwardException的代码:

if (FirstChance == TRUE) {

//
// This is the first chance to handle the exception.
//

if ((KiDebugRoutine != NULL) &&
((PsGetCurrentProcess()->DebugPort == NULL &&
!KdIgnoreUmExceptions) ||
(KdIsThisAKdTrap(ExceptionRecord, &ContextFrame, UserMode)))) {
//
// Now dispatch the fault to the kernel debugger.
//

if ((((KiDebugRoutine) (TrapFrame,
ExceptionFrame,
ExceptionRecord,
&ContextFrame,
PreviousMode,
FALSE)) != FALSE)) {

goto Handled1;
}
}

if (DbgkForwardException(ExceptionRecord, TRUE, FALSE)) {
goto Handled2;
}

......
//
// This is the second chance to handle the exception.
//

if (DbgkForwardException(ExceptionRecord, TRUE, TRUE)) {
goto Handled2;
} else if (DbgkForwardException(ExceptionRecord, FALSE, TRUE)) {
goto Handled2;
} else {
ZwTerminateProcess(NtCurrentProcess(), ExceptionRecord->ExceptionCode);
KeBugCheckEx(
KERNEL_MODE_EXCEPTION_NOT_HANDLED,
ExceptionRecord->ExceptionCode,
(ULONG)ExceptionRecord->ExceptionAddress,
(ULONG)TrapFrame,
0);
}
}

在PreviousMode是UserMode的时候:
如果是FirstChance且内核调试引擎没有启动或没有处理异常(对KiDebugRoutine的调用返回FALSE),则调用DbgkForwardException,这时DebugException是指定为TRUE的,这样如果线程没有指定PS_CROSS_THREAD_FLAGS_HIDEFROMDBG标志,那么会调用DbgkpSendApiMessage,如指定了PS_CROSS_THREAD_FLAGS_HIDEFROMDBG标志则DbgkForwardException直接返回FALSE。
调试器没有处理,就让程序返回用户态时从KeUserExceptionDispatcher开始,进行用户态的异常处理。这部分代码上面引用时省略掉了。
如果第一次没有处理异常,那么用户态的KiUserExceptionDispatcher会再调用ZwRaiseException并将FirstChance设为FALSE,从而发起第二轮分发。
这时到了KiDispatchException,就是SecondChance的代码,首先再次调用DbgkForwardException,将DebugException和SecondChance都指定为TRUE,这样同样要不就调用DbgkpSendApiMessage要不就直接返回FALSE。
如果这次还是返回FALSE,再次调用DbgkForwardException,将DebugException指定为FALSE,SecondChance指定为TRUE,这时才会调用DbgkpSendApiMessageLpc给ExceptionPort指定的监听者一个处理异常的机会。

综上,异常分发过程中DebugPort指定的调试器可能得到的两次处理机会(注意我不是指内核调试引擎,与内核调试引擎交互是在KiDebugRoutine)均是调用DbgkpSendApiMessage,只有当前面所有的程序自身和调试器干预过程都没有能够处理异常之后,才会调用DbgkpSendApiMessageLpc给ExceptionPort指定的监听者(这里一般是Win32子系统)一个处理异常的机会(包括提示用户程序出错需要关闭)。

最后再说一句,上面我写的对wrk相关函数的流程表述,是很直白的,会看代码的应该都能看明白,我还是那句话,你真的有好好看wrk吗,如果看了,你真的有好好思考吗?
2009-12-5 21:48
0
雪    币: 246
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
1.下次改掉毛病 一定全部贴出!
2.这些天 看都看迷糊了 ,我就记住DbgkForwardException是我要分析的目标了,都忘了谁调用他了!下次改!
3.这就去下pdf,书丢了不是借口 !下次改!
4.我承认 就这一个问题问了许多次的:其实我并不想问这么多次,可是你也看到那些帖子并未得到什么答复~这几天你回答我的问题啊!谢谢老大!!其实问了不知一遍呢~http://www.0ginr.com/bbs/thread-3503-1-1.html

你说的东西完全懂了~谢谢,而且你这个发出去能不能得个精华贴?发到我这里有点屈才了吧!

最近有些问题难以找到答复,而且我对一些高深的概念更是一窍不通,我还听说网上的“XX”培训班都是骗人的,所以为了学到东西,只得游走于几个论坛之间 ,不懂只好来问。。。 以后一定按照老大的旨意办事
2009-12-5 22:15
0
雪    币: 70
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
小聪这样的回帖,太费心了,崇拜
2009-12-5 22:22
0
雪    币: 254
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
二楼牛人是给你好学打动,应该
2009-12-5 22:23
0
雪    币: 1040
活跃值: (1293)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
55555555555……软件调试的电子版到底在那里……谷歌了一大堆……都不能下……
2009-12-5 22:36
0
游客
登录 | 注册 方可回帖
返回
//