您的位置:首页 > 其它

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

2012-06-08 22:01 239 查看
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,粗略动态跟踪,不保证无错
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: