怎样才能抓IP包?(200分)

  • 主题发起人 主题发起人 Summit80
  • 开始时间 开始时间
i hu le u!gaoshou gaoshou gaogaoshou
 
去看一看嗅探器的原理吧,《黑客就这么几招》上有,我可忘了是什么出版社了。
 
to http://netgroup-serv.polito.it/
 
Vpacket的Vxd比较直接,不过netgroup的驱动可以运行在nt上,
 
有兴趣的DFWER请提前或回答,否则就结束问题了,谢谢
 
在98或NT下需要驱动程序,在2000下不需要,具体程序如下(你可以参考sniffer的工作原理):
无需驱动程序的Sniffer-IPMon
在Windows平台上实现的Sniffer一般都需要自己写驱动程序,例如在Win9x
下面是通过写一个驱动程序用Hook_Device_Service( )来挂接ndis.vxd提供

的服务,在WinNT/2K下面则一般是需要写一个中间驱动程序(请参考白云黄

鹤站的相关文章以及http://www.pcausa.com的论述)。

Arkady Frankel(arkadyf@hotmail.com) 在CodeGuru上给出了一个无需自

己编写驱动程序的Sniffer-IPMon。该程序利用了WinSock 2的特性,只能

运行在Win2K平台上。WinSock 2允许程序使用WSAIoctl( )给一个SOCK_RAW类

型的socket设置SIO_RCVALL属性,这样该socket就可以收到所有经过本机的

数据。 下面简单分析一下其实现方法。


首先打开一个socket,参数必须是 AF_INET、SOCK_RAW和IPPROTO_IP,否则

不能设置SIO_RCVALL属性:


m_s = socket( AF_INET , SOCK_RAW , IPPROTO_IP ) ;

if( INVALID_SOCKET == m_s )

{

dwErr = WSAGetLastError() ;

sprintf( szErr , "Error socket() = %ld " , dwErr ) ;

AfxMessageBox( szErr ) ;

return ;

}


然后可以设置一下该socket的超时参数等选项:


int rcvtimeo = 5000 ;

if( setsockopt( m_s , SOL_SOCKET , SO_RCVTIMEO ,

(const char *)&rcvtimeo , sizeof(rcvtimeo) ) == SOCKET_ERROR)

{

dwErr = WSAGetLastError() ;

sprintf( szErr , "Error WSAIoctl = %ld " , dwErr ) ;

AfxMessageBox( szErr ) ;

closesocket( m_s ) ;

return ;

}


再将该socket与本机的某个网络接口绑定(注意绑定的IP地址不能是INADDR_ANY):


sa.sin_family = AF_INET;

sa.sin_port = htons(7000);

sa.sin_addr.s_addr= m_iphostsource;

if (bind(m_s,(PSOCKADDR)&sa, sizeof(sa)) == SOCKET_ERROR)

{

dwErr = WSAGetLastError() ;

sprintf( szErr , "Error bind() = %ld " , dwErr ) ;

AfxMessageBox( szErr ) ;

closesocket( m_s ) ;

return ;

}


接下来就可以设置SIO_RCVALL属性。此后就可以利用这个socket来读取经

过本机的数据包了。IPMon创建了一个新线程专门来读取该socket,以防止

处理用户输入的主线程被阻塞。


if( SOCKET_ERROR != WSAIoctl( m_s, SIO_RCVALL , &dwBufferInLen,

sizeof(dwBufferInLen),&dwBufferLen, sizeof(dwBufferLen),

&dwBytesReturned , NULL , NULL ) )

AfxBeginThread( threadFunc , (LPVOID)this );

else

{

dwErr = WSAGetLastError() ;

sprintf( szErr , "Error WSAIoctl = %ld " , dwErr ) ;

AfxMessageBox( szErr ) ;

closesocket( m_s ) ;

return ;

}


新线程中读取socket的代码也非常简单,只需要反复调用recv( )即可:


memset( buf , 0 , sizeof(buf) ) ;

iRet = recv( pDlg->m_s , buf , sizeof( buf ) , 0 ) ;

if( iRet == SOCKET_ERROR )

{

dwErr = WSAGetLastError() ;

sprintf( szErr , "Error recv() = %ld " , dwErr ) ;

continue ;

}

else

if( *buf )

{

bufwork = buf ;

pIpHeader = (IPHEADER *)bufwork ;

WORD iLen = ntohs(pIpHeader->total_len) ;

......

}


此时pIpHeader就指向buf中的RAW IP数据包,如何处理就看自己的需要了。


总之这个实现是非常方便的,不用自己编写复杂的抓包代码,所有重要

的工作都由WinSock自己封装了。WSAIoctl( )还有其它一些比较有用的

参数,如SIO_RCVALL_MCAST参数使socket可以接收所有的多播数据,

SIO_RCVALL_IGMPMCAST参数则可以接收IGMP多播数据。实际测试的时候

发现IPMon经常无法看到本机发出去的数据包(偶尔能收到),不知是什

么原因。



参考资料:

1、http://www.codeguru.com/network/ipmon.html

2、MSDN


 
我对实现sniffer非常感兴趣。[:)]
 
WinSock 2允许程序使用WSAIoctl( )给一个SOCK_RAW类
型的socket设置SIO_RCVALL属性,这样该socket就可以收到所有经过本机的
数据。

但是这种方式效率比较低,网络流量大时,丢包情况比较严重。
 
越到底层的东西就越少人愿意透气!!!!!!
 
谁有例子啊?
 

zhaqiong.delphibbs.com上有个程序,您看一下,满意在联系ZhaQiong@CUniware.Com.
 
如果光是“抓IP包”:
Win2000的:http://delphi.mychangshu.com/dispdoc.asp?id=133
(这个好象就是ZhaQiong大虾的:))
Win98的:http://delphi.mychangshu.com/dispdoc.asp?id=278
有源码。
 
好像有控件忘了在那,找找
 
我也需要这个代码
turan2003_27@hotmail.com
 
我也想要
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部