即使 pid 错误,PsLookupProcessByProcessId 也会返回 STATUS_SUCCESS

PsLookupProcessByProcessId is returning STATUS_SUCCESS even if the pid is wrong

我正在从我的驱动程序中检查我的用户模式应用程序是否仍然 运行, 在这样做的同时,我使用 PsLookupProcessByProcessId 来检查进程是否仍然存在。 它在开始时有效,但即使在我关闭我的进程并且没有其他进程具有相同的 pid 之后,我仍然得到 STATUS_SUCCESS。以前有人遇到过这种行为吗? 我 运行 在 Windows 20h2 测试我的驱动程序

我的代码片段

NTSTATUS status = PsLookupProcessByProcessId((HANDLE)UserModePid, &UserModeProcess);
if (status == STATUS_INVALID_PARAMETER) {
    DbgPrintEx(0, 0, "[Driver] Invalid Process\n");
    ExitKernel();
}
else {
    DbgPrintEx(0, 0, "[Driver] Status : %llx", status);
}

抱歉我的英语不好:)

进程退出时,Windows不会立即释放EPROCESS,而是保留一段时间(因为引用计数还没有减为0)。

以下代码可以很好地确定进程是否已退出(从 Blackbone 复制):

/// <summary>
/// Check if process is terminating
/// </summary>
/// <param name="imageBase">Process</param>
/// <returns>If TRUE - terminating</returns>
BOOLEAN BBCheckProcessTermination( PEPROCESS pProcess )
{
    LARGE_INTEGER zeroTime = { 0 };
    return KeWaitForSingleObject( pProcess, Executive, KernelMode, FALSE, &zeroTime ) == STATUS_WAIT_0;
}

结合你的代码:

bool IsTerminated;
NTSTATUS Status = PsLookupProcessByProcessId((HANDLE)LoaderPid, &LoaderProccess);
if (!NT_SUCCESS(Status)) {
    IsTerminated = true;
}
else {
    IsTerminated = BBCheckProcessTermination(LoaderProccess);
    ObDereferenceObject(LoaderProccess);
}

if (IsTerminated) {
    DbgPrintEx(0, 0, "[Driver] Invalid Process\n");
    ExitKernel();
}
else {
    DbgPrintEx(0, 0, "[Driver] Status : %llx", Status);
}

如果上面的代码不行,你也可以试试:

IsTerminated = PsGetProcessExitStatus(LoaderProccess) != STATUS_PENDING;

如果还是不行,我能提供的最后一个方案是用ZwQuerySystemInformation枚举进程,检查你的进程是否在链表中。