退出BSOD期间内核\u APC\u挂起\u
我正在设置一个PLOAD_IMAGE_NOTIFY_例程来检测特定的图像名称,如果存在匹配,则终止它。我在退出BSOD期间得到一个内核APC挂起。BSOD发生在我的KillProcess函数中的某个地方,它只是用ObOpenObjectByPointer打开一个内核句柄,然后在该句柄上调用ZwTerminateProcess 有什么不对劲吗?代码在例程之外运行良好。我必须把它寄出去吗?当我调用KillProcess时,我在PLOAD_IMAGE_NOTIFY_例程中得到一个BSOD 以下是我的KillProcess函数:退出BSOD期间内核\u APC\u挂起\u,c,windows,kernel,C,Windows,Kernel,我正在设置一个PLOAD_IMAGE_NOTIFY_例程来检测特定的图像名称,如果存在匹配,则终止它。我在退出BSOD期间得到一个内核APC挂起。BSOD发生在我的KillProcess函数中的某个地方,它只是用ObOpenObjectByPointer打开一个内核句柄,然后在该句柄上调用ZwTerminateProcess 有什么不对劲吗?代码在例程之外运行良好。我必须把它寄出去吗?当我调用KillProcess时,我在PLOAD_IMAGE_NOTIFY_例程中得到一个BSOD 以下是我的K
NTSTATUS KillProcess(HANDLE ProcessId)
{
PEPROCESS Process;
HANDLE newProcessHandle = NULL;
NTSTATUS status = PsLookupProcessByProcessId(ProcessId, &Process);
do
{
if (!NT_SUCCESS(status))
{
#ifdef DEBUGPRINT
DbgPrint("Process with id %d does not exist\n", ProcessId);
#endif
break;
}
if (NT_SUCCESS(status = ObOpenObjectByPointer(
Process,
OBJ_KERNEL_HANDLE,
NULL,
PROCESS_TERMINATE,
*PsProcessType,
KernelMode,
&newProcessHandle
)))
{
if (newProcessHandle != NULL)
{
status = ZwTerminateProcess(newProcessHandle, 0);
ZwClose(newProcessHandle);
}
else
{
ObDereferenceObject(Process);
break;
}
if (NT_SUCCESS(status))
{
#ifdef DEBUGPRINT
DbgPrint("Successfully killed process with id %d\n", ProcessId);
#endif
}
else
{
#ifdef DEBUGPRINT
DbgPrint("Failed to kill process with id %d\n", ProcessId);
#endif
}
}
else
{
#ifdef DEBUGPRINT
DbgPrint("Failed to open process with id %d\n", ProcessId);
#endif
}
ObDereferenceObject(Process);
} while (FALSE);
return status;
}
报告说:
加载新创建的进程的主可执行映像时,加载映像通知例程将在新进程的上下文中运行
(加载DLL时,调用也可能是在加载DLL的进程上下文中进行的。)
因此,从它的声音来看,您正在终止正在其上下文中运行的进程。更重要的是,在回调图像加载操作的过程中,您在一个特别脆弱的点上执行此操作。这引起麻烦并不奇怪
这意味着驱动程序可以终止当前进程,前提是它确保从内核堆栈中释放资源,但我认为这不适用于这种情况。(还有,我不知道你会怎么做。)
相反,可以挂起进程,稍后从系统线程终止它。问题是我试图在进程自身的上下文中终止进程,这会导致BSOD。 解决方案:
没有代码,就很难确定错误。但请检查您是否正在释放例程中的所有锁、关键部分等。好的,您是对的,我发布了它。相反,我将尝试注入一个调用ExitProcess()的DLL。这也可能有效。我不确定它是否能确保可执行文件在开始运行之前终止,如果这是一个问题的话。我曾考虑将APC排队并以这种方式注入,但我意识到这只适用于32位系统,而且ZwSuspendProcess没有任何文档记录,通常也不是一个好主意,所以现在我想我必须找到一种不同的注入方法。我可能会发布一个新问题。我想的是ZwSuspendThread而不是ZwSuspendProcess。在这一点上,应该只有主线程(我认为),如果您挂起它,就不可能创建其他线程。但这只是猜测。该死,我决定只生成一个系统线程,检查保存pid的全局变量是否已更改,然后终止它。更简单。请注意,根据您的场景,这里有一个潜在的竞争条件-如果两个需要终止的进程同时启动,您可能只会得到其中一个。您可以使用队列而不是单个变量来修复此问题。您还应该提高系统线程的优先级,以确保它尽快运行,尽管在多核系统上,仍然不能绝对保证新进程在您杀死它之前不会开始运行(但可能相当安全)。