十二、windows网络知识梳理(12)--进阶知识流量监控-Winpcap

这一节,我们看一下winpcap的相关知识。

一、在官方文档中介绍的比较清楚。

十二、windows网络知识梳理(12)--进阶知识流量监控-Winpcap_第1张图片

 winpcap 是不能嗅探本地回环包的,不像npcap可以直接检索单本地的LoopBack(127.0.0.1)

如果非要的话,也是有两种方法的。 

1、把本地包的下一跳直接设置成网关的,本地宝就会通过网卡到网关,这样就能捕捉到了。详细教程可以参考这里。

该方式把所有本地包都从网关过了一下,导致效率低了。

2、导出wpcap.dll的导出函数。重新设计。

二、详细的winpcap抓包代码设计

1、环境集成

        首先在官网下载winpcap安装包(WinPcap - Home),然后下载依赖文件()。

        或者直接下载我弄好的咯((1条消息) WinPcap-4-1-3.exe安装包WpdPack-4-1-2.zip开发依赖包资源-CSDN文库

  十二、windows网络知识梳理(12)--进阶知识流量监控-Winpcap_第2张图片

        把这些文件拷贝到你的开发工程里。基本就是库的集成方式。注意在预编译头里添加这几项: _CRT_SECURE_NO_WARNINGS
_WINSOCK_DEPRECATED_NO_WARNINGS
WPCAP
HAVE_REMOTE

2、获取网卡信息


int main()
{
	pcap_if_t *alldevs;
	pcap_if_t *d;
	char errbuf[PCAP_ERRBUF_SIZE+1];
	
	/* Retrieve the device list */
	if(pcap_findalldevs(&alldevs, errbuf) == -1)
	{
		fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
		exit(1);
	}
	
	/* Scan the list printing every entry */
	for(d=alldevs;d;d=d->next)
	{
		ifprint(d);
	}

	/* Free the device list */
	pcap_freealldevs(alldevs);

	return 1;
}

void ifprint(pcap_if_t *d)
{
  pcap_addr_t *a;
  char ip6str[128];

  /* Name */
  printf("%s\n",d->name);

  /* Description */
  if (d->description)
    printf("\tDescription: %s\n",d->description);

  /* Loopback Address*/
  printf("\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no");

  /* IP addresses */
  for(a=d->addresses;a;a=a->next) {
    printf("\tAddress Family: #%d\n",a->addr->sa_family);
  
    switch(a->addr->sa_family)
    {
      case AF_INET:
        printf("\tAddress Family Name: AF_INET\n");
        if (a->addr)
          printf("\tAddress: %s\n",iptos(((struct sockaddr_in *)a->addr)->sin_addr.s_addr));
        if (a->netmask)
          printf("\tNetmask: %s\n",iptos(((struct sockaddr_in *)a->netmask)->sin_addr.s_addr));
        if (a->broadaddr)
          printf("\tBroadcast Address: %s\n",iptos(((struct sockaddr_in *)a->broadaddr)->sin_addr.s_addr));
        if (a->dstaddr)
          printf("\tDestination Address: %s\n",iptos(((struct sockaddr_in *)a->dstaddr)->sin_addr.s_addr));
        break;

	  case AF_INET6:
       printf("\tAddress Family Name: AF_INET6\n");
#ifndef __MINGW32__ /* Cygnus doesn't have IPv6 */
        if (a->addr)
          printf("\tAddress: %s\n", ip6tos(a->addr, ip6str, sizeof(ip6str)));
#endif
		break;

	  default:
        printf("\tAddress Family Name: Unknown\n");
        break;
    }
  }
  printf("\n");
}

十二、windows网络知识梳理(12)--进阶知识流量监控-Winpcap_第3张图片

3、捕捉包


int main()
{
	pcap_if_t* alldevs;	//适配器列表,它是一个链表的数据结构
	pcap_if_t* d;		//保存某个适配器
	pcap_t* fp;
	int res;
	struct pcap_pkthdr* header;
	const u_char* pkt_data;
	time_t local_tv_sec;
	struct tm* ltime;
	char timestr[16];

	int count = 1;
	int i = 0, inum;
	char errbuf[PCAP_ERRBUF_SIZE];

	u_int netmask;
	struct bpf_program bpf_filter;  //BPF过滤规则   
	char bpf_filter_string[] = "icmp"; //过滤规则字符串,只分析IPv4的数据包   ip ; port 443;icmp

	printf("===============Adapter List===============\n");

	//获取本地设备列表
	if (pcap_findalldevs(&alldevs, errbuf) == -1)
	{
		fprintf(stderr, "Error in pcap_findalldevs: %s\n", errbuf);
		exit(1);
	}

	//输出列表
	for (d = alldevs; d != NULL; d = d->next)
	{
		printf("%d. %s", ++i, d->name);
		if (d->description)
			printf(" (%s)\n", d->description);
		else
			printf(" (No description available)\n");

		printf("\tLoopback: %s\n", (d->flags & PCAP_IF_LOOPBACK) ? "yes" : "no");
	}

	if (i == 0)
	{
		printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
		return -1;
	}

	//获取选择编号
	while (1)
	{
		printf("\nEnter the interface number (1-%d): ", i);
		scanf("%d", &inum);

		if (inum > 0 && inum <= i)
			break;
	}

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

	//打开适配器
	if ((fp = pcap_open_live(d->name, 65536, PCAP_OPENFLAG_PROMISCUOUS, 1000, errbuf)) == NULL)
	{
		fprintf(stderr, "\nError openning adapter: %s\n", errbuf);
		pcap_freealldevs(alldevs);
		return -1;
	}

	//检查链路层的类型 只看以太网
	if (pcap_datalink(fp) != DLT_EN10MB)
	{
		fprintf(stderr, "This program only run on Ethernet networks\n");
		pcap_close(fp);
		pcap_freealldevs(alldevs);
		return -1;
	}

	// 设置过滤规则
	if (d->addresses != nullptr) {
		netmask = ((struct sockaddr_in*)(d->addresses->netmask))->sin_addr.S_un.S_addr;
	}
	else {
		/* If the interface is without addresses we suppose to be in a C class network */
		netmask = 0xffffff;
	}
	pcap_compile(fp, &bpf_filter, bpf_filter_string, 0, netmask); //编译过滤规则   
	pcap_setfilter(fp, &bpf_filter);//设置过滤规则   

	printf("The program is working......\n");
	printf("The capture file is saving as 'data.txt'\n");
	printf("You can input 'ctrl + C' to stop the program\n");

	//if ((file = freopen("data.txt", "w", stdout)) == 0)
	//	printf("Cannot open the file.\n");
	
	while ((res = pcap_next_ex(fp, &header, &pkt_data)) >= 0)
	{
		//超时
		if (res == 0)
			continue;

		//将时间戳转化为可识别格式
		local_tv_sec = header->ts.tv_sec;
		ltime = localtime(&local_tv_sec);
		strftime(timestr, sizeof(timestr), "%H:%M:%S", ltime);

		//输出编号、时间戳和包长度
		printf("==============================================================================\n");
		printf("No.%d\ttime: %s\tlen: %ld\n", count++, timestr, header->len);
		printf("==============================================================================\n");

		char temp[LINE_LEN + 1];
		//输出包
		for (i = 0; i < header->caplen; ++i)
		{
			printf("%.2x ", pkt_data[i]);
			if (isgraph(pkt_data[i]) || pkt_data[i] == ' ')
				temp[i % LINE_LEN] = pkt_data[i];
			else
				temp[i % LINE_LEN] = '.';

			if (i % LINE_LEN == 15)
			{
				temp[16] = '\0';
				printf("        ");
				printf("%s", temp);
				printf("\n");
				memset(temp, 0, LINE_LEN);
			}
		}
		printf("\n");

		//分析数据包
		ethernet_protocol_packet_handle(NULL, header, pkt_data);
	}

	if (res == -1)
	{
		printf("Error reading the packets: %s\n", pcap_geterr(fp));
		pcap_close(fp);
		pcap_freealldevs(alldevs);
		fclose(stdin);
		if (file)
			fclose(file);
		return -1;
	}

	//释放
	pcap_close(fp);
	pcap_freealldevs(alldevs);
	fclose(stdin);
	if (file)
		fclose(file);

	return 0;
}

分析数据包就是解析数据,去掉以太网头(14个字节)和 网络层ip头 以及传输层的tcp或者udp 头,如果是icmp去掉icmp头,即可解析出来应用层数据。

十二、windows网络知识梳理(12)--进阶知识流量监控-Winpcap_第4张图片

你可能感兴趣的:(Win,socket,网络,winpcap,socket,C++流量探测,流量过滤)