小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

WinDDK自帶的 Passthru NDIS網(wǎng)絡(luò)中間層驅(qū)動 學(xué)習(xí)

 tuohuang0303 2011-04-05

中間層驅(qū)動下面連接ndis miniport驅(qū)動,上面連接ndis protocol驅(qū)動 ,可以監(jiān)控所有本機(jī)收到的和發(fā)出去的網(wǎng)絡(luò)包。自己寫一個NDIS Intermediate Driver (中間層驅(qū)動)     可以過濾網(wǎng)絡(luò)包實(shí)現(xiàn)類似防火墻的功能(我不知道那些防火墻是不是這樣做的,好像都是去寫NDIS Hook Drivers,而不是這個),也可以修改網(wǎng)絡(luò)包,可以用來做VPN等功能(實(shí)際VPN客戶端可能不一定是這樣做的,不過確實(shí)有人寫了類似的實(shí)例)。

      有上圖可以知道中間層是包括protocol和虛擬miniport兩部分的,因?yàn)槲易约鹤隽艘粋€arp防欺騙工具,所以像寫一個這樣的驅(qū)動來截取本機(jī)收到的ARP包。因?yàn)榍懊娌捎胣dis protocol驅(qū)動來獲取arp包也是可以的,但同時(shí)在發(fā)送ARP包的時(shí)候,可能是handle有沖突,我自己弄不好同步問題,索性再寫個中間層驅(qū)動算了。參考WinDDK自帶的 Passthru例子,稍加修改就可以達(dá)到目的。我想捕獲本機(jī)收到的ARP包,所以只要修改protocol.c 中的PtReceivePacket()函數(shù)就可以了,本機(jī)收到網(wǎng)絡(luò)包的時(shí)候系統(tǒng)是會自動回調(diào)這個函數(shù)的,我只要在這里過濾ARP包然后轉(zhuǎn)發(fā)給自己的應(yīng)用程序就行了。不過好像說是底層有的miniport不支持直接提交packet上來,所以也有可能是通過PtReceive()這個函數(shù)提交數(shù)據(jù)。所以也要改一下這個函數(shù)才行。我實(shí)際測試的時(shí)候也是有時(shí)是在PtReceivePacket()中得到數(shù)據(jù),有時(shí)是在PtReceive()得到數(shù)據(jù)的。所以最后兩個都改一下吧。如果像過濾本機(jī)發(fā)出去的網(wǎng)絡(luò)包,那么看miniport那部分就行了。不過我沒有做了,我只是想得到本機(jī)收到的ARP包而已了。

改后的PtReceivePacket()函數(shù)如下,其他的修改如PtReceive,還有就是和用戶態(tài)應(yīng)用程序交互IO控制相應(yīng)那些,ARP包結(jié)構(gòu)等就不細(xì)說了。


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);    //通知應(yīng)用程序收到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結(jié)構(gòu)讀取包緩存的函數(shù)。一并轉(zhuǎn)貼出來吧,如下:

/**************************************************************************************************/      
/*                                                                                                 */      
/* Copy the payload of the specified packet into the specified buffer.                             */      
/*                                                                                                 */      
/* Adapted from http://www./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 包的關(guān)鍵代碼了。如果像過濾 TCP/IP包其實(shí)也是要修改一點(diǎn)點(diǎn)就行了。

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

自己動手豐衣足食!  


    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多