PsSuspendProcess阻塞/等待/卡住- Windows内核编程

6tr1vspr  于 2023-03-04  发布在  Windows
关注(0)|答案(2)|浏览(249)

我带着一个关于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;
}
9bfwbjaz

9bfwbjaz1#

你是根据事实打电话的

PsSuspendProcess(FltGetRequestorProcess(Data));

但对于文件操作,预回调几乎总是在请求给定I/O操作的线程上下文中调用。因此几乎总是

FltGetRequestorProcess(Data) == IoGetCurrentProcess();

因此您挂起了current进程和current线程。

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

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

k3bvogb1

k3bvogb12#

以下示例说明如何使用FltQueueDeferredIoWorkItem阻止预I/O操作并挂起请求该操作的进程

PFLT_DEFERRED_IO_WORKITEM workItem = NULL;

                            workItem = FltAllocateDeferredIoWorkItem();

                            if (workItem != NULL) {

                                if (Data->Iopb->MajorFunction == IRP_MJ_WRITE) {
                                    status = FltLockUserBuffer(Data);
                                }
                                else {
                                    status = STATUS_SUCCESS;
                                }

                                if (NT_SUCCESS(status)) {

                                    status = FltQueueDeferredIoWorkItem(workItem, Data, FilterWorkerCallback, DelayedWorkQueue, CompletionContext);

                                    if (NT_SUCCESS(status)) {
                                        return FLT_PREOP_PENDING;
                                    }
                                    else {
                                        KdPrint(("FilterPreIoOp -> FltQueueDeferredIoWorkItem routine failed (Error: 0x%X).\r\n", status));
                                    }
                                }
                                else {
                                    KdPrint(("FilterPreIoOp -> FltLockUserBuffer routine failed (Error: 0x%X).\r\n", status));
                                }

                            }
                            else {
                                KdPrint(("FilterPreIoOp -> Unable to allocate memory for the worker item.\r\n"));
                            }

工人程序

VOID FLTAPI FilterWorkerCallback(_In_ PFLT_DEFERRED_IO_WORKITEM FltWorkItem, _In_ PFLT_CALLBACK_DATA CallbackData, _In_opt_ PVOID Context) {

    // Do some deferred I/O work here

    NTSTATUS status;

    PEPROCESS prcs = FltGetRequestorProcess(CallbackData);
    ULONG prcsId = FltGetRequestorProcessId(CallbackData);

    status = PsSuspendProcess(prcs);

    if (NT_SUCCESS(status)) {
        KdPrint(("FilterWorkerCallback -> Process with PID %lu suspended successfully.\r\n", prcsId));
    }
    else {
        KdPrint(("FilterWorkerCallback -> Unable to suspend process %lu \r\n", prcsId));
    }

    FltCompletePendedPreOperation(CallbackData, FLT_PREOP_COMPLETE, NULL);

    // Free the work item
    FltFreeDeferredIoWorkItem(FltWorkItem);

}

相关问题