Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
退出BSOD期间内核\u APC\u挂起\u_C_Windows_Kernel - Fatal编程技术网

退出BSOD期间内核\u APC\u挂起\u

退出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

我正在设置一个PLOAD_IMAGE_NOTIFY_例程来检测特定的图像名称,如果存在匹配,则终止它。我在退出BSOD期间得到一个内核APC挂起。BSOD发生在我的KillProcess函数中的某个地方,它只是用ObOpenObjectByPointer打开一个内核句柄,然后在该句柄上调用ZwTerminateProcess

有什么不对劲吗?代码在例程之外运行良好。我必须把它寄出去吗?当我调用KillProcess时,我在PLOAD_IMAGE_NOTIFY_例程中得到一个BSOD

以下是我的KillProcess函数:

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。 解决方案:

  • 创建保存pid的全局变量
  • 设置全局变量
  • 在系统线程中,检查全局变量是否已更改
  • 终止进程

  • 没有代码,就很难确定错误。但请检查您是否正在释放例程中的所有锁、关键部分等。好的,您是对的,我发布了它。相反,我将尝试注入一个调用ExitProcess()的DLL。这也可能有效。我不确定它是否能确保可执行文件在开始运行之前终止,如果这是一个问题的话。我曾考虑将APC排队并以这种方式注入,但我意识到这只适用于32位系统,而且ZwSuspendProcess没有任何文档记录,通常也不是一个好主意,所以现在我想我必须找到一种不同的注入方法。我可能会发布一个新问题。我想的是ZwSuspendThread而不是ZwSuspendProcess。在这一点上,应该只有主线程(我认为),如果您挂起它,就不可能创建其他线程。但这只是猜测。该死,我决定只生成一个系统线程,检查保存pid的全局变量是否已更改,然后终止它。更简单。请注意,根据您的场景,这里有一个潜在的竞争条件-如果两个需要终止的进程同时启动,您可能只会得到其中一个。您可以使用队列而不是单个变量来修复此问题。您还应该提高系统线程的优先级,以确保它尽快运行,尽管在多核系统上,仍然不能绝对保证新进程在您杀死它之前不会开始运行(但可能相当安全)。