-
-
[未解决,已结帖] [求助]hook “DbgkForwardException”函数后x64dbg 下断后无法单步 50雪币
-
发表于: 2026-1-24 17:33 627
-
本人小白,在学windows调试体系。从GitHub下了一套 代码,然后出现了这个问题。
现在只Hook了DbgkForwardException这个函数

下面是我的代码:
/*
判断目标进程是否是被调试的进程
Process 目标进程对象指针
DebugProcess 匹配到的那条 DEBUG_PROCESS 记录”的指针
这个记录里通常会包含你想要的东西(比如 entry->DebugObject、entry->Mutex 等)
*/
BOOLEAN IsDebugTargetProcess(IN PEPROCESSWIN10 Process, OUT PDEBUG_PROCESS* DebugProcess)
{
BOOLEAN result = FALSE;
*DebugProcess = NULL;
PLIST_ENTRY ListHead, NextEntry;
PDEBUG_PROCESS entry;
ExAcquireFastMutex(&g_DebugProcessList.Mutex);
ListHead = &g_DebugProcessList.list_entry.ListHead;
NextEntry = ListHead->Flink;
while (ListHead != NextEntry)
{
entry = CONTAINING_RECORD(NextEntry,
DEBUG_PROCESS,
list_entry);
if (entry)
{
if (entry->Process == Process)
{
*DebugProcess = entry;
result = TRUE;
break;
}
}
/* Move to the next entry */
NextEntry = NextEntry->Flink;
}
ExReleaseFastMutex(&g_DebugProcessList.Mutex);
return result;
}
BOOLEAN HotDbgkForwardException(IN PEXCEPTION_RECORD ExceptionRecord, IN BOOLEAN DebugException, IN BOOLEAN SecondChance)
{
DBGKM_APIMSG ApiMessage = { 0 };
PEPROCESSWIN10 Process;
PDEBUG_PROCESS DebugProcess;
PVOID DebugPort = NULL;
BOOLEAN UseLpc = FALSE;
PDBGKM_EXCEPTION DbgKmException = &ApiMessage.u.Exception;
NTSTATUS Status;
__int64 v13 = 1;
ApiMessage.h.u1.Length = 0xD000A8;
ApiMessage.h.u2.ZeroInit = 8;
ApiMessage.ApiNumber = DbgKmExceptionApi;
PAGED_CODE();
Process = PsGetCurrentProcess();
/*
如果这是第二次机会异常,说明“已经没人处理过了
内核会给进程打个“fault 标记/故障信息”用于后续:WER(错误报告)诊断/日志,某些策略判断(比如是否生成 dump/是否触发 failfast)
*/
if (SecondChance)
{
FindPsSetProcessFaultInformationProc(Process, (int*)&v13);
}
/*
IsUseDebugPort == TRUE
调用方希望这次异常发给调试器
*/
if (DebugException)
{
if (IsDebugTargetProcess(Process, &DebugProcess))
{
DebugPort = DebugProcess->DebugObject;
}
else
{
size_t ptr_DebugPort = (size_t)Process + 0x578;
DebugPort = *(PDEBUG_OBJECT*)ptr_DebugPort;
}
}
/*
UseLpc:走异常端口的标志
IsUseDebugPort == FALSE
走异常端口(LPC_EXCEPTION)
*/
else
{
ApiMessage.h.u2.ZeroInit = LPC_EXCEPTION;
UseLpc = TRUE;
DebugPort = PsCaptureExceptionPortP(Process);
}
/*
没有DebugPort还要走调试器通道
*/
if (!DebugPort && DebugException) return FALSE;
/*
目标进程是被调试进程
*/
if (IsDebugTargetProcess(Process, &DebugProcess))
{
/*
如果异常编码是 STATUS_ILLEGAL_INSTRUCTION 非法指令 或
STATUS_ACCESS_VIOLATION 访问违例(读/写/执行非法地址)
*/
if ((ExceptionRecord->ExceptionCode == STATUS_ILLEGAL_INSTRUCTION) ||
(ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION))
{
return FALSE;
}
/*
如果异常编码是 STATUS_SINGLE_STEP 单步/硬件断点触发 或
STATUS_WX86_SINGLE_STEP 当 32 位代码在 WoW64 兼容层里触发了“单步事件”时
*/
if ((ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP) ||
(ExceptionRecord->ExceptionCode == STATUS_WX86_SINGLE_STEP))
{
/*
TrapFrame :CPU 发生异常/中断时,内核保存现场的结构
Dr6 :硬件调试寄存器 DR6 的保存值
*/
PETHREADWIN10 Thread = PsGetCurrentThread();
KTHREADWIN10 Kthread = Thread->Tcb;
PKTRAP_FRAME TrapFrame = Kthread.TrapFrame;
union Dr6 dr6;
dr6.flags = TrapFrame->Dr6;
/*
DR6 是“#DB(调试异常)原因寄存器”,它会告诉你:
是单步(BS 位)
还是硬件断点触发(B0~B3 位)
如果 BS==1:通常是 TF 单步(逐条指令单步那种)
如果 BS==0:说明这次 #DB 不是传统 TF 单步导致的。
然后再看 B0~B3:
如果 B0~B3 有一个为 1:说明是硬件断点命中。你选择:
return FALSE:把这个 #DB 放行给被调试者自己处理。
*/
if (dr6.BS == 0) //判断是否是tf单步执行
{
//在vt中通过向guest注入#DB异常并不会修改dr6寄存器
if (dr6.B0 || dr6.B1 || dr6.B2 || dr6.B3)
{
//将#DB异常抛给被调试者
return FALSE;
}
}
}
}
/*
KeCopyExceptionRecordPort : 把当前异常记录(ExceptionCode/Address/Information…)完整复制到 ApiMessage 里,准备发给调试器/异常端口。
SecondChance==FALSE → FirstChance=TRUE:第一次机会异常
SecondChance==TRUE → FirstChance=FALSE:第二次机会异常
*/
KeCopyExceptionRecordPort(&ApiMessage.u.Exception.ExceptionRecord, ExceptionRecord);
DbgKmException->FirstChance = !SecondChance;
/*
如果 UseLpc==TRUE:走异常端口(LPC_EXCEPTION)那条路
*/
if (UseLpc)
{
/* 异常端口不存在 */
if (!DebugPort)
{
Status = STATUS_SUCCESS;
ApiMessage.ReturnedStatus = DBG_EXCEPTION_NOT_HANDLED;
}
/*
异常端口存在
通过 LPC 把消息发到异常端口
*/
else
{
Status = DbgkpSendApiMessageLpcProc(&ApiMessage, DebugPort, DebugException);
ObDereferenceObject(DebugPort);
}
}
/*
否则 UseLpc==FALSE:走 DebugObject(调试端口)那条路
*/
else
{
EXCEPTION_RECORD Local = *ExceptionRecord;
if (Local.ExceptionCode == STATUS_BREAKPOINT)
{
__try {
UCHAR cur = *(volatile UCHAR*)Local.ExceptionAddress;
UCHAR prev = *(volatile UCHAR*)((ULONG_PTR)Local.ExceptionAddress - 1);
if (cur != 0xCC && prev == 0xCC) {
Local.ExceptionAddress = (PVOID)((ULONG_PTR)Local.ExceptionAddress - 1);
}
}
__except (EXCEPTION_EXECUTE_HANDLER) {
}
}
Status = DbgkpSendApiMessageProc(Process, DebugException!=0, &ApiMessage);
}
if (!(NT_SUCCESS(Status)))
{
/* Fail */
return FALSE;
}
/*
如果对方回了 “DBG_EXCEPTION_NOT_HANDLED”:说明对方不处理
*/
if (ApiMessage.ReturnedStatus == DBG_EXCEPTION_NOT_HANDLED)
{
/*
如果不是 DebugPort(也就是走异常端口的情况)
*/
if (!DebugException)
{
Status = DbgkpSendErrorMessageProc(ExceptionRecord, 2, &ApiMessage);
return NT_SUCCESS(Status);
}
//调试器未能正确处理STATUS_SINGLE_STEP异常,可能是因为监视断点已经被取消
//if ((ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP) ||
// (ExceptionRecord->ExceptionCode == STATUS_WX86_SINGLE_STEP))
//{
// return TRUE;
//}
/* Fail */
return FALSE;
}
Status = ApiMessage.ReturnedStatus;
/*
成功 → TRUE(异常被处理/允许继续)
失败 → FALSE(异常仍然没被正确处理)
*/
return NT_SUCCESS(Status);
}求大佬解决 。莫嘲笑我。
赞赏
赞赏
雪币:
留言: