Windows Платформа фильтрации: ClassifyFn BSOD в DISPATCH_LEVEL - PullRequest
0 голосов
/ 27 марта 2020

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

Брандмауэр должен разрешать / блокировать соединение.

Для перехвата соединений любым способом я создал драйвер ядра, который использует Windows Платформа фильтрации .

Я зарегистрировал обратный вызов ClassifyFn (FWPS_CALLOUT_CLASSIFY_FN1) на уровне фильтрации FWPM_LAYER_ALE_AUTH_CONNECT :

FWPM_CALLOUT m_callout = { 0 };
m_callout.applicableLayer = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
...
status = FwpmCalloutAdd(filter_engine_handle, &m_callout, NULL, NULL);

Решение о разрешении / блокировке соединения должно быть принято на уровне пользователя.

Я общаюсь с уровнем пользователя, используя FltSendMessage , который нельзя использовать в IRQL DISPATCH_LEVEL.

Следуя инструкциям документации Microsoft относительно того, как обрабатывать вызовы асинхронно , я вызываю FwpsPendOperation0 перед вызовом FltSendMessage.

После вызова FltSendMessage я возобновляю обработку пакетов, вызывая FwpsCompleteOperation0 .

FwpsPeperation в документации говорится, что вызов этой функции должен позволять обрабатывать вызовы на PASSIVE_LEVEL:

Вызов может ожидать текущую операцию обработки пакета, когда вызов должен выполнить обработку на одном из этих уровней, которая может занять длинный интервал для завершения или это должно происходить при IRQL = PASSIVE_LEVEL, если текущий IRQL> PASSIVE_LEVEL.

Однако, , когда обратный вызов ClassifyFn вызывается в DISPATCH_LEVEL, иногда я все равно получаю BSOD на FltSendMessage (INVALI D_PROCESS_ATTACH_ATTEMPT) .

Я не понимаю, в чем дело.

Заранее благодарю за любой совет, который может указать мне правильное направление.

Вот соответствующий код обратного вызова ClassifyFn:

/*************************
ClassifyFn Function
**************************/
void example_classify(
    const FWPS_INCOMING_VALUES * inFixedValues,
    const FWPS_INCOMING_METADATA_VALUES * inMetaValues,
    void * layerData,
    const void * classifyContext,
    const FWPS_FILTER * filter,
    UINT64 flowContext,
    FWPS_CLASSIFY_OUT * classifyOut)
{

    NTSTATUS status;
    BOOLEAN bIsReauthorize = FALSE;
    BOOLEAN SafeToOpen = TRUE; // Value returned by userlevel which signals to allow/deny packet
    classifyOut->actionType = FWP_ACTION_PERMIT;

    remote_address = inFixedValues->incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_REMOTE_ADDRESS].value.uint32;
    remote_port = inFixedValues->incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_REMOTE_PORT].value.uint16;

    bIsReauthorize = IsAleReauthorize(inFixedValues);
    if (!bIsReauthorize)
    {
        // First time receiving packet (not a reauthorized packet)
        // Communicate with userlevel asynchronously

        HANDLE hCompletion;
        status = FwpsPendOperation0(inMetaValues->completionHandle, &hCompletion);

        //
        // FltSendMessage call here
        // ERROR HERE:
        // INVALID_PROCESS_ATTACH_ATTEMP BSOD on FltMessage call when at IRQL DISPATCH_LEVEL
        //

        FwpsCompleteOperation0(hCompletion, NULL);
    }

    if (!SafeToOpen) {
        // Packet blocked
        classifyOut->actionType = FWP_ACTION_BLOCK;
    }
    else {
        // Packet allowed
    }

    return;
}

1 Ответ

1 голос
/ 28 марта 2020

Вам необходимо вызвать FltSendMessage () в другом потоке, работающем с PASSIVE_LEVEL. Вы можете использовать IoQueueWorkItem () или реализовать свой собственный механизм для его обработки в системном рабочем потоке, созданном с помощью PsCreateSystemThread ().

...