WinPcap编程渐进教程.doc_第1页
WinPcap编程渐进教程.doc_第2页
WinPcap编程渐进教程.doc_第3页
WinPcap编程渐进教程.doc_第4页
WinPcap编程渐进教程.doc_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

WinPcap编程渐进教程 2008-09-25 16:59:51标签:WinPcap 编程 教程 推送到技术圈 【网络编程】翻译 WinPcap编程渐进教程(1)- - 翻译 WinPcap编程渐进教程 WinPcap 教程 原文出处:http:/winpcap.polito.it/docs/man/html/index.html 作者: Loris Degioanni (degioannipolito.it), NetGroup, Politecnico di Torino http:/winpcap.polito.it 译者: 记忆碎片 (val_) 概述: 这篇教程将会指引读者逐步了解WinPcap编程, 从简单的基础函数(获取网络接口列表, 捕捉数据包)到更高级的内容(处理发送队列, 网络流量统计). 教程中包括一些代码片断, 以及一些简单但完整的例子, 读者可以参考这些例子更好的理解教程的内容. 这些例子全部用C语言写成, 所以基本的C语言编程知识是必要. 同时, 因为这篇教程的内容是与底层网络紧密相连的, 所以笔者假设读者已经具备有关网络和协议的相关知识. 译者的话: WinPcap是一套免费的, 基于Windows的网络接口API, 它在底层网络操作方面对程序员很有帮助. 这篇文档翻译自 WinPcap Documentation 3.0 中的 WinPcap tutorial: a step by step guide to program WinPcap 一部分. 这篇教程对初学者的帮助很大, 尤其是简短清晰的例子, 但这篇教程只是整个文档的一小部分, 我认为你仍然需要参考文档的其它部分来了解各种结构等信息. 教程中注有前缀 Y- 的部分是译者为了让读者更明白作者的意思添加的, 原文中没有. 1. 获取网络接口列表 通常, 一个基于WinPcap的应用程序所要做的第一件事, 就是获得适合的网络接口的列表. Libpcap中的pcap_findalldevs()函数就是干这活的: 这个函数然回一个pcap_if结构的列表, 每个元素都记录了一个接口的信息. 其中, name和description以人类可以阅读的形式, 记录了设备的信息. 下面的源代码输出可用的网络接口的列表, 并且在没有找到任何借口的情况下输出错误信息: 代码 #include pcap.h main() pcap_if_t *alldevs; pcap_if_t *d; int i=0; char errbufPCAP_ERRBUF_SIZE; /* 取得列表 */ if (pcap_findalldevs(&alldevs, errbuf) = -1) fprintf(stderr,Error in pcap_findalldevs: %sn, errbuf); exit(1); /* 输出列表 */ for(d=alldevs;d;d=d-next) printf(%d. %s, +i, d-name); if (d-description) printf( (%s)n, d-description); else /* Y- 没有有效的描述 */ printf( (No description available)n); if(i=0) /* Y- 没有有效的接口, 可能是因为没有安装WinPcap */ printf(nNo interfaces found! Make sure WinPcap is installed.n); return; /* 我们不再需要列表了, 释放 */ pcap_freealldevs(alldevs); 我们来看看这段代码. 首先, 和其他的libpcap函数一样, pcap_findalldevs(), 有一个错误缓冲区(errbuf)参数. 这个参数是一个字符串指针, 一旦发生错误,libpcap将会在这里填入错误描述. 然后, 请注意, pcap_findalldev系统下的s()函数同时也被UNIX下的libpcap所支持, 但是并不是所有的操作系统都支持“网络接口描述”(description)这一项. 所以, 如果我们想写一个可以移植的的应用程序,那么我们必须要为描述为“空”(null)的情况做好准备:遇到这种情况我们就输出一个“没有有效的描述”的消息. 最后我们通过pcap_freealldevs()函数来释放接口列表. 现在让我们编译并运行我们的第一个WinPcap程序. 如果你使用UNIX或者Cgywin的话, 你只需要以下命令: gcc -o testaprog testprog.c -lpcap 在Windows环境中(Y - 如果你使用Microsoft Visual C+), 你需要建立一个工程, 按照Using WinPcap in your programs 一节中说明来做. 不过, 我仍然建议你参照Winpcap开发者包(WinPcap developers pack)中的例子, 那些例子包括了所以配置完善的工程, 以及全部你所需要的库和包含文件. (Y - 你可以在本章最后找到Microsoft Visual C+ 的配置方法) 假设现在你已经成功编译了程序, 我们就来运行它. 在我的WinXP工作站上, 输出结果是: 1. 4E273621-5161-46C8-895A-48D0E52A0B83 (Realtek RTL8029(AS) Ethernet Adapter) 2. 5D24AE04-C486-4A96-83FB-8B5EC6C7F430 (3Com EtherLink PCI) 就如你所看到的, 网络接口的名称(当打开这个接口时, 需要传递这个名称给libpcap库)在windows环境下几乎是没有办法读懂的(Y-严重同意), 所以输出一个描述对于你的用户来说是非常有帮助的. 附注: Microsoft Visual C+ 工程的设置 1. 下载并安装 WinPcap, 推荐的版本是3.0 2. 从 http:/winpcap.polito.it 下载 WinPcap Developers Pack 并解压缩 3. 用 Microsoft Visual C+ 建立一个空工程 (empty project) 4. 复制源代码 5. 把 Winpcap Developers Pack 中的 Includes 目录添加为新的包含文件目录 6. 添加库 wpcap.lib 和 wsock32.lib 一路达计数器提示:统计网站 设置不对统计网站:应为 现在修改 【网络编程】翻译 WinPcap编程渐进教程(2)- - 原文出处:http:/winpcap.polito.it/docs/man/html/index.html 作者: Loris Degioanni (degioannipolito.it), NetGroup, Politecnico di Torino http:/winpcap.polito.it 译者: 记忆碎片 (val_) 2. 获取设备的高级信息 上一课我们介绍了如何获取一个设备的基本信息(比如设备名称和设备描述). 实际上, WinPcap 也可以为我们提供关于接口的更多信息. 由 pcap_findalldevs() 函数返回的 pcap_if 结构也包含了一个 pcap_addr 结构的列表, 它记录了以下信息: 1. 接口的地址列表 2. 接口的掩码列表 (与地址列表一一对应) 3. 接口的广播地址列表 (与地址列表一一对应) 4. 目标地址列表 (与地址列表一一对应) 下面例子中的 ifprint() 函数将会输出 pcap_if 结构的全部内容. 它包括了 pcap_findalldevs() 函数所返回的所有元素. ( Y- 全部有效接口) 代码 /* * Copyright (c) 1999 - 2002 * Politecnico di Torino. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * This product includes software developed by the Politecnico * di Torino, and its contributors. Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include pcap.h #ifndef WIN32 #include #include #else #include #endif void ifprint(pcap_if_t *d); char *iptos(u_long in); int main() pcap_if_t *alldevs; pcap_if_t *d; char errbufPCAP_ERRBUF_SIZE+1; /* 获得设备列表 */ if (pcap_findalldevs(&alldevs, errbuf) = -1) fprintf(stderr,Error in pcap_findalldevs: %sn,errbuf); exit(1); /* 遍历所有元素 */ for(d=alldevs;d;d=d-next) ifprint(d); return 1; /* Print all the available information on the given interface */ void ifprint(pcap_if_t *d) pcap_addr_t *a; /* 名称 */ printf(%sn,d-name); /* 描述 */ if (d-description) printf(tDescription: %sn,d-description); /* 回环地址 */ printf(tLoopback: %sn,(d-flags & PCAP_IF_LOOPBACK)?yes:no); /* IP 地址 */ for(a=d-addresses;a;a=a-next) printf(tAddress Family: #%dn,a-addr-sa_family); switch(a-addr-sa_family) case AF_INET: printf(tAddress Family Name: AF_INETn); if (a-addr) /* Y- IP 地址 */ printf(tAddress: %sn,iptos(struct sockaddr_in *)a-addr)-sin_addr.s_addr); if (a-netmask) /* Y- 掩码 */ printf(tNetmask: %sn,iptos(struct sockaddr_in *)a-netmask)-sin_addr.s_addr); if (a-broadaddr) /* Y- 广播地址 */ printf(tBroadcast Address: %sn,iptos(struct sockaddr_in *)a-broadaddr)-sin_addr.s_addr); if (a-dstaddr) /* Y - 目标地址 */ printf(tDestination Address: %sn,iptos(struct sockaddr_in *)a-dstaddr)-sin_addr.s_addr); break; default: /* 未知 */ printf(tAddress Family Name: Unknownn); break; printf(n); /* 来自 tcptracert, 把数字IP地址转换为点格式 */ #define IPTOSBUFFERS 12 char *iptos(u_long in) static char outputIPTOSBUFFERS3*4+3+1; static short which; u_char *p; p = (u_char *)∈ which = (which + 1 = IPTOSBUFFERS ? 0 : which + 1); sprintf(outputwhich, %d.%d.%d.%d, p0, p1, p2, p3); return outputwhich; 一路达计数器提示:统计网站 设置不对统计网站:应为 现在修改 【网络编程】翻译 WinPcap编程渐进教程(3)- - 原文出处: http:/winpcap.polito.it/docs/man/html/index.html 作者: Loris Degioanni (degioannipolito.it), NetGroup, Politecnico di Torino http:/winpcap.polito.it 译者: 记忆碎片 (val_) 3. 打开一个接口并捕捉流量 现在我们已经知道如何获取一个接口的有关信息了, 我们可以来点真家伙了 - 打开一个接口并捕捉流量. 在这一课里, 我们会编译一个程序, 它将捕捉网络中所有的数据包并输出他们的一些相关信息。我们使用函数 pcap_open_live() 来打开一个捕捉设备. 这里, 我们需要解释一下 snaplen, promisc 和 to_ms 参数. ( Y- 函数原型: pcap_t * pcap_open_live (char *device, int snaplen, int promisc, int to_ms, char *ebuf) ) snaplen 参数指定了要捕捉的数据包的部分. 在某些操作系统中 (如 xBSD 和 Win32), 驱动程序提供了只捕捉每个数据包其中一部分的可能性: 这样就降低了要处理的数据的量, 从而提高了捕捉程序的效率. 在例子中, 我们使用一个高出 MTU 最大值的值 (65536) 以确保可以捕捉到成个数据包. promisc 表明接口将会被设置为混杂模式. 一般情况下, 接口只处理目标地址为自己的数据; 到其他主机的数据包将会被忽略. 然而当一个接口处于混杂模式时, 它将会处理全部的流量: 也就是说, 在共享媒介 ( Y- 才疏学浅, 不知道怎么翻译好 ), 例如非交换型以太网 ( Y- 比如基于集线器的网络 )中, WinPcap 可以捕捉到所有主机的数据包. 混在模式是多数捕捉程序的默认模式, 所以我们在例子中也采用这种模式. to_ms 用以设置超时, 单位是毫秒. 一个从接口读取 ( Y- 捕捉) 的操作, (例如 pcap_dispatch() 或者 pcap_next_ex(), 如果没有捕捉到数据包, 那么在超过指定的时间以后就会返回. 进一步说, 如果接口处在静态模式中, to_ms 也定义了静态报告的间隔时间 (参阅 Gathering Statistics on the network traffic 以获取更多信息). 设置 to_ms 为 0, 则说明永远不会超时, 如果没有数据包到达, 那么捕捉操作将会永远不会返回, 而将其值设置为 -1 则会立刻返回. 代码 #include pcap.h /* 数据包处理函数声明 */ void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data); main() pcap_if_t *alldevs; pcap_if_t *d; int inum; int i=0; pcap_t *adhandle; char errbufPCAP_ERRBUF_SIZE; /* 获取设备列表 */ if (pcap_findalldevs(&alldevs, errbuf) = -1) fprintf(stderr,Error in pcap_findalldevs: %sn, errbuf); exit(1); /* 数据列表 */ for(d=alldevs; d; d=d-next) printf(%d. %s, +i, d-name); if (d-description) printf( (%s)n, d-description); else printf( (No description available)n); if(i=0) printf(nNo interfaces found! Make sure WinPcap is installed.n); return -1; printf(Enter the interface number (1-%d):,i); scanf(%d, &inum); if(inum i) printf(nInterface number out of range.n); /* 释放设备列表 */ pcap_freealldevs(alldevs); return -1; /* 转到选择的设备 */ for(d=alldevs, i=0; inext, i+); /* 打开设备 */ if ( (adhandle= pcap_open_live(d-name, /设备名 65536, / 捕捉完整的数据包 1, / 混在模式 1000, / 读入超时 errbuf / 错误缓冲 ) ) = NULL) /* Y- 打开失败*/ fprintf(stderr,nUnable to open the adapter. %s is not supported by WinPcapn); /* 释放列表 */ pcap_freealldevs(alldevs); return -1; printf(nlistening on %s.n, d-description); /* 我们已经不需要设备列表了, 释放它 */ pcap_freealldevs(alldevs); /* 开始捕捉 */ pcap_loop(adhandle, 0, packet_handler, NULL); return 0; /* 处理数据包的回调函数*/ void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) struct tm *ltime; char timestr16; /* 转换时间戳为可以阅读的格式 */ ltime=localtime(&header-ts.tv_sec); strftime( timestr, sizeof timestr, %H:%M:%S, ltime); printf(%s,%.6d len:%dn, timestr, header-ts.tv_usec, header-len); 一旦接口被打开, pcap_dispatch() 或者 pcap_loop() 函数将会开始捕捉. 这两个函数非常相似, pcap_dispatch() 将会在超时后直接返回, 而 pcap_loop() 则一定要等到一定数量的数据包被处理了以后才会返回 (Y- 第二个参数指定了要处理的数据包的数量, 0 为无限, 在这里, 我们设置的超时对 pcap_loop() 不起作用.) 在本例中, pcap_loop() 已经足够我们使用了, 而 pcap_dispatch() 一般应用在更复杂的程序里. 这两个函数都有一个回调参数, 只想一个处理数据包的函数, 如本例中的 packet_handler. 每当有新的数据包到来的时候, libpcap将会调用这个函数来处理数据包, libpcap也会提供这个数据包的一些信息: 一个首部, 包含了时间戳和长度信息 (Y-header 参数); 真实数据包 (Y- pkt_data参数), 包括各种协议首部. 请注意, MAC CRC一般不会出现, 因为当设备(网卡)进行帧确认操作时, 它就已经被移除了. 同时, 大部分网卡将会丢弃错误的 CRC, 所以 WinPcap 基本上也不能捕捉他们. 上面的例子只输出每个数据包时间戳以及长度 (来自 pcap_pkthdr header). 关于TCP/IP数据包的截取和分析TCP/IP数据包的截取是一个简单的工作,在Windows 2000/xp下,下面方法可以完成TCP/IP数据包的截获:1、通过建立rawsocket来完成对TCP/IP数据包的截获。从Windows 2000开始,Winsock 2开始支持原始socket,可以 截获所有经过本机的TCP/IP数据包,支持拨号网络,但对本机向外发送的TCP/IP数据包截获有缺陷。可以从/Cpp/I-N/network/tcpip/article.php/c5413得到更加详细的信息及演示代码,现在很多基于rawsocket的代码都是参照这篇文章完成的。2、通过WinPcap Developers pack来完成对TCP/IP数据包的截获。这个开发包可以很好的在windows 9x/nt/2000/xp下工作,不支持拨号网络。可以从http:/winpcap.polito.it/获得更详细的信息和用户手册,在本版的精华版也包括一个介绍这个开发包的文章可以参照。Windows下对TCP/IP数据包的截获大多通过这两个方法来完成。如果你需要编写一个轻量级的TCP/IP数据包的截取和分析工具,而且只在Windows 2000/xp下工作,你可以选择第一种方法,比较简单,而且不需要另外的驱动;否则,你需要选择第二种方法或其他方法。在类UNIX系统(比如linux)下,通常使用libpcap(/)完成TCP/IP数据包的截取工作,它可以工作在多种操作系统下。可以从互联网上面搜索到很多Windows下的TCP/IP数据包截取的演示代码,还可以搜索到很多linux下的开源项目,甚至功能完备复杂的大型TCP/IP数据包截取项目。TCP/IP数据包的分析就比较困难和麻烦了。首先这种分析是基于对TCP/IP协议族的理解之上的,如果你还不了解,TCP-IP详解卷1:协议是首先需要翻阅的书籍,如果懒的看,那也不要提什么分析了,呵呵。截取了一个TCP/IP数据包后,首先分离出IP协议(IP“Internet Protocol”协议是TCP/IP协议族中最为核心的协议,所有的TCP、UDP、ICMP和IGMP数据等都是以IP数据报格式传输的)的头部分,从IP协议头中可以得到很多关键的数据,如IP头的长度、源IP、目的IP、TCP/IP协议类型等,下面演示代码实现这个功能:typedef struct _IP_HEADER/定义IP首部unsigned charh_lenver; /4位首部长度+4位IP版本号unsigned chartos;/8位服务类型TOSunsigned short total_len;/16位总长度(字节)unsigned short ident;/16位标识unsigned short frag_and_flags; /3位标志位+13位片偏移unsigned charttl;/8位生存时间 TTLunsigned charproto;/8位协议 (TCP, UDP 或其他)unsigned short checksum; /16位IP首部校验和unsigned int sourceIP; /32位源IP地址unsigned int destIP; /32位目的IP地址 IP_HEADER;typedef struct _TCP_HEADER/定义TCP首部USHORT th_sport;/16位源端口USHORT th_dport;/16位目的端口UINT th_seq;/32位序列号UINT th_ack;/32位确认号UCHARth_lenres; /4位首部长度/6位保留字UCHARth_flag; /6位标志位USHORT th_win;/16位窗口大小USHORT th_sum;/16位校验和USHORT th_urp;/16

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论