首页
社区
课程
招聘
[未解决,已结帖] [求助]hook “DbgkForwardException”函数后x64dbg 下断后无法单步 50雪币
发表于: 2026-1-24 17:33 627

[未解决,已结帖] [求助]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);
}


求大佬解决 。莫嘲笑我。


传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回