PsSuspendProcess блокируется/ожидает/зависает — Программирование ядра Windows

Я пришел сюда с вопросом очень низкого уровня в ядре 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;
}

person Tom    schedule 25.05.2020    source источник
comment
моя программа зависла - какая ваша программа? вы также приостанавливаете текущий процесс и текущий поток. конечно DbgPrintEx с DBG SUSPENDED не будет выполняться.   -  person RbMm    schedule 25.05.2020
comment
Моя программа является драйвером минифильтра. Я приостанавливаю процесс, ведь я открываю свой файл, а не текущий процесс драйвера. Кроме того, в LPSTR имя_процесса я могу найти, например, notepad.exe   -  person Tom    schedule 25.05.2020
comment
похоже, вы все еще не понимаете. не текущий процесс драйвера - ?! что такое драйверный процесс?! вы приостанавливаете текущий поток. и чего же ты хочешь ?   -  person RbMm    schedule 25.05.2020
comment
Я использовал PsSuspendProcess с параметром p. p определяется FltGetRequestorProcess(Data), ведьма дает мне указатель на EPROCESS процесса, который открыл мой защищенный файл. Как этот вызов может приостановить мой текущий поток драйвера? И если это так, почему процесс, указанный PEPROCESS, приостанавливается? Если вы думаете, что я совершенно не прав, скажите, пожалуйста, что мне делать, чтобы приостановить процесс, открывающий мой защищенный файл.   -  person Tom    schedule 25.05.2020
comment
текущий поток драйверов ?!?   -  person RbMm    schedule 25.05.2020
comment
вы приостанавливаете текущий поток. и это все. вам нужно изучить, в каком контексте выполняется код ядра   -  person RbMm    schedule 25.05.2020


Ответы (1)


ты звонишь по факту

PsSuspendProcess(FltGetRequestorProcess(Data));

но для файловых операций предварительные обратные вызовы почти всегда вызываются в контексте потока, запрашивающего данную операцию ввода-вывода. так почти всегда

FltGetRequestorProcess(Data) == IoGetCurrentProcess();

поэтому вы приостанавливаете текущий процесс и текущий поток. в результате следующая строка

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

конечно не будет выполняться до тех пор, пока поток не будет возобновлен

person RbMm    schedule 25.05.2020
comment
Хорошо, спасибо большое, я понял. Я думал, что это похоже на PsSetCreateProcessNotifyRoutine. - person Tom; 25.05.2020
comment
@Tom - нет, драйверы верхнего уровня почти всегда вызываются в контексте процесса запроса ввода-вывода. - person RbMm; 25.05.2020
comment
@Tom - в любом случае приостанавливать процесс не имеет смысла. что вы будете делать дальше с этим процессом? когда вы возобновите его? это вы не планируете возобновлять - лучше просто завершите процесс. для этого вам нужен рабочий элемент очереди, из него вызовите ZwTerminateProcess, а затем KeSetEvent и в предварительном обратном вызове подождите этого события.. но на самом деле то, что вам нужно - вернуть FLT_PREOP_COMPLETE и заблокировать открытый файл - person RbMm; 25.05.2020