执着成就未来 技术成就梦想
文字横幅以及760*60黄金广告位置招租,欢迎恰谈! 广告业务联系QQ:8019399 声明:在本站所投放广告内容均与本站立场无关!

您现在的位置: 中国安全在线 >> 攻防技术 >> 菜鸟学习 >> 文章正文 用户登录 新用户注册
专 题 栏 目
最 新 热 门
最 新 推 荐
相 关 文 章
手把手教你玩转ARP包
手把手教你捕获数据包
作者:佚名 来源:安全在线 更新时间:2005-12-26 【字体:
<%=(int(rnd()*1)+1)%>您当前的位置:中国安全在线cnsafer.com 请进入[技术论坛]发表评论

阅读提示:     经常看到论坛有人问起关于数据包的截获、分析等问题,幸好本人也对此略有所知,也写过很多的sniffer,所以就想写一系列的文章来详细深入的探讨关于数据包的知识。 我希望通过这一系列的文章,能使得关于数据包的知识得以普及,所以这系列的每一篇文章我都会有由浅入深的解释、详细的分析、以及编码步骤,另外附上带有详细注释的源码(为了照顾大多数朋友,我提供的都是MFC的源码)。 不过由于也是初学者,疏漏之处还望不吝指正。 本文凝聚着笔者心血,如要转载,请指明原作者及出处,谢谢!^_^   OK,. Let’s go !  Have fun!! q^_^p   第二篇   手把手教你捕获数据包 目录: 一.捕获数据包的实现原理 二.捕获数据包的编程实现: 1.   raw socket的实现方法 2.   Winpcap的实现方法 a.      枚举本机网卡的信息 b.      打开相应网卡并设置为混杂模式 c.       截获数据包并保存为文件   作者: CSDN  VC/MFC 网络编程版主 PiggyXP    一.捕获数据包的实现原理:-------------------------------------------------------------------- 在通常情况下,网络通信的套接字程序只能响应与自己硬件地址相匹配的或是以广播形式发出的数据帧,对于其他形式的数据帧比如已到达网络接口但却不是发给此地址的数据帧,网络接口在验证投递地址并非自身地址之后将不引起响应,也就是说应用程序无法收取与自己无关的的数据包。 所以我们要想实现截获流经网络设备的所有数据包,就要采取一点特别的手段了: 将网卡设置为混杂模式。 这样一来,该主机的网卡就可以捕获到所有流经其网卡的数据包和帧。 但是要注意一点,这种截获仅仅是数据包的一份拷贝,而不能对其进行截断,要想截断网络流量就要采用一些更底层的办法了,不在本文的讨论范围之内。   二. 捕获数据包的编程实现: 1.raw socket的实现方法-------------------------------------------------------------------- 不同于我们常用的数据流套接字和数据报套接字,在创建了原始套接字后,需要用WSAIoctl()函数来设置一下,它的定义是这样的 int WSAIoctl(   SOCKET s,   DWORD dwIoControlCode,   LPVOID lpvInBuffer,   DWORD cbInBuffer,   LPVOID lpvOutBuffer,   DWORD cbOutBuffer,   LPDWORD lpcbBytesReturned,   LPWSAOVERLAPPED lpOverlapped,   LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine ); 虽然咋一看参数比较多,但是其实我们最关心的只是其中的第二项而已,我们需要做的就是把第二项设置为SIO_RCVALL,讲了这么多其实要做的就是这么一行代码,很简单吧?^_^  当然我们还可以指定是否亲自处理IP头,但是这并不是必须的。 完整的代码类似与如下这样,加粗的代码是与平常不同的需要注意的地方: ( 为了让代码一目了然,我把错误处理去掉了,下同)   #include “WinSock2.h” #define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)   SOCKET SnifferSocket   WSADATA wsaData;   iFlag=WSAStartup(MAKEWORD(2,2),&wsaData);           //开启winsock.dll                                   SnifferSocket=WSASocket(AF_INET,             //创建raw  socket SOCK_RAW,IPPROTO_IP,NULL,0,WSA_FLAG_OVERLAPPED);     char FAR name[128];                                //获取本机IP地址 gethostname(name, sizeof(name));   struct hostent FAR * pHostent;   pHostent = gethostbyname(name);     SOCKADDR_IN sa;                           //填充SOCKADDR_IN结构的内容   sa.sin_family = AF_INET;   sa.sin_port = htons(6000);           // 端口号可以随便改,当然与当然系统不能冲突   memcpy(&(sa.sin_addr),pHostent->h_addr,pHostent->h_length);   bind(SnifferSocket,(LPSOCKADDR)&sa,sizeof(sa));            //绑定   // 置ioctl来接收所有网络数据,关键步骤   DWORD dwBufferLen[10] ;   DWORD dwBufferInLen = 1 ;   DWORD dwBytesReturned = 0 ;   WSAIoctl(SnifferSocket, IO_RCVALL,&dwBufferInLen, izeof(dwBufferInLen),         &dwBufferLen, sizeof(dwBufferLen),&dwBytesReturned , NULL , NULL ); 至此,实际就可以开始对网络数据包进行嗅探了,而对于数据包的接收还是和普通的socket一样,通过recv()函数来完成,因为这里涉及到不同的socket模型,接收方法差别很大,所以在此就不提供接收的代码了。   2.winpcap的实现方法:----------------------------------------------------------------------- winpcap驱动包,是我们玩转数据包不可或缺的好东东,winpcap的主要功能在于独立于主机协议(如TCP-IP)而发送和接收原始数据报,主要为我们提供了四大功能: 功能:
    1> 捕获原始数据报,包括在共享网络上各主机发送/接收的以及相互之间交换的数据报;
    2> 在数据报发往应用程序之前,按照自定义的规则将某些特殊的数据报过滤掉;
    3> 在网络上发送原始的数据报;
    4> 收集网络通信过程中的统计信息 如果环境允许的话(比如你做的不是木马程序),我还是推荐大家用winpcap来截获数据包,因为它的功能更强大,工作效率更高,唯一的缺点就是在运行用winpcap开发的程序以前,都要在主机上先安装winpcap的driver。 而且一会我们就会发现它比raw socket功能强大的多,而且工作得更为底层,最明显的理由就是raw socket捕获的数据包是没有以太头的,此乃后话。 至于怎么来安装使用,请参考本系列的系列一《手把手教你玩转ARP包中的》,里面有详细的加载winpcap驱动的方法^_^ 废话不多说了,让我们转入正题, 具体用winpcap来截获数据包需要做如下的一些工作: A . 枚举本机网卡的信息(主要是获得网卡的名称)    其中要用到pcap_findalldevs函数,它是这样定义的    /************************************************* int pcap_findalldevs  (  pcap_if_t **    alldevsp,                               char *    errbuf                           )       功能:              枚举系统所有网络设备的信息      参数:  alldevsp:  是一个pcap_if_t结构体的指针,如果函数pcap_findalldevs函数执行成功,将获得一个可用网卡的列表,而里面存储的就是第一个元素的指针。              Errbuf:    存储错误信息的字符串      返回值: int :   如果返回0 则执行成功,错误返回 -1。   *************************************************/    我们利用这个函数来获得网卡名字的完整代码如下:          pcap_if_t* alldevs;        pcap_if_t* d;        char errbuf[PCAP_ERRBUF_SIZE];        pcap_findalldevs(&alldevs,errbuf);       // 获得网络设备指针        for(d=alldevs;d;d=d->next)               // 枚举网卡然后添加到ComboBox中        { d->name;                            // d->name就是我们需要的网卡名字字符串,按照你// 自己的需要保存到你的相应变量中去        } pcap_freealldevs(alldevs);               // 释放alldev资源 B. 打开相应网卡并设置为混杂模式:    在此之前肯定要有一段让用户选择网卡、并获得用户选择的网卡的名字的代码,既然上面已经可以获得所有网卡的名字了,这段代码就暂且略过了。    我们主要是要用到 pcap_open_live 函数,不过这个函数winpcap的开发小组已经建议用pcap_open 函数来代替,不过因为我的代码里面用的就是pcap_open_live,所以也不便于修改了,不过pcap_open_live使用起来也是没有任何问题的,下面是pcap_open_live的函数声明:  /************************************************* pcap_t* pcap_open_live  (  char *    device,                               int    snaplen,    int    promisc,    int    to_ms,    char *    ebuf  )        功能:            根据网卡名字打开网卡,并设置为混杂模式,然后返回其句柄      参数:            Device  : 就是前前面我们获得的网卡的名字;            Snaplen :  我们从每个数据包里取得数据的长度,比如设置为100,则每次我们只是获得每个数据包 100 个长度的数据,没有什么特殊需求的话就把它设置为65535最大值就可以了;            Promisc:这个参数就是设置是否把网卡设置为“混杂模式”,设置为 1 即可;            to_ms :   超时时间,毫秒,一般设置为 1000即可。      返回值:            pcap_t :  类似于一个网卡“句柄”之类的,不过当然不是,这个参数是后面截获数据要用到的。 ******************************************************************************/ 虽然看起来比较复杂,不过用起来还是非常简单的,其实 1 行就OK了:     pcap_t* adhandle;        char errbuf[PCAP_ERRBUF_SIZE]; // 打开网卡,并且设置为混杂模式 // pCardName是前面传来的网卡名字参数 adhandle = pcap_open_live(pCardName,65535,1,1000,errbuf);   C. 截获数据包并保存为文件:------------------------------------------------------      当然,不把数据包保存为文件也可以,不过如果不保存的话,只能在截获到数据包的那一瞬间进行分析,转眼就没了^_^ 所以,为了便于日后分析,所以高手以及我个人经常是把数据包保存下来的慢慢分析的。 但是注意网络流量,在流量非常大的时候注意硬盘空间呵呵,常常几秒中就有好几兆是很正常的事情。 下面首先来详细讲解一下,这个步骤中需要用到的winpcap函数: /************************************************************** pcap_dumper_t* pcap_dump_open  (  pcap_t *    p,                                        const char *    fname  ) 功能:       建立或者打开存储数据包内容的文件,并返回其句柄 参数:        pcap_t *    p     :前面打开的网卡句柄;       const char * fname :要保存的文件名字    返回值:        pcap_dumper_t* : 保存文件的描述句柄,具体细节我们不用关心 ***************************************************************/ /*************************************************************** int pcap_next_ex          (  pcap_t *    p,              

[1] [2] 下一页

您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力

文章录入:ls1238    责任编辑:ls1238 
  • 上一篇文章:

  • 下一篇文章:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    | 设为首页 | 加入收藏 | 联系方式 | 友 情链接 | 关于我们 | 网站留言 |
    Copyright ?2003-2008 www.cnsafer.com All Rights Reserved.
    如有意见请与我们联系 Email:admin#mail.cnsafer.com 联系QQ:8589101
    中国安全在线友情提示:建议使用IE6.0或以上版本, 分辩率1024*768进行浏览
    敢想 敢做 挑战自我 努力做最好 打造最优秀的新手成长 第一起跑线
    中网科技有限公司 技术支持 鄂ICP备05006475号