【问题标题】:PsSuspendProcess blocking / waiting / stuck - Windows Kernel ProgrammingPsSuspendProcess 阻塞/等待/卡住 - Windows 内核编程
【发布时间】:2020-09-11 19:02:24
【问题描述】:

我来这里是在 Windows 内核中提出一个非常低级别的问题。 我在一个微过滤驱动程序的回调函数中。 驱动程序的目标是暂停任何试图打开我标记为受保护的文件的进程。 我正在使用从这个函数获得的 PsSuspendProcess:

(pPsSuspendProcess)ReturnSystemRoutineAddress(L"PsSuspendProcess");

但是当我用上面的代码调用它时,我的程序卡在了 Suspend 调用中。 在任务管理器上,进程被很好地挂起,但驱动程序永远不会结束这个函数。

只有当我手动取消暂停进程或从 taskmgr 中终止它时它才会继续。

我完全被阻止了,因为 PsSuspendProcess 是一个未记录的函数...

这是我的代码:

FLT_PREOP_CALLBACK_STATUS
DfPreCreateCallback(
    _Inout_ PFLT_CALLBACK_DATA Data,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _Outptr_result_maybenull_ PVOID* CompletionContext
    )
{
    PAGED_CODE();
    NTSTATUS status;
    ULONG options = Data->Iopb->Parameters.Create.Options;
    UCHAR disposition = (options >> 24) & 0xff;
    ULONG createOptions = (options << 8) >> 8;

    if ((createOptions & FILE_NON_DIRECTORY_FILE) && (disposition == FILE_OPEN || disposition == FILE_OPEN_IF
        || disposition == FILE_OVERWRITE || disposition == FILE_OVERWRITE_IF))
    {
        HANDLE processId = (HANDLE)FltGetRequestorProcessId(Data);
        PEPROCESS p = FltGetRequestorProcess(Data);
        if (p == NULL)
            goto callback_end;
        LPSTR processName = PsGetProcessImageFileName(p);
        if (processName == NULL)
            goto callback_end;
        for (int i = 0; i < (sizeof(ExcludedProcess) / sizeof(LPCWSTR)); i++)
        {
            if (strcmp(processName, ExcludedProcess[i]) == 0)
                goto callback_end;
        }

        PFLT_FILE_NAME_INFORMATION FileInfo;
        status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_ALWAYS_ALLOW_CACHE_LOOKUP, &FileInfo);
        if (NT_ERROR(status))
            goto callback_end;
        if (!IsProtected(&FileInfo->Name))
            goto callback_end;
        DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "DBG PROTECTED %wZ", FileInfo->Name);

        PsSuspendProcess(p);

        DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "DBG SUSPENDED")
    }
    callback_end:
    CompletionContext = NULL;
    return FLT_PREOP_SUCCESS_NO_CALLBACK;
}

【问题讨论】:

  • 我的程序卡住了 - 你的程序是什么?您也暂停 current 进程和 current 线程。当然不会执行带有“DBG SUSPENDED”的DbgPrintEx
  • “我的程序”是微过滤器驱动程序,我挂起正在打开我的文件的进程,而不是当前的驱动程序进程。同样,在 LPSTR processName 中,我可以找到“notepad.exe”,例如
  • 看来你还是不明白。 不是当前的驱动进程 - ?!什么是驱动进程?!你暂停当前线程。那你想要什么?
  • 我使用了带有参数“p”的 PsSuspendProcess。 “p”由 FltGetRequestorProcess(Data) 定义,女巫给了我一个指向打开我受保护文件的进程的 EPROCESS 的指针。此调用如何暂停我当前的驱动程序线程?如果是这样,为什么 PEPROCESS 指向的进程会暂停?如果您认为我完全错了,请告诉我应该怎么做才能暂停打开受保护文件的进程。
  • 当前驱动线程 ?!?

标签: c windows kernel driver minifilter


【解决方案1】:

事实证明

PsSuspendProcess(FltGetRequestorProcess(Data));

但对于文件操作 Pre Callbacks 几乎总是在请求给定 I/O 操作的线程上下文中调用。所以几乎总是

FltGetRequestorProcess(Data) == IoGetCurrentProcess();

所以你暂停 current 进程和 current 线程。结果下一行

DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "DBG SUSPENDED");

当然不会执行,直到线程不会恢复

【讨论】:

  • 好的,非常感谢,我明白了。我认为它就像 PsSetCreateProcessNotifyRoutine。
  • @Tom - 不,顶级驱动程序几乎总是在 I/O 请求者进程的上下文中调用。
  • @Tom - 在所有情况下挂起过程都没有意义。接下来你将如何处理这个过程?你什么时候恢复呢?如果您不计划恢复 - 最好终止进程。为此,您需要队列工作项,从它调用 ZwTerminateProcess 而不是 KeSetEvent 并在回调前等待此事件.. 但您真正需要的是 - 返回 FLT_PREOP_COMPLETE 并阻止打开文件
猜你喜欢
  • 1970-01-01
  • 2016-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-04
  • 2013-02-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多