none
Send NET_BUFFER_LIST in NDIS filter driver RRS feed

  • Question

  • Hi, everyone.
    I want to send a NET_BUFFER_LIST in FilterReceiveNetBufferLists routine. How to do that?
    I try to use NdisSendNetBufferLists but BSOD at once.

    VOID FilterReceiveNetBufferLists
    (
        NDIS_HANDLE         FilterModuleContext,
        PNET_BUFFER_LIST    NetBufferLists,
        NDIS_PORT_NUMBER    PortNumber,
        ULONG               NumberOfNetBufferLists,
        ULONG               ReceiveFlags
    )
    {
    PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext;
    PNET_BUFFER NetBuffer;
    UCHAR TempBuffer[MAX_BUFFER_SIZE];
    ULONG BytesCopied;
    BOOLEAN bFalse = FALSE;
    //DbgPrint(">>> FilterReceiveNetBufferLists: %p\n", NetBufferLists, ReceiveFlags, NumberOfNetBufferLists);
    do
    {
    for(NetBuffer = NetBufferLists->FirstNetBuffer;
    NetBuffer != NULL;
    NetBuffer = NetBuffer->Next)
    {
    //DbgPrint("[FilterReceiveNetBufferLists]ENTER for LOOP: %p\n",NetBufferLists);
    GetNetBufferData(NetBuffer, TempBuffer, MAX_BUFFER_SIZE, &BytesCopied);
    if (BytesCopied == 0)
    {
    DbgPrint("[FilterReceiveNetBufferLists]Net buffer catch error\n");
    }
    else
    {
    //search TCP_MUX_TEST
    PCHAR ptr = (PCHAR)TempBuffer;
    ULONG i;
    for(i=0;i<BytesCopied;i++)
    {
    if(!_strnicmp(ptr+i,"TCP_MUX_TEST",12))
    {
    ULONG TargetIP=0,SourceIP=0;
    USHORT TargetPort=0,SourcePort=0;
    UCHAR TargetMac[6]={0},SourceMac[6]={0};
    PBEFORE_HTTP_HEADER pBTH = (PBEFORE_HTTP_HEADER)TempBuffer;
    //
    TargetIP = pBTH->ipHeader.dstaddr; TargetPort=pBTH->tcpHeader.dst_port; memcpy(TargetMac,pBTH->eHeader.dstmac,6);
    SourceIP = pBTH->ipHeader.srcaddr; SourcePort=pBTH->tcpHeader.src_port; memcpy(SourceMac,pBTH->eHeader.srcmac,6);
    DbgPrint("[FilterReceiveNetBufferLists]FIND TCP_MUX_TEST! [SRC]%X [DST]%X\n",SourceIP,TargetIP);
    //
    //WAY-1: PASS DOWN THE DATA
    //
    //break;
    //==========================
    //
    //WAY-2: DROP THE DATA
    //
    //return;
    //==========================
    //
    //WAT-3: DROP THE DATA AND SEND BACK THE DATA (try to fix MAC of ETH head and CHECKSUM of IP head)
    //
    pBTH->ipHeader.dstaddr = SourceIP;
    pBTH->ipHeader.srcaddr = TargetIP;
    pBTH->tcpHeader.dst_port = SourcePort;
    pBTH->tcpHeader.src_port = TargetPort;
    memcpy(TargetMac,pBTH->eHeader.srcmac,6);
    memcpy(SourceMac,pBTH->eHeader.dstmac,6);
    SetNetBufferData(NetBuffer, TempBuffer, BytesCopied, &BytesCopied);
    //NdisReturnNetBufferLists(FilterModuleContext,NetBufferLists,NDIS_RETURN_FLAGS_DISPATCH_LEVEL);
    NdisSendNetBufferLists(FilterModuleContext, NetBufferLists, PortNumber, NDIS_SEND_FLAGS_DISPATCH_LEVEL);
    return;
    }
    }
    }
    }
    }
    while (bFalse);
    //DbgPrint("[FilterReceiveNetBufferLists][IRQL=%d]\n",KeGetCurrentIrql());
    NdisFIndicateReceiveNetBufferLists(pFilter->FilterHandle, NetBufferLists, PortNumber, NumberOfNetBufferLists, ReceiveFlags);
    }

    Thanks in Advance

    -Mrutyunjaya

    Tuesday, July 24, 2018 6:41 PM

Answers

  • It's not appropriate to use strnicmp on network packets' payloads.  The payloads are binary, and not necessarily well-formed strings.  Furthermore, strnicmp probably does not work at DISPATCH_LEVEL, since the NLS tables are probably paged out.

    You can't originate a send for an NBL that you didn't allocate.  In particular, you can't pluck an NBL from the receive path, turn around and send it.  You need to clone the NBL.

    Keep in mind that you can only set the NDIS_SEND_FLAGS_DISPATCH_LEVEL flag if you're actually at dispatch level.  (And don't just check it -- the OS can do that already.)

    There are some remotely-exploitable security issues in this code.  You should work with someone who's got experience writing network drivers to ensure that your packet parser is robust.

    If the purpose of your driver is manipulating HTTP data, you may find that a WFP callout can do this more easily.  A WFP callout can edit the stream data, without having to worry about packet reassembly and fixing up the L2, L3, and L4 headers.

    Tuesday, July 24, 2018 11:23 PM

All replies

  • That's amazing. You get a new project every day.

    Tuesday, July 24, 2018 11:10 PM
  • It's not appropriate to use strnicmp on network packets' payloads.  The payloads are binary, and not necessarily well-formed strings.  Furthermore, strnicmp probably does not work at DISPATCH_LEVEL, since the NLS tables are probably paged out.

    You can't originate a send for an NBL that you didn't allocate.  In particular, you can't pluck an NBL from the receive path, turn around and send it.  You need to clone the NBL.

    Keep in mind that you can only set the NDIS_SEND_FLAGS_DISPATCH_LEVEL flag if you're actually at dispatch level.  (And don't just check it -- the OS can do that already.)

    There are some remotely-exploitable security issues in this code.  You should work with someone who's got experience writing network drivers to ensure that your packet parser is robust.

    If the purpose of your driver is manipulating HTTP data, you may find that a WFP callout can do this more easily.  A WFP callout can edit the stream data, without having to worry about packet reassembly and fixing up the L2, L3, and L4 headers.

    Tuesday, July 24, 2018 11:23 PM
  • Could you please tell me, How can i enable tracing to troubleshoot the issue for NDIS drivers ?

    -Mrutyunjaya

    Wednesday, July 25, 2018 10:05 AM
  • Read on ndiskd 

    --pa 

    Thursday, July 26, 2018 1:02 PM
  • How can i edit the stream data using WFP call out. Could you please point out to any  msdn link ? or guide me.

    Thanks in advance.

    -Mrutyunjaya

    Saturday, July 28, 2018 5:33 AM
  • Have you seen this?

    https://github.com/Microsoft/Windows-driver-samples/tree/master/network/trans/stmedit

    -- pa

    Saturday, July 28, 2018 9:22 PM
  • Basically, I would like to send the special packet back to the sender then drop the packet. 
    For example: If I receive a packet include string "HELLO_PACKET_WORLD", I will send this packet to the sender, then drop this packet.


    Keep in mind that you can only set the NDIS_SEND_FLAGS_DISPATCH_LEVEL flag if you're actually at dispatch level.  (And don't just check it -- the OS can do that already.)

    Could you please explain little bit more, How can I handle this ?

    Mrutyunjaya

    Wednesday, August 8, 2018 6:21 PM
  • First, let's decide what level you want to filter: L2 or higher. What means "packet": a datagram such as UDP, or L2 packet?

    -- pa

    Wednesday, August 8, 2018 7:42 PM
  • thanks, I would like to filter on L2 level. -Mrutyunjaya
    Thursday, August 9, 2018 4:37 AM
  • Then it likely should be a LFW driver.
    Thursday, August 9, 2018 11:28 AM
  • Keep in mind that you can only set the NDIS_SEND_FLAGS_DISPATCH_LEVEL flag if you're actually at dispatch level.  (And don't just check it -- the OS can do that already.)

    if I am in dispatch level then why can't I set NDIS_SEND_FLAGS_DISPATCH_LEVEL . If OS can do that what can I pass in NdisSendNetBufferLists ?

    -Mrutyunjaya

     

    Thursday, August 9, 2018 7:06 PM
  • If you know you are at DISPACH, of course do set NDIS_SEND_FLAGS_DISPATCH_LEVEL. 

    The text "And don't just check it..." means that you can receive this flag on entry into your function, in this case trust the caller and do not call KeGetCurrentIrql, NDIS_RAISE_IRQL_TO_DISPATCH etc. It is a long story why this flag exists at all...

    -- pa

    Thursday, August 9, 2018 9:01 PM
  • If i would like to filter it L3 or L4 level. I mean, IP or UDP packet. How can I do that ?

    -Mrutyunjaya

    Sunday, August 12, 2018 9:29 AM
  • Then, read the Windows Filtering Platform docum about filtering these layers.

    -- pa

    Sunday, August 12, 2018 9:15 PM