细节解密NDIS协议驱动为什么能捕获到发送包

NDIS Loopback Discussion

http://www.ndis.com/ndis-ndis5/loopback/loopback.htm

Looping Back NDIS Packets

http://msdn.microsoft.com/en-us/library/ff557071.aspx

============================================================

XP2环境下的具体流程:

tcpip调用ndissend的时候

//////////////////////////////////////////

ndissend(miniport,mypacket)

{

)//这个标志貌似是协议驱动设置混杂模式就会设置上的,上面标志说明中提到,如果一个miniport有多个protocol绑定,只要有有其中一个就会设置上

if(miniport->flag&check_for_loopback)

   {

      ndisMLoopbackPacketX( miniport, mypacket)

   }

}

////////////////////////////

ndisMLoopbackPacketX( miniport, mypacket)

{

  if ((mypacket->Private.NdisPacketFlags & 0x20)//20= fPACKET_ALREADY_LOOPEDBACK

     { return ;}

   ndis_packet * new_packet=NULL;

//ndisMIsLoopbackPacket会申请一个新的new_packet

     is_LOOPBACK_ONLY = ndisMIsLoopbackPacket((_NDIS_MINIPORT_BLOCK *)miniport_block, (_NDIS_PACKET *)mypacket, &new_packet);

    if (new_packet)

      {

    if ( pMini_block->MediaType != 7 )          // 7=NdisMediumArcnet878_2

    {

      确定要loopback上去了,加上20=fPACKET_ALREADY_LOOPEDBACK标志,说明已  经处理过了

      mypacket->Private.NdisPacketFlags |= 0x20u;

  

      ethFilterDprIndicateReceivePacket(miniport_block, new_packet);

      } 

     returnis_LOOPBACK_ONLY ;

}

////////////////////=================================================================

char __fastcall ndisMIsLoopbackPacket(_NDIS_MINIPORT_BLOCK *pMini_block, _NDIS_PACKET *ori_packet, _NDIS_PACKET **pNewPacket)

{

   //里面会有目标地址是否为自身的判断,略过!

    v7 = pMini_block2->MediaType;

  if ( !v7 )                                    // mediatype =0   means NdisMedium802_3

  {

     判断

   if ( !(BYTE2(pMini_block2->Flags) & 0x80) ) // 80,其实就是flags的800000标志,对应着SEND_LOOPBACK_DIRECTED

   {}

  else{

     //一般情况下都是这个分支,说明miniport一般都设置了SEND_LOOPBACK_DIRECTED这个标志位

     判断下包里面的MAC地址是不是本机的MAC地址,我们需要的情况是MAC地址不同

    申请一个新包pNewPacket,把ori_packet数据copy到pNewPacket

        if ( pNewPacket )

        {

          *pNewPacket = pNewPacket_allocated;//pNewPacket_allocated在前面已经copy好数据

          pNewPacket_allocated->Private.NdisPacketFlags |= 2u;// 会多了fPACKET_IS_LOOPBACK, fPACKET_CLEAR_ITEMS这2个属性

          pNewPacket_allocated->Private.Flags = v27->Private.Flags & 0x80 | 0x100;

        }                                       // 80就是DONT_LOOPBACK,但这里是与操作,如果原来没的话,也不会加上

                                                // 100=IS_LOOPBACK_PACKET标明是loopback包

 

     return 0;

     }

 }

}

 PS:如果你想你发送的包不给捕获,很简单,只要把你的包加上DONT_LOOPBACK标志即可,默认是无这个标志的

////////////////////////////////

ethFilterDprIndicateReceivePacket(miniport_block, new_packet)

{

    miniport_filter_header = mini_block->EthDB //_X_FILTER类型,这个_X_FILTER结构有NumOpens字段,标志有多少个协议绑定了它

//pBindInfo是_X_BINDING_INFO类型,

         for ( pBindInfo = miniport_filter_header->OpenList; pBindInfo; pBindInfo = v89 )

      {

        v89 = pBindInfo->NextOpen; //取对应的_NDIS_OPEN_BLOCK

         if ( !(pkt1->Private.Flags & 0x80)      // // 80好像是DONT_LOOPBACK

        {

           v65 = pBindInfo->PacketFilters;

             v66 = (unsigned __int8)(v65 & 0xA0) == 0;// a0就是NDIS_PACKET_TYPE_ALL_LOCAL和NDIS_PACKET_TYPE_PROMISCUOUS的组合

                                                // 这里取值的来源是bindinfo链表,里面每个对应一个绑定信息,说明是针对指定设定的协议驱动,例如A驱动的设置成NDIS_PACKET_TYPE_PROMISCUOUS

                                                // 但如果B协议驱动不设置NDIS_PACKET_TYPE_PROMISCUOUS的话,B协议驱动不能接收到。

          v92 = v65 & 0xA0;

          if ( v66 )                            // 一些其它的协议会跳走。。例如TCP/IP,所以不会重复接收到发送出去的包

                                                // 

                                                // 测试改了tcpip的这个标志位为0x8b后,tcpip!arprecv回调也能接收到发送出去的包,修改之前是不能的

          {                                     // 

                                                // 在我把wireshark协议驱动的这个_X_BINDING_INFO->PacketFilters改为0xb后。

                                                // 由于0xb&a0==0,所以改了之后,就收不到发送出去的包了。但还是能收到外部发来的包,

                                                // 因为发送和接收的包indicate的路径不一样,前者是直接在send的时候判断是否要loopback就直接indicate了

            JUMPOUT(v96, 8u, *(unsigned int *)loc_22FB1);//不符合就循环跳过。。例子中就是tcpip协议驱动不会接收到(出现JUMPOUT,是因为IDA识别函数的范围不准确)

         }

           //条件满足0xA0,调用协议驱动的接收例程,像wireshark为什么能截获发送包就是因为这里的调用了wireshark的协议驱动的ReceiveHandler

      openblock = pBindInfo->NdisBindingHandle

        openblock->ReceiveHandler(   )

         }

}

XP环境,粗略F5,粗略动态跟踪,不保证无错

原文地址:https://www.cnblogs.com/kkindof/p/2542320.html