杨洋接吻图片大全:WinDDK自带的 Passthru NDIS网络中间层驱动 学习

来源:百度文库 编辑:中财网 时间:2024/05/11 04:00:14

中间层驱动下面连接ndis miniport驱动,上面连接ndis protocol驱动 ,可以监控所有本机收到的和发出去的网络包。自己写一个NDIS Intermediate Driver (中间层驱动)     可以过滤网络包实现类似防火墙的功能(我不知道那些防火墙是不是这样做的,好像都是去写NDIS Hook Drivers,而不是这个),也可以修改网络包,可以用来做VPN等功能(实际VPN客户端可能不一定是这样做的,不过确实有人写了类似的实例)。

      有上图可以知道中间层是包括protocol和虚拟miniport两部分的,因为我自己做了一个arp防欺骗工具,所以像写一个这样的驱动来截取本机收到的ARP包。因为前面采用ndis protocol驱动来获取arp包也是可以的,但同时在发送ARP包的时候,可能是handle有冲突,我自己弄不好同步问题,索性再写个中间层驱动算了。参考WinDDK自带的 Passthru例子,稍加修改就可以达到目的。我想捕获本机收到的ARP包,所以只要修改protocol.c 中的PtReceivePacket()函数就可以了,本机收到网络包的时候系统是会自动回调这个函数的,我只要在这里过滤ARP包然后转发给自己的应用程序就行了。不过好像说是底层有的miniport不支持直接提交packet上来,所以也有可能是通过PtReceive()这个函数提交数据。所以也要改一下这个函数才行。我实际测试的时候也是有时是在PtReceivePacket()中得到数据,有时是在PtReceive()得到数据的。所以最后两个都改一下吧。如果像过滤本机发出去的网络包,那么看miniport那部分就行了。不过我没有做了,我只是想得到本机收到的ARP包而已了。

改后的PtReceivePacket()函数如下,其他的修改如PtReceive,还有就是和用户态应用程序交互IO控制相应那些,ARP包结构等就不细说了。


INT
PtReceivePacket(
     IN NDIS_HANDLE             ProtocolBindingContext,
     IN PNDIS_PACKET            Packet
     )
/*++

Routine Description:

     ReceivePacket handler. Called by NDIS if the miniport below supports
     NDIS 4.0 style receives. Re-package the buffer chain in a new packet
     and indicate the new packet to protocols above us. Any context for
     packets indicated up must be kept in the MiniportReserved field.

     NDIS 5.1 - packet stacking - if there is sufficient "stack space" in
     the packet passed to us, we can use the same packet in a receive
     indication.

Arguments:

     ProtocolBindingContext - Pointer to our adapter structure.
     Packet - Pointer to the packet

Return Value:

     == 0 -> We are done with the packet
     != 0 -> We will keep the packet and call NdisReturnPackets() this
             many times when done.
--*/
{
     PADAPT               pAdapt =(PADAPT)ProtocolBindingContext;
     NDIS_STATUS          Status;
     PNDIS_PACKET         MyPacket;
     BOOLEAN              Remaining;
//----------------------
      ULONG      readPacketBufferLength;
//-----------------------

 

     //
     // Drop the packet silently if the upper miniport edge isn't initialized or
     // the miniport edge is in low power state
     //
     if ((!pAdapt->MiniportHandle) || (pAdapt->MPDeviceState > NdisDeviceStateD0))
     {
           return 0;
     }

 

///-----widebright增加的 过滤 ARP包的 段----------------------------------------------------------------------------
      DBGPRINT(("PtReceivePacket Function   \n")); //////////////////////////////////////////////////////////
          GetPktPayload(Packet,                             // Copy payload
                   &recARPPacket,                         //    to area.
                   sizeof(recARPPacket),                       // Amount of space in area.
                   &readPacketBufferLength                        // Return number of bytes in packet.
                  );
      
    if (readPacketBufferLength !=0)
    {
           if (recARPPacket.ehhdr.eh_type ==   1544)       // #define EPT_ARP 0x0806    1544= htons(EPT_ARP)   就是看是不是ARP包
     {
            DBGPRINT(("PtReceivePacket Function   and ARP packet \n")); //////////////////////////////////////////////////////////
                         if (pEvent)
                        KeSetEvent(pEvent, 0, 0);    //通知应用程序收到ARP 包了
     }
    }


          //如果return 0 则表示丢弃 包,不传给上一层

///-----widebright增加的 过滤 ARP包的 段----------------------------------------------------------------------------

 

 

#ifdef NDIS51
     //
     // Check if we can reuse the same packet for indicating up.
     // See also: PtReceive().
     //
     (VOID)NdisIMGetCurrentPacketStack(Packet, &Remaining);
     if (Remaining)
     {
         //
         // We can reuse "Packet". Indicate it up and be done with it.
         //
         Status = NDIS_GET_PACKET_STATUS(Packet);
         NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &Packet, 1);
         return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);
     }
#endif // NDIS51

     //
     // Get a packet off the pool and indicate that up
     //
     NdisDprAllocatePacket(&Status,
                            &MyPacket,
                            pAdapt->RecvPacketPoolHandle);

     if (Status == NDIS_STATUS_SUCCESS)
     {
         PRECV_RSVD             RecvRsvd;

         RecvRsvd = (PRECV_RSVD)(MyPacket->MiniportReserved);
         RecvRsvd->OriginalPkt = Packet;

         NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet);
         NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet);

         //
         // Get the original packet (it could be the same packet as the one
         // received or a different one based on the number of layered miniports
         // below) and set it on the indicated packet so the OOB data is visible
         // correctly to protocols above us.
         //
         NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));

         //
         // Set Packet Flags
         //
         NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);

         Status = NDIS_GET_PACKET_STATUS(Packet);

         NDIS_SET_PACKET_STATUS(MyPacket, Status);
         NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet));

         if (pAdapt->MiniportHandle != NULL)
         {
             NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);
         }

         //
         // Check if we had indicated up the packet with NDIS_STATUS_RESOURCES
         // NOTE -- do not use NDIS_GET_PACKET_STATUS(MyPacket) for this since
         // it might have changed! Use the value saved in the local variable.
         //
         if (Status == NDIS_STATUS_RESOURCES)
         {
             //
             // Our ReturnPackets handler will not be called for this packet.
             // We should reclaim it right here.
             //
             NdisDprFreePacket(MyPacket);
         }

         return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);
     }
     else
     {
         //
         // We are out of packets. Silently drop it.
         //
         return(0);
     }
}

 

可以看到我增加的代码是很少的, GetPktPayload是一个从别人的代码里面抄过来的,从packet结构读取包缓存的函数。一并转贴出来吧,如下:

/**************************************************************************************************/      
/*                                                                                                 */      
/* Copy the payload of the specified packet into the specified buffer.                             */      
/*                                                                                                 */      
/* Adapted from http://www.ndis.com/papers/ndispacket/readonpacket.htm, 12 May 2003.               */      
/*                                                                                                 */      
/**************************************************************************************************/      

VOID
GetPktPayload(
               PNDIS_PACKET      pPacket,                // Address of packet descriptor.
               PUCHAR            pOutBfr,                // Address of output buffer, to get copied packet payload.
               ULONG             ulOutBfrAvail,          // Size of output buffer.
               PULONG            pUlBytesCopied          // Output variable for number of bytes copied.
              )
{
    PNDIS_BUFFER     pNdisBfr;
    ULONG            ulBfrCnt,
                    ulTotPktLen,
                    ulCurrBfr,
                    ulAmtToMove;
    PUCHAR           pCurrBfr;

    *pUlBytesCopied = 0;                                // Set 0 bytes copied.

    if (0==ulOutBfrAvail)                               // Is output buffer 0 bytes in length?
      goto Done;

    NdisQueryPacket(pPacket,                            // Get information from packet descriptor.
                    NULL,                      
                    NULL,
                    &pNdisBfr,                          // Output variable for address of first buffer descriptor.
                    &ulTotPktLen                        // Output variable for number of bytes in packet payload.
                   );

    NdisQueryBuffer(pNdisBfr,                           // Get information from first buffer descriptor.
                    &pCurrBfr,                          // Output variable for address of described virtual area.
                    &ulCurrBfr                          // Output variable for size of virtual area.
                   );

    while (ulOutBfrAvail>0)                             // Space remaining in output buffer?
      {
       while (0==ulCurrBfr)                             // While the current buffer has zero length.
         {
          NdisGetNextBuffer(pNdisBfr,                   // Get next buffer descriptor.
                            &pNdisBfr
                           );

          if (NULL==pNdisBfr)                           // None?
            goto Done;

          NdisQueryBuffer(pNdisBfr,                     // Get information from next buffer descriptor.
                          &pCurrBfr,                    // Output variable for address of current buffer.
                          &ulCurrBfr                    // Output variable for size of current buffer.
                         );
         }

       if (ulCurrBfr>ulOutBfrAvail)                     // Does current buffer's usable size exceed space remaining in output buffer?
         ulAmtToMove = ulOutBfrAvail;                   // Use only amount remaining in output buffer.
       else
         ulAmtToMove = ulCurrBfr;                       // Use full size of current buffer.

       NdisMoveMemory(pOutBfr,                          // Copy packet data to output buffer.
                      pCurrBfr,
                      ulAmtToMove
                     );

       *pUlBytesCopied += ulAmtToMove;                  // Update output variable of bytes copied.
       pOutBfr += ulAmtToMove;                          // Update pointer to output buffer.
       ulOutBfrAvail -= ulAmtToMove;                    // Update number of bytes available in output buffer.

       ulCurrBfr = 0;                                   // Force search for next buffer.
      }                                                 // End 'while' copy bytes to output buffer.

Done:
   ;
}

 

这就是获取ARP 包的关键代码了。如果像过滤 TCP/IP包其实也是要修改一点点就行了。

要什么其他的功能自己动手吧,我也是看了一下MSDN的参考而已,不甚明白。

自己动手丰衣足食!  


上一页 1... -1-1-1-1-1-1-1... -1下一页