winpcap编程抓包实例和windump使用

http://www.winpcap.org/archive/

官方文档

http://www.ferrisxu.com/WinPcap/html/index.html

http://www.winpcap.org/

http://www.winpcap.org/windump/install/default.htm

http://www.360doc.com/content/11/0319/10/54470_102500630.shtml

WinDump的使用:

WinDump.exe version 3.9.5, based on tcpdump version 3.9.5

WinPcap version 4.1.3 (packet.dll version 4.1.0.2980), based on libpcap version 1.0 branch 1_0_rel0b (20091008)

Usage: WinDump.exe [-aAdDeflLnNOpqRStuUvxX] [ -B size ] [-c count] [ -C file_size ]

[ -E algo:secret ] [ -F file ] [ -i interface ] [ -M secret ]

[ -r file ] [ -s snaplen ] [ -T type ] [ -w file ]

[ -W filecount ] [ -y datalinktype ] [ -Z user ]

[ expression ]

windump -D

列出所有的网卡。

windump -h 列出帮助。

WinDump.exe -h  >mylog.txt 2>&1

WinDump.exe -i 4

windump -i 2 port 80

通过端口80从界面#2记录所有流量

windump -i 2 host im-chat.com

记录所有从the host im-chat.com.或来或到界面#2的流量

windump -i 1 net 127

这些参数也可以自由组合。

WinDump手册

命令格式

windump [ -aBdDeflnNOpqRStvxX ] [ -c count ] [ -F file ] [ -i interface ] [ -m module ] [ -r file ] [ -s snaplen ] [ -T type ] [ -w file ] [ -E algo:secret ] [ expression ]

描述 Tcpdump 输出网卡数据包中匹配布尔表达式的数据包头。

SunOS 系统下使用nit或bpf:要运行tcpdump,你必须有对dev/nit或/dev/bpf*的权利。Solaris系统下使用dlpi:你必须有对 网络假设置的权利。HP-UX系统下使用dlpi:你应该以超级用户ROOT或安装SETUID到ROOT下。IRIX下使用SNOOP:你应该以超级用 户ROOT或安装SETUID到ROOT下。

LINUX下:你应该以超级用户ROOT或安装SETUID到ROOT下。

在系统Ultrix和Digital UNIX:

命令参数

-a 将网络和广播地址转化为名称

-c 接收指定数据包后退出

-d 接收人可读的包匹配编译代码到标准输出,然后停止

-dd 以C程序分段方式捕获包匹配代码

-ddd 以十进制数据形式捕获包匹配代码

-e 在每个捕获行打印链路层头标

-E algo:secret为解密IPSE ESP包使用算法。

算法可以是des-cbc, 3des-cbc, blowfish-cbc, rc3-cbc, cast128-cbc, 或none。

默认值是desc-cbc。只有当TCPDUMP编译时使用激活加密选项时,才可以解密数据包。

Secret是ESP密匙是ASCII码。当前还不能认为一定是二进制值。该选项是以RFC2406ESP为假设,而不是RFC1827 ESP。只用于调试,不鼓励用真正的密码作为选项。当你在PS或其他场合,把IPSEC密码写在命令行上时,会被他人看到。

-f 不用符号而用数字方式输出外部英特网地址 -F 使用文件作为过滤表达式的输入。命令行的其他部分会被忽略。

-i 在接口上监听。如果没有指定,TCPDUMP将搜索系统接口列表中最小,被配置激活的接口(LOOPBACK接口除外)。可用最先匹配替换这种关系。在 WINDOWS中接口可以是网卡的名称,或是网卡的号码(-D参数可显示该号码)。内核为2。2或其后的LINUX系统,参数“ANY”可以获取所有接口 的数据。应注意的是在混乱模式下不能使用“ANY”参数。

-l 标准输出行缓存。如果你想在捕获数据时查看的话,这个参数很有用。

例如:“tcpdump -l │ tee dat” or “tcpdump -l > dat & tail -f dat”.” n 不要将地址(如主机地址,端口号)转换为名称 -N 不要打印主机名称的域名限定。如:如果你使用该参数,TCPDUMP会输出“NIC”而不是“NIC。DDN。MIL”。

-m 从文件模块中载入SMI MIB 模块定义。这个选项可以为TCPDUMP载入多个MIB模块

-O 不要运行包匹配代码优化器。只有在你怀疑优化器有问题时可以使用这个参数。

-p 不要让接口处于“混乱”模式。注意接口可能由于其他原因处于“混乱”模式;因此“-p”不能用作以太网络主机或广播的缩写。

-q 快速(安静?)输出。打印较少的协议信息,因此输出行更短。

-r 从文件中读取包(与参数据-W一起使用)。如果文件是“-”就使用标准输入。

-s 不使用默认的68个字节,更改从每个包中获取数据的字节数量( SunOS系统实际最小为96)。对于IP,ICMP,TCP和UDP包68个字节已足够,但是对命名服务和NFS包,他们的协议会被截断(见下面)。包 被截断是因为在使用参数“[│proto]”输出时指定受限制的快照,proto是被截断协议层的名称。注意如果使用大的快照会增加处理包的时间,并且明 显地减少包的缓存数量。也许会导致包的丢失。你应该将snaplen 设置成你感兴趣协议的最小数。当snaplen 为0时接收整个包。

-T 根据表达式将选中的数据包表达成指定的类型。当前已有的类型有CNFP(Cisco的网络流量协议),rpc(远端程序调用),rtp(实时程序协议), rtcp(实时程序控制协议),snmp(简单网络管理协议),vat(可视单频工具),和wb(分布式白板)。 -R 假设ESP/AH包遵守旧的说明(RFC1825到RFC1829)。如果该参数被指定,TCPDUMP不打输出域。因为在ESP/AH说明中没有协议版 本,TCPDUMP就无法推断出其版本号。 -S 输出绝对TCP序列号,而不是相对号。

-t 每个捕获行不要显示时间戳。 -tt 每个捕获行显示非格式化的时间时间戳。

-v 详细输出。例如,显示生存时间TTL,标识符,总长度和IP数据包的选项。也进行额外的包完整性较验,如验证IP和ICMP的头标较验值。

-vv 更为详细的输出。例如,显示NFS中继包中的其他域。

-vvv 很详细的输出。如,完全输出TELNET SB… SE选项。带-X参数的TELNET,打印并以十六进制输出。

-w 不对原始数据包解析打印而是转到文件中去。以后可用-r选项打印。当文件名为“-”表示标准输出。 -x 以十六进制(去除链路层头标)输出每个数据包。输出整个包的小部分或snaplen 个字节。

-X 输出十六进制同时,输出ASCII码。如果-x也被设置,数据包会以十六制/ASCII码显示。这对于分析新协议非常方便。如果-x也没有设置,一些数据包的部分会以十六制/ASCII码显示。 Win32特殊扩展

-B 以千字节为单位设置驱动缓存。默认缓存为1M(即1000)。如果在获取数据包时有数据丢失,建议使用该参数增大核心缓存大小,因为驱动缓存大小对数据捕获性能有很大影响。

-D 显示系统上可用的网卡列表。该参数将返回每块网卡的号码,名称和描述。

下载:http://www.winpcap.org/archive/4.1beta5_WpdPack.zip

这个包里面有很多例子,下面我们就可以编程实现了:

#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>
#define HAVE_REMOTE
#include <pcap.h>
#include <iomanip>
#include <string>
#include <stdio.h>
using namespace std;

#include <pcap.h>
#pragma comment(lib,"wpcap.lib")
#pragma comment(lib,"ws2_32.lib")  

//https://github.com/yfnick/winpcap/blob/master/ref_http/main.cpp
//demo  https://github.com/yfnick/winpcap

/*Ethernet Heder*/
struct ether_header
{
	u_int8_t  ether_dhost[6];      /* destination eth addr */
	u_int8_t  ether_shost[6];      /* source ether addr    */
	u_int16_t ether_type;          /* packet type ID field */
};

/* 4 bytes IP address */
struct ip_address{
	u_char byte1;
	u_char byte2;
	u_char byte3;
	u_char byte4;
};

/* IPv4 header */
struct ip_header{
	u_char  ver_ihl;        // Version (4 bits) + Internet header length (4 bits)
	u_char  tos;            // Type of service
	u_short tlen;           // Total length
	u_short identification; // Identification
	u_short flags_fo;       // Flags (3 bits) + Fragment offset (13 bits)
	u_char  ttl;            // Time to live
	u_char  proto;          // Protocol
	u_short crc;            // Header checksum
	ip_address  saddr;      // Source address
	ip_address  daddr;      // Destination address
	u_int   op_pad;         // Option + Padding
};

/* UDP header*/
struct udp_header{
	u_short sport;          // Source port
	u_short dport;          // Destination port
	u_short len;            // Datagram length
	u_short crc;            // Checksum
};

/*TCP Header*/
struct tcp_header
{
	u_int16_t th_sport;         /* source port */
	u_int16_t th_dport;         /* destination port */
	u_int32_t th_seq;             /* sequence number */
	u_int32_t th_ack;             /* acknowledgement number */
	u_int16_t th_len_resv_code; //   Datagram   length and reserved code
	u_int16_t th_win;           /* window */
	u_int16_t th_sum;           /* checksum */
	u_int16_t th_urp;           /* urgent pointer */
};

int main()
{
	//retrieve the devices list
	pcap_if_t *all_devs;
	char err_buff[PCAP_ERRBUF_SIZE];
	if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &all_devs, err_buff) == -1){
		cerr << "Error in pcap_findalldevs_ex " << err_buff << endl;
		return -1;
	}

	//get the device index,default is the first one
	int dev_idx = 2;
	pcap_if_t *dev = all_devs;
	for (int i = 0; i < dev_idx; ++i, dev = dev->next);//jump to the device of the specified index
	cout << "Listen on: " << dev->name << endl;
	cout << "****************************************" << endl;

	//get the netcard adapter
	pcap_t *adpt_hdl = pcap_open(dev->name, 65536, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, err_buff);
	if (adpt_hdl == NULL){
		cerr << "Unable to open adapter " << dev->name << endl;
		pcap_freealldevs(all_devs);
		return -1;
	}

	/* At this point, we don't need any more the device list. Free it */
	pcap_freealldevs(all_devs);

	//analyze each packet
	struct pcap_pkthdr *header;
	const u_char *pkt_data;

	int rst = 0;
	char x;
	FILE *fp, *fq;
	fp = fopen("http.txt", "w+");
	fq = fopen("ac.txt", "w+");
	while ((rst = pcap_next_ex(adpt_hdl, &header, &pkt_data)) >= 0)
	{
		if (rst == 0){
			//time out and not packet captured
			continue;
		}

		ether_header *eh = (ether_header*)pkt_data;

		if (ntohs(eh->ether_type) == 0x0800){ // ip packet only

			ip_header *ih = (ip_header*)(pkt_data + 14);

			if (ntohs(ih->proto) == 0x0600){ // tcp packet only

				int ip_len = ntohs(ih->tlen);//ip_len = ip_body + ip_header

				bool find_http = false;

				string http_txt = "";
				//char* http;
				char* ip_pkt_data = (char*)ih;

				for (int i = 0; i < ip_len; ++i){

					//check the http request

					if (!find_http && ( 3 < ip_len && strncmp(ip_pkt_data + i, "GET", strlen("GET")) == 0)

						|| (i + 4 < ip_len && strncmp(ip_pkt_data + i, "POST", strlen("POST")) == 0)){

						find_http = true;

					}

					//check the http response

					if (!find_http && i + 8 < ip_len && strncmp(ip_pkt_data + i, "HTTP/1.1", strlen("HTTP/1.1")) == 0){

						find_http = true;
					}

					//collect the http text

					if (find_http){

						http_txt += ip_pkt_data[i];
						fputc(ip_pkt_data[i], fp);
						if ((ip_pkt_data[i] > 'A'&&ip_pkt_data[i]<'Z') || (ip_pkt_data[i]>'a'&&ip_pkt_data[i]<'z'))
						{
							if ((ip_pkt_data[i]>'A'&&ip_pkt_data[i] < 'Z'))
								x = ip_pkt_data[i] - 'A' + 'a';
							else x = ip_pkt_data[i];
							fputc(x, fq);
						}
					}
				}
				//print the http request or response
				if (http_txt != ""){
					cout << http_txt;
					cout << endl << "***********************************************************" << endl << endl;
				}
			}
		}
	}
	return 0;
}
#define HAVE_REMOTE
#define _CRT_SECURE_NO_WARNINGS 1

#include <pcap.h>

#pragma comment(lib,"wpcap.lib")   

/* 回调函数原型 */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);

int main(int argc, char **argv)
{
	pcap_if_t *alldevs;
	pcap_if_t *d;
	int inum;
	int i = 0;
	pcap_t *adhandle;
	char errbuf[PCAP_ERRBUF_SIZE];
	pcap_dumper_t *dumpfile;

	/* 检查程序输入参数 */
	if (argc != 2)
	{
		printf("usage: %s filename", argv[0]);
		return -1;
	}

	/* 获取本机设备列表 */
	if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
	{
		fprintf(stderr, "Error in pcap_findalldevs: %s\n", 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 < 1 || inum > i)
	{
		printf("\nInterface number out of range.\n");
		/* 释放列表 */
		pcap_freealldevs(alldevs);
		return -1;
	}

	/* 跳转到选中的适配器 */
	for (d = alldevs, i = 0; i < inum - 1; d = d->next, i++);

	/* 打开适配器 */
	if ((adhandle = pcap_open(d->name,          // 设备名
		65536,            // 要捕捉的数据包的部分
		// 65535保证能捕获到不同数据链路层上的每个数据包的全部内容
		PCAP_OPENFLAG_PROMISCUOUS,    // 混杂模式
		1000,             // 读取超时时间
		NULL,             // 远程机器验证
		errbuf            // 错误缓冲池
		)) == NULL)
	{
		fprintf(stderr, "\nUnable to open the adapter. %s is not supported by WinPcap\n", d->name);
		/* 释放设备列表 */
		pcap_freealldevs(alldevs);
		return -1;
	}

	/* 打开堆文件 */
	dumpfile = pcap_dump_open(adhandle, argv[1]);

	if (dumpfile == NULL)
	{
		fprintf(stderr, "\nError opening output file\n");
		return -1;
	}

	printf("\nlistening on %s... Press Ctrl+C to stop...\n", d->description);

	/* 释放设备列表 */
	pcap_freealldevs(alldevs);

	/* 开始捕获 */
	pcap_loop(adhandle, 0, packet_handler, (unsigned char *)dumpfile);

	return 0;
}

/* 回调函数,用来处理数据包 */
void packet_handler(u_char *dumpfile, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
	/* 保存数据包到堆文件 */
	pcap_dump(dumpfile, header, pkt_data);
}

时间: 2024-10-17 13:15:27

winpcap编程抓包实例和windump使用的相关文章

抓包实例

超过70秒的请求是通过分析IIS日志发现的: 10.159.63.104是SLB的内网IP. 通过Wireshark抓包分析请求是9:22:21收到的(tcp.stream eq 23080): 09:22:21.299838000 10.159.63.104 10.161.241.208 HTTP 291 GET /eastsea/p/3764040.html HTTP/1.0 这个请求响应内容的长度是:Content-Length 1154110(1.1MB) 云服务器(ECS)在收到请求后

使用winpcap多线程抓包,以及简单的分析数据包

刚开始使用winpcap数据包的时候,我在抓包的时候使用了 pcap_loop(adhandle, 0, packet_handler, NULL); 这个回调函数进行抓包.同时在回调函数中分析IP地址后加入了新的线程进行分析数据包. pthread_create(&thread[threadnum], NULL,thread, &thread_ins); 我的新线程函数大致是这样的: void* thread(void *) { /*省略...*/ while((res = pcap_n

WinPcap网络抓包分析程序--总结

应付大作业写的一个程序,先给出程序的运行界面 程序的核心内容是抓包然后分析数据,我做的最多的也是协议分析这块内容.上面首先给出的是当前网络的上传下载速度,这块内容我是参考Windows性能计数器来写的,就是PDH,直接获取相应的接口, 获取数据,这块内容直接放出代码 1 #include <Pdh.h> 2 #include <list> 3 #pragma comment(lib, "Pdh.lib") 4 5 class NetWorkSpeed 6 { 7

Wireshark抓包实例分析TCP重复ACK与乱序

转载请在文首保留原文出处: EMC 中文支持论坛https://community.emc.com/go/chinese 介绍 TCP 的一大常见问题在于重复 ACK 与快速重传.这一现象的发生也是由于性能问题,本章讨论如何发现这一问题以及他们意味着什么. 另一个常见问题是前一片段丢失以及乱序片段.某些情况下,这一现象喻示着故障发生,可能是由于网络问题或是抓包中断. 更多信息 重复 ACK 与快速重传 : 当网速变慢时,重复 ACK 是可能的原因之一.大多数情况下,重复 ACK 的发生是由于高延

转://tcpdump抓包实例

基本语法 ========过滤主机--------- 抓取所有经过 eth1,目的或源地址是 192.168.1.1 的网络数据# tcpdump -i eth1 host 192.168.1.1- 源地址# tcpdump -i eth1 src host 192.168.1.1- 目的地址# tcpdump -i eth1 dst host 192.168.1.1过滤端口--------- 抓取所有经过 eth1,目的或源端口是 25 的网络数据# tcpdump -i eth1 port

tcpdump非常实用的抓包实例

原文地址:http://blog.csdn.net/nanyun2010/article/details/23445223 详细的文档见tcpdump高级过滤技巧 基本语法 ========过滤主机--------- 抓取所有经过 eth1,目的或源地址是 192.168.1.1 的网络数据# tcpdump -i eth1 host 192.168.1.1- 源地址# tcpdump -i eth1 src host 192.168.1.1- 目的地址# tcpdump -i eth1 dst

抓包利器Fiddler

1).Fiddler安装 a.下载地址: http://fiddler2.com/get-fiddler b.安装:省略(下一步...下一步即可) 2).Fiddler配置 a.允许远程计算机连接Fiddler 菜单:Tools-> Fiddler Options->Connections,勾选"Allow remote computers to connect" 注:8888为默认端口号,可修改,但需注意两点,一是本机空闲端口,二是手机代理设置时端口要一致. b.配置可捕

从Fiddler抓包到Jmeter接口测试(简单的思路)

版权声明:本文为博主原创文章,未经博主允许不得转载. Fiddler下载和配置安装 从网上下载fiddler的安装包即可,直接默认,一直点击下一步,直至安装完成. 安装完成后直接打开Fiddler 在菜单栏Tools->Fiddler Options->Connections,勾选Allow remote computers to connect,默认的端口号为8888,这里不需要修改,在修改手机代理设置时注意与这里一致. 查看pc本机ip后,手机设置代理,填入pc本机的ip和端口号8888,

Wireshark和TcpDump抓包分析对比

常见的抓包分析工具有:微软的Network Monitor和Message Analyzer.Sniff.WSExplorer.SpyNet.iptools.WinNetCap.WinSock Expert.Wireshark和linux的tcpdump等工具 今天,做了实验测试就对比分析其中的两款,其他的大家可以百度谷歌测试一哈^_^ 1. Wireshark与tcpdump介绍 Wireshark是一个网络协议检测工具,支持Windows平台和Unix平台,我一般只在Windows平台下使用