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

PsSuspendProcess阻塞/等待/卡住-Windows内核编程,c,windows,kernel,driver,minifilter,C,Windows,Kernel,Driver,Minifilter,我是带着一个关于Windows内核的非常低级的问题来到这里的。 我在一个微型过滤器驱动程序的回调函数中。 驱动程序的目标是暂停任何试图打开我标记为受保护的文件的进程。 我使用的是从这个函数中得到的PsSuspendProcess: (pPsSuspendProcess)ReturnSystemRoutineAddress(L"PsSuspendProcess"); 但是当我用上面的代码调用它时,我的程序在挂起调用时卡住了。 在任务管理器上,进程处于挂起状态,但驱动程序从未结束此功能 仅当我手动

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

(pPsSuspendProcess)ReturnSystemRoutineAddress(L"PsSuspendProcess");
但是当我用上面的代码调用它时,我的程序在挂起调用时卡住了。 在任务管理器上,进程处于挂起状态,但驱动程序从未结束此功能

仅当我手动解除进程暂停或从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;
}
FLT\u PREOP\u CALLBACK\u状态
DfPreCreateCallback(
_Inout_uPFLT_回调_数据,
_在PCFLT相关对象FltObjects中,
_Outptr_result_maybenull_upvoid*完成上下文
)
{
PAGED_代码();
非关税国家地位;
ULONG options=Data->Iopb->Parameters.Create.options;
UCHAR disposition=(选项>>24)&0xff;
ULONG createOptions=(选项>8;
如果((createOptions&FILE_NON_DIRECTORY_FILE)&(disposition==FILE_OPEN | | disposition==FILE_OPEN_if)
||处置==文件| |处置==文件(如果覆盖))
{
HANDLE processId=(HANDLE)FltGetRequestorProcessId(数据);
PEPROCESS p=FltGetRequestorProcess(数据);
if(p==NULL)
后进先出;
LPSTR processName=PsGetProcessImageFileName(p);
if(processName==NULL)
后进先出;
对于(int i=0;i<(sizeof(不包括数据处理)/sizeof(LPCWSTR));i++)
{
if(strcmp(进程名,不包括进程[i])==0)
后进先出;
}
PFLT_文件名_信息文件信息;
状态=FLTGETFILENAME信息(数据、FLT文件名、规范化、FLT文件名、查询、始终允许缓存、查找和文件信息);
如果(NT_错误(状态))
后进先出;
如果(!IsProtected(&FileInfo->Name))
后进先出;
DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_ERROR_LEVEL,“DBG保护%wZ”,文件信息->名称);
PsSuspendProcess(p);
DbgPrintEx(DPFLTR_IHVDRIVER_ID,DPFLTR_ERROR_LEVEL,“DBG挂起”)
}
回调结束:
CompletionContext=NULL;
返回FLT\u PREOP\u SUCCESS\u NO\u回调;
}
你按事实打电话

PsSuspendProcess(FltGetRequestorProcess(Data));
但对于文件操作,几乎总是在请求给定I/O操作的线程上下文中调用预回调

FltGetRequestorProcess(Data) == IoGetCurrentProcess();
所以您暂停current进程和current线程

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

当然,在线程未恢复之前不会执行。我的程序卡住了-你的程序是什么?你挂起当前进程和当前线程。当然,带有“DBG SUSPENDED”的
DbgPrintEx
将不会执行。“我的程序”是正在打开文件的挂起进程的微筛选器驱动程序,而不是当前的驱动程序进程。同样,在LPSTR processName中,我可以找到“notepad.exe”例如,看起来您仍然不明白。不是当前的驱动程序进程-?!什么是驱动程序进程?!您挂起当前线程。那么您想要什么呢?我使用了带参数“p”的PsSuspendProcess。“p”由FltGetRequestorProcess(数据)定义,witch给我一个指向打开我的受保护文件的进程的EPROCESS的指针。此调用如何挂起我当前的驱动程序线程?如果挂起,为什么PEPROCESS指向的进程会暂停?如果您认为我完全错了,请告诉我应该如何挂起打开我的受保护文件的进程。当前驱动程序线程?!?好的,非常感谢,我明白了。我认为这就像PsSetCreateProcessNotifyRoutine一样。@Tom-不,顶级驱动程序几乎都是在i/O请求程序进程的上下文中调用的。@Tom-在所有情况下,挂起进程都没有意义。下一步你将如何处理这个进程?当你恢复它时?你不打算恢复吗?最好还是继续终止进程。为此,您需要队列工作项,从它调用
ZwTerminateProcess
然后调用
KeSetEvent
,并在预回调中等待此事件。但实际上您需要的是-返回
FLT\u PREOP\u COMPLETE
并阻止打开文件