//真正的过滤函数是这个,在最早的IRPdispatch里面传递的这个函数。
//这个函数就是系统传递了一个包头和包内容和包长度之类的东西,你可以在里面进行一些处理,
//假如你想让这个包通过的话,就返回PF_FORWARD,或者你不想让包通过的话,就返回PF_D
ROP就拦住了。是不是
//听起来很简单,
PF_FORWARD_ACTION cbFilterFunction(IN unsigned char *PacketHeader,IN
unsigned char *Packet, IN unsigned int PacketLength, IN unsigned int
RecvInterfaceIndex, IN unsigned int SendInterfaceIndex, IN unsigned long
RecvLinkNextHop, IN unsigned long SendLinkNextHop)
{
IPPacket *ipp;
TCPHeader *tcph;
UDPHeader *udph;
int countRule=0;
struct filterList *aux = first;
//we "extract" the ip Header
ipp=(IPPacket *)PacketHeader;
// dprintf("Source: %x\nDestination: %x\nProtocol: %d", ipp->ipSource,
ipp->ipDestination, ipp->ipProtocol);
//TCP -> protocol = 6
//we accept all packets of established connections
if(ipp->ipProtocol == 6)
{
tcph=(TCPHeader *)Packet;
// dprintf("FLAGS: %x\n", tcph->flags);
//if we havent the bit SYN activate, we pass the packets
if(!(tcph->flags & 0x02))
return PF_FORWARD;
}
//otherwise, we compare the packet with our rules
while(aux != NULL)
{
// dprintf("Comparing with Rule %d", countRule);
//if protocol is the same....
if(aux->ipf.protocol == 0 || ipp->ipProtocol ==
aux->ipf.protocol)
{
//we look in source Address
if(aux->ipf.sourceIp != 0 && (ipp->ipSource &
aux->ipf.sourceMask) != aux->ipf.sourceIp)
{
aux=aux->next;
countRule++;
continue;
}
// we look in destination address
if(aux->ipf.destinationIp != 0 && (ipp->ipDestination
& aux->ipf.destinationMask) != aux->ipf.destinationIp)
{
aux=aux->next;
countRule++;
continue;
}
//if we have a tcp packet, we look in ports
//tcp, protocol = 6
if(ipp->ipProtocol == 6)
{
if(aux->ipf.sourcePort == 0 ||
tcph->sourcePort == aux->ipf.sourcePort)
{
if(aux->ipf.destinationPort == 0
|| tcph->destinationPort == aux->ipf.destinationPort) //puerto tcp destino
{
//now we decided what
to do with the packet
if(aux->ipf.drop)
return PF_DROP;
else
return PF_FORWARD;
}
}
}
//udp, protocol = 17
else if(ipp->ipProtocol == 17)
{
udph=(UDPHeader *)Packet;
if(aux->ipf.sourcePort == 0 ||
udph->sourcePort == aux->ipf.sourcePort)
{
if(aux->ipf.destinationPort == 0
|| udph->destinationPort == aux->ipf.destinationPort)
{
//now we decided what
to do with the packet
if(aux->ipf.drop)
return
PF_DROP;
else
return
PF_FORWARD;
}
}
}
else
{
//for other packet we dont look more and
....
//now we decided what to do with the
packet
if(aux->ipf.drop)
return PF_DROP;
else
return PF_FORWARD;
}
}
//compare with the next rule
countRule++;
aux=aux->next;
}
//we accept all not registered
return PF_FORWARD;
}
winpcap也是用的NDIS,将自己注册为一个协议处理驱动。(在原代码的driverentry里面能看到)
又:上面这个drvipflt这个代码的过滤部分不知道大家是不是看起来很熟悉,是的,是抄的那个nu
mege的驱动开发包里面的一个包过滤程序里的,看来老外也是喜欢到处抄的。
ruike:
读研的时候专门搞过nids,因此对winpcap可以说是情有独钟,这个东东确实好用,但也确实很烦
人,它有一个致命的缺陷就是只适用于共享式以太网络,对于交换式网络下的数据则无能为力,我
专门做过测试,在使用交换机连接的局域网下,只能监听到本网段内的数据,而对于来自其他网段
的数据则无法监听,除非你把probe接到交换机之前或者接到交换机的console口上,不过那样的
弊端是显而易见的。
所以,winpcap的应用还是很有局限性的!
kingzai:
实现交换网络的嗅探也有不少方法的
1.将你的抓包程序放在网关或代理服务器上,这样抓到整个局域网的包。
2.对交换机实行端口映射,将该端口的数据包全部映射到某个监控机器上。
3.在交换机和路由器之间连接一个HUB,这样数据将以广播的方式发送。
4.实行ARP欺骗,即在你的机器上实现整个包的转发,不过会降低整个局域网的效率。
warton:
嗅探对策:
光说嗅探了,我说说反嗅探吧:)
1.检查网内的主机上是否将网卡设置为混合模式(有很多工具可以做到,AntiSniff,Promiscan,S
entinel等)
2.对EtterCap这样的交换网络嗅探器(进行ARP欺骗),可以采用防止ARP欺骗的方法来对待
3.SSH加密通道
4.SSL
5.VPN
6.PGP等
目前这用利用网卡混合模式来进行sniffer的软件看来作用不太大了,所以应该多考虑交换网络的可
行办法:
MAC Flooding,MAC Duplicating,ARP欺骗等等
这些方法实现起来就不怎么容易了,欢迎有兴趣的朋友提供相关的资料,呵呵!
netsys:
难道没人用过RAW SOCKET 吗?
虽然WINPCP功能很大,但RAW SOCKET可以让你直接了SOCKET的原生机制。
实际上我提的那两个问题是很容易解决的。。
netsys2:
对于一些混合模式的SNIFFER,大多采用发送特殊ARP包的方式,正确的网卡不会响应,而处于
混合模式的网卡则会响应。
当然,ARP与IP处于同层,因此你不能用RAW SOCKET完成,你需WinPcap支持工作。
下面是部分代码
AnsiString msgStatus;
extern TArpFuncParam wParams;
int BuildARPPacket(PArpPacket ArpPacket, unsigned char *dst_etheraddr,
unsigned char *src_etheraddr, int ar_op, unsigned
char *ar_sha,
unsigned char *ar_sip, unsigned char *ar_tha,
unsigned char *ar_tip,unsigned short int ar_hw)
{
memcpy(&(ArpPacket->eth_dst_addr), dst_etheraddr, ETH_ADD_LEN);
memcpy(&(ArpPacket->eth_src_addr), src_etheraddr, ETH_ADD_LEN);
ArpPacket->eth_type = htons(ETH_TYPE_ARP);
ArpPacket->ar_hrd = htons(ar_hw);
ArpPacket->ar_pro = htons(ARP_PRO_IP);
ArpPacket->ar_hln = ARP_ETH_ADD_SPACE;
ArpPacket->ar_pln = ARP_IP_ADD_SPACE;
ArpPacket->ar_op = htons(ar_op);
memcpy(&(ArpPacket->ar_sha), ar_sha, ARP_ETH_ADD_SPACE);
memcpy(&(ArpPacket->ar_spa), ar_sip, ARP_IP_ADD_SPACE);
memcpy(&(ArpPacket->ar_tha), ar_tha, ARP_ETH_ADD_SPACE);
memcpy(&(ArpPacket->ar_tpa), ar_tip, ARP_IP_ADD_SPACE);
memset(ArpPacket->eth_pad, 32, ETH_PADDING_ARP);
return(EXIT_SUCCESS);
}
int OpenAdapter(LPADAPTER *lpAdapter)
{
*lpAdapter =
PacketOpenAdapter(wParams.AdapterList[wParams.SelectedAdapter]);
if(!(*lpAdapter) || ((*lpAdapter)->hFile == INVALID_HANDLE_VALUE))
{
msgStatus = "Error : unable to open the driver.";
SHOWSTAT(msgStatus);
return(EXIT_FAILURE);
}
return(EXIT_SUCCESS);
}
void CloseAdapter(LPADAPTER lpAdapter)
{
PacketCloseAdapter(lpAdapter);
}
void GetLocalMAC(LPADAPTER lpAdapter, unsigned char *ether_addr)
{
ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA) + sizeof(ULONG) - 1);
PPACKET_OID_DATA OidData;
OidData = (struct _PACKET_OID_DATA *)malloc(IoCtlBufferLength);
OidData->Oid = OID_802_3_CURRENT_ADDRESS;
OidData->Length = 6;
if(PacketRequest(lpAdapter, FALSE, OidData) == FALSE)
memcpy(ether_addr, 0, 6);
else
memcpy(ether_addr, OidData->Data, 6);
free(OidData);
}
int GetARPReply(LPPACKET lpPacket, unsigned char *iptarget, unsigned char
*result)
{
unsigned short int ether_type;
unsigned char ipsender[4];
unsigned int off=0;
unsigned int tlen;
struct bpf_hdr *hdr;
char *pChar;
char *buf;
buf = (char *)lpPacket->Buffer;
hdr = (struct bpf_hdr *)(buf + off);
tlen = hdr->bh_caplen;
off += hdr->bh_hdrlen;
pChar = (char*)(buf + off);
off = Packet_WORDALIGN(off + tlen);
memcpy(ðer_type, pChar + 12, 2);
ether_type = ntohs(ether_type);
if(ether_type == ETH_TYPE_ARP)
{
memcpy(ipsender, pChar + 28, 4);
if((iptarget[0] == ipsender[0])&&(iptarget[1] == ipsender[1])&&
(iptarget[2] == ipsender[2])&&(iptarget[3] == ipsender[3]))
memcpy(result, pChar + 22, 6);
else
return(EXIT_FAILURE);
}
else
return(EXIT_FAILURE);
return(EXIT_SUCCESS);
}
int CheckPROMode(LPADAPTER lpAdapter, unsigned char *iptarget, unsigned char
*remotemac)
{
LPPACKET lpPacketRequest;
LPPACKET lpPacketReply;
char buffer[256000];
TArpPacket ArpPacket;
unsigned char magicpack[ETH_ADD_LEN]= {0xFF,0xFF,0xFF,0xFF,0xFF,0xFE};
unsigned char mactarget[ARP_ETH_ADD_SPACE];
DWORD timestamp = 0;
int numPacks = 0;
/* Init fields */
memset(mactarget, 0, 6);
/* Allocate PACKET structure for ARP Request packet */
if((lpPacketRequest = PacketAllocatePacket()) == NULL)
{
msgStatus = "Error : failed to allocate the LPPACKET structure..";
SHOWSTAT(msgStatus);
return(EXIT_FAILURE);
}
/* Init packet structure */
memset(&ArpPacket, 0, sizeof(TArpPacket));
/* Build ARP Request packet */
BuildARPPacket(&ArpPacket, magicpack, wParams.srcMAC, ARP_OP_REQUEST,
wParams.srcMAC, wParams.srcIPAdd, mactarget, iptarget,wParams.ar_hw);
/* Init ARP Request packet */
PacketInitPacket(lpPacketRequest, &ArpPacket, sizeof(ArpPacket));
/* Set number of ARP Request packets to send */
if(PacketSetNumWrites(lpAdapter, 1) == FALSE)
{
msgStatus = "Warning : unable to send more than one packet in a single write..";
SHOWSTAT(msgStatus);
}
/* Set hardware filter to directed mode */
if(PacketSetHwFilter(lpAdapter, NDIS_PACKET_TYPE_DIRECTED) == FALSE)
{
msgStatus ="Warning: unable to set directed mode..";
SHOWSTAT(msgStatus);
}
/* Set a 512K buffer in the driver */
if(PacketSetBuff(lpAdapter, 512000) == FALSE)
{
msgStatus = "Error: unable to set the kernel buffer..";
SHOWSTAT(msgStatus);
PacketFreePacket(lpPacketRequest);
return(EXIT_FAILURE);
}
/* Set a 1 second read timeout */
if(PacketSetReadTimeout(lpAdapter, -1) == FALSE)
{
msgStatus = "Warning: unable to set the read tiemout..";
SHOWSTAT(msgStatus);
}
/* Allocate PACKET structure for ARP Reply packet */
if((lpPacketReply = PacketAllocatePacket()) == NULL)
{
msgStatus = "Error: failed to allocate the LPPACKET structure..";
SHOWSTAT(msgStatus);
PacketFreePacket(lpPacketRequest);
return(EXIT_FAILURE);
}
/* Init ARP Reply packet */
PacketInitPacket(lpPacketReply, (char*)buffer, 256000);
/* Allocate memory for remote MAC address */
timestamp = GetTickCount();
/* Main capture loop */
for(;;)
{
if(numPacks < wParams.numPacks)
{
/* Send packet */
if(PacketSendPacket(lpAdapter, lpPacketRequest, TRUE) == FALSE)
{
msgStatus ="Error : unable to send the packets..";
SHOWSTAT(msgStatus);
PacketFreePacket(lpPacketRequest);
PacketFreePacket(lpPacketReply);
return(EXIT_FAILURE);
}
/* Free packet */
PacketFreePacket(lpPacketRequest);
numPacks += 1;
}
/* Capture the packets */
if(PacketReceivePacket(lpAdapter, lpPacketReply, TRUE) == FALSE)
{
msgStatus = "Error: PacketReceivePacket failed..";
SHOWSTAT(msgStatus);
PacketFreePacket(lpPacketReply);
return(EXIT_FAILURE);
}
if(lpPacketReply->ulBytesReceived > 0)
if(GetARPReply(lpPacketReply, iptarget, remotemac) == EXIT_SUCCESS)
break;
if((GetTickCount() - timestamp) > wParams.delay)
{
PacketFreePacket(lpPacketReply);
return(EXIT_FAILURE);
}
}
/* Free packet */
PacketFreePacket(lpPacketReply);
return(EXIT_SUCCESS);
}
sunxufei:
哦,交换机是以MAC地址进行交换的,不是IP那一层的,要IP已经路由器了
现在交换机便宜了,因此以后你想用sniffer抓密码概率不大了,不过还能多公司仍然是交换机和H
UB一起用的,这样小范围内是有效地,至于ADSL CABLE FTTB,我的FTTB是用华为设计的设备
,呵呵,不仅仅工网IP,只有我和交换机两个MAC(这次中国人干的不错),没希望找到第三者,很安全,但
不都这样安全,很多人的网络还是很糟糕的.
很多加密协议可以用来提高安全性,但老的POP3,SMTP,HTTP,FTP这种协议应用广泛,不可能在短
时间内完全取代,而且加密也是有待价的,所以对于要求较高的场合,才会加密.
不过sniffer不是给大家偷密码用的,我当初用来学习网络,看看包的样子,后来就用来当作网管工具,
分析网络的健康与否,其实这样的话,你知道,很有可能sniffer就是接在我需要探测的网络上,听诊器
吗,到处都听听,呵呵,因此即使用了交换机,sniffer仍然是有用处的,但不是抓密码!!
Wincap很简单,大3的学生不要怕,去他的网站看看,有例子的,VC6编译,BCB也行的,把lib的格式转
换一下,不过写这种程序,你最好先熟悉协议,很多协议在linux里有现成的源代码,主要是一些struct
吧,移植时注意VC可不是gcc,有些c的高级语法,编译选项要注意,否则差一个byte你就得不到正确的
结果.
如果你搞不到sniffer,Win2000 Server也有网络包查看器的,不比sniffer强大,但简单的东西入手
也快.
反嗅探和嗅探技术其实很old了,呵呵,不过CSDN经常old的.
注意不要干坏事,有矛必有盾
sevencat:
网卡的混杂模式好像要通过NDIS设置。
下面是转贴的。
哪位UP一下,我来贴完。
一、驱动开发网
作者:gjpland
看到很多仁兄提供的数据包的拦截技术,其中最多的是编写IM DRIVER在NDIS中间层
对MINIPORT(网卡驱动程序)和协议驱动程序之间的数据包进行拦截。这是微软提供的一种技术
但编写该过滤程序拦截程序非常的复杂,安装也很麻烦。
本人简单的介绍一种更有效的基于NDIS包拦截技术。
大家都知道,NDIS协议驱动程序是通过填写一张NDIS_PROTOCOL_CHARACTERISTICS的表
,并调用NDIS API
函数NdisRegisterProtocol进行注册。现在我们来关注一下NDIS_PROTOCOL_CHARACTERI
STICS这张表,
这张表中存有所有协议驱动程序与底层的派发函数的入口。如SendHandler,ReceiveHandler,Bi
ndAdapterHandler等,
当网卡有数据包进入时,会通过表中ReceiveHandle 或ReceivePacketHandler通知协议驱动程
序有一个该协议
的数据包进入,反之协议驱动程序是通过SendHandler或SendPacketsHandler函数向网卡驱动
发送数据包到网络
上去的,有人会奇怪程序中明明不是调用NdisSend或NdisSendPackets函数发送的吗?没错,
是这样的,
但是你可以看一下NDIS.H的头文件里对这两个函数的定义就知道了,他们都是一个
宏定义,实际还是通过这表中SendHandler或SendPacketsHandler发送的。
现在我们所要做的事情应该很清楚了,只要我们能够将每一个协议程序所填写的NDIS_PROTOCO
L_CHARACTERISTICS
表里的派发函数指向自己的函数,我们就能成功的对数据包进行拦截。那么每个协议驱动程序的这张
表到底存放在
那里呢?太简单了,看一下下面的我对NdisRegisterProtocol重新给出的原型就很明白了。
struct _NDIS_PROTOCOL_BLOCK
{
PNDIS_OPEN_BLOCK OpenQueue; // queue of opens for this protocol
REFERENCE Ref; // contains spinlock for OpenQueue
UINT Length; // of this NDIS_PROTOCOL_BLOCK struct
NDIS50_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics;// handler
addresses
struct _NDIS_PROTOCOL_BLOCK * NextProtocol; // Link to next
ULONG MaxPatternSize;
#if defined(NDIS_WRAPPER)
//
// Protocol filters
//
struct _NDIS_PROTOCOL_FILTER * ProtocolFilter[NdisMediumMax+1];
WORK_QUEUE_ITEM WorkItem; // Used during NdisRegisterProtocol to
// notify protocols of existing drivers.
KMUTEX Mutex; // For serialization of Bind/Unbind requests
PKEVENT DeregEvent; // Used by NdisDeregisterProtocol
#endif
};
typedef struct _NDIS_PROTOCOL_BLOCK NDIS_PROTOCOL_BLOCK,
*PNDIS_PROTOCOL_BLOCK;
EXPORT
VOID
NdisRegisterProtocol(
OUT PNDIS_STATUS Status,
OUT PNDIS_PROTOCOL_BLOCK NdisProtocolHandle, /*注意NDIS_HANDLE所指向的
就是PNDIS_PROTOCOL_BLOCK的结构,不要有什么怀疑。*/
IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics,
IN UINT CharacteristicsLength
);








