Синий экран при перезаписи пакетов на уровне DATAGRAM_DATA в WFP - PullRequest
0 голосов
/ 02 августа 2020

Я пытался изменить исходящие DNS-пакеты через слой DATAGRAM_DATA в WFP, однако при перезаписи IP-адреса назначения в исходящем пакете у меня появляются ошибки синего экрана. Что я делаю не так?

Признаюсь, параметры для FwpsInjectTransportSendAsync меня немного сбивают с толку, и я не был уверен, что именно добавить в аргумент sendParams - хотя я думаю, что то, что у меня есть, выглядит правильно.

RtlIpv4StringToAddressExW(
L"1.1.1.1", // hard-coding the new (rewritten) dns server for now
FALSE,
&sin4.sin_addr,
&sin4.sin_port);

RtlIpv4StringToAddressExW(
    L"8.8.8.8",        // hard-coding the original dns server for now
    FALSE,
    &origSin4.sin_addr,
    &origSin4.sin_port);
if ((Direction == FWP_DIRECTION_OUTBOUND) && (PacketInjectionState == FWPS_PACKET_NOT_INJECTED) && (RemotePort == 53) && (RemoteAddress == origSin4.sin_addr.S_un.S_addr))
{

    UINT32 IpHeaderSize = inMetaValues->ipHeaderSize;
    UINT32 TransportHeaderSize = inMetaValues->transportHeaderSize;
    UINT64 endpointHandle = inMetaValues->transportEndpointHandle;

    PNET_BUFFER NetBuffer = NET_BUFFER_LIST_FIRST_NB((PNET_BUFFER_LIST)layerData);
    NdisRetreatNetBufferDataStart(NetBuffer, IpHeaderSize + TransportHeaderSize, 0, NULL);

    PNET_BUFFER_LIST NetBufferList = NULL;
    NTSTATUS Status = FwpsAllocateCloneNetBufferList(layerData, NULL, NULL, 0, &NetBufferList);
    if (!NT_SUCCESS(Status))
    {
        return;
    }

    NdisAdvanceNetBufferDataStart(NetBuffer, IpHeaderSize + TransportHeaderSize, FALSE, NULL);

    if (!NetBufferList)
    {
        return;
    }

    NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);

    PIPV4_HEADER IpHeader = NdisGetDataBuffer(NetBuffer, sizeof(IPV4_HEADER), NULL, 1, 0);

    // Rewriting the dest ip
    IpHeader->DestinationAddress = sin4.sin_addr.S_un.S_addr;

    // Updating the IP checksum
    UpdateIpv4HeaderChecksum(IpHeader, sizeof(IPV4_HEADER));

    // not 100% sure the sendParams argument is setup correctly, the docs are slightly unclear
    FWPS_TRANSPORT_SEND_PARAMS sendParams = {
        .remoteAddress = (UCHAR*)IpHeader->DestinationAddress,
        .remoteScopeId = inMetaValues->remoteScopeId,
        .controlData = inMetaValues->controlData,
        .controlDataLength = inMetaValues->controlDataLength,
        .headerIncludeHeader = inMetaValues->headerIncludeHeader,
        .headerIncludeHeaderLength = inMetaValues->headerIncludeHeaderLength
    };

    Status = FwpsInjectTransportSendAsync(g_InjectionHandle, NULL, endpointHandle, 0, &sendParams, AF_INET, inMetaValues->compartmentId, NetBufferList, DriverDatagramDataInjectComplete, NULL);
    if (!NT_SUCCESS(Status))
    {
        FwpsFreeCloneNetBufferList(NetBufferList, 0);
    }

    classifyOut->actionType = FWP_ACTION_BLOCK;
    classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
    classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
}

1 Ответ

1 голос
/ 02 августа 2020

Для меня выделяются две вещи, обе в sendParams.

Во-первых, remoteAddress неверно. Ему нужен указатель на адрес, поэтому он должен быть (UCHAR*)&IpHeader->DestinationAddress.

Во-вторых, FwpsInjectTransportSendAsync() является асинхронным, поэтому любые параметры, которые вы ему передаете, должны оставаться действительными до его завершения, что может быть после вашего вызова функция возвращается. Обычно вы выделяете некоторую контекстную структуру, которая содержит sendParams и глубокие копии соответствующих членов (remoteAddress и controlData). Вы передаете это как контекст в процедуру завершения, где вы его освобождаете.

...