计算机网络课设(一)

计算机网络课设(一)对Windows下的一下抓包工具的初步了解

主要选了利用抓包工具对TCP工作过程进行分析和监控IP数据包两个题目,有时间有精力再说别的吧

Fiddler使用

1.Fiddler是什么

Fiddler是位于客户端和服务器端的HTTP代理,也是目前最常用的http的抓包工具之一 。(一开始分析的时候没有注意该工具的定位,废了点时间)

2.Fiddler下载地址

Fiddler 下载地址 :https://www.telerik.com/download/fiddler

Fiddler2离线下载地址:https://pan.baidu.com/s/1bpnp3Ef 密码:5skw

这里需要注意,他是用于分析http/HTTPS的工具

如果是处理HTTP,HTTPS 还是用Fiddler, 其他协议比如TCP,UDP 就用wireshark.

wireshark使用

WireShark软件安装

软件下载路径:wireshark官网。按照系统版本选择下载,下载完成后,按照软件提示一路Next安装。

如果你是Win10系统,安装完成后,选择抓包但是不显示网卡,下载win10pcap兼容性安装包。下载路径:win10pcap兼容性安装包

分析TCP工作过程

wireshark是常用的网络抓包工具,这里尝试用它抓取TCP包并分析三次握手过程

看这个看这个!!https://www.cnblogs.com/xig112635/p/15236771.html

利用winpcap开发包捕获IP数据包

在Windows环境下,选择使用winpcap第三方的库文件

winpcap的下载安装

下载地址:https://www.winpcap.org/devel.htm,这里要注意一定要下载开发包
在配置过程中遇到了以下问题

  1. 在使用该库时由于Windows系统不兼容导致陷入很长时间的困境,依旧是上面的win10pcap兼容性安装包

  2. 未使用Packet.dll文件
    解决:下载Packet.dll,将它拷贝到c:\windows\system32目录下即可(这里可以搜一下dll的配置),当然,如果要能让别人使用的话,最好还是要配置一下调用dll文件,比较简单的就是直接将它和exe文件放在一个目录下(vs的话就是debug目录了)

这里再放两个链接,是关于npcap
Npcap基于WINPCAP,Winpcap基于libpcap,并做出了诸多改进。
下面是官网的介绍,看起来很牛的样子!!!

Npcap is the Nmap Project’s packet capture (and sending) library for
Microsoft Windows. It implements the open Pcap API using a custom
Windows kernel driver alongside our Windows build of the excellent
libpcap library.

这个是npcap的资源包 https://nmap.org/npcap/
这个是GitHub上的仓库 https://github.com/nmap/npcap

winpcap的开发包使用的部分测试学习代码

将开发包lib和include目录下内容分别拷贝至vs对应目录下,或者选择对该项目的vs目录(include路径和运行库路径增添修改)
如下图:
计算机网络课设(一)_第1张图片
在这里插入图片描述
下面的代码都在vs2019下运行通过了,可以直接用

  1. 设备列表打印

采用如下代码对环境进行测试

#include
#include
#include
// #include
// #include

#define WPCAP
#define HAVE_REMOTE
#include
#include"remote-ext.h"
//#pragma comment(lib,"wpcap.lib")

using namespace std;

int main()
{
	pcap_if_t* alldevs;
	pcap_if_t* d;
	int i = 0;
	char errbuf[PCAP_ERRBUF_SIZE];

	/* 获取本地机器设备列表 */
	if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL /* auth is not needed */, &alldevs, errbuf) == -1)
	{
		fprintf(stderr, "Error in pcap_findalldevs_ex: %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");
	}

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

	/* 不再需要设备列表了,释放它 */
	pcap_freealldevs(alldevs);
	return 0;
}

遇到问题: VS2019项目出现"const char *" 类型的实参与 “char *” 类型的形参不兼容

解决方案: 可以在VS2019中依次点击项目->属性->C/C+±>语言->符合模式,将原来的“是”改为“否”即可。

2.捕获数据包

下面是捕获所有数据包的示例程序:

#define WPCAP
#define HAVE_REMOTE
#include
#include"remote-ext.h"
//#pragma comment(lib,"wpcap.lib")

using namespace std;

int main()
{
    pcap_if_t* allAdapters;//适配器列表
    pcap_if_t* adapter;
    pcap_t* adapterHandle;//适配器句柄
    struct pcap_pkthdr* packetHeader;
    const u_char* packetData;
    char errorBuffer[PCAP_ERRBUF_SIZE];//错误信息缓冲区
    if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL,
        &allAdapters, errorBuffer) == -1)
    {//检索机器连接的所有网络适配器
        fprintf(stderr, "Error in pcap_findalldevs_ex function: %s\n", errorBuffer);
        return -1;
    }
    if (allAdapters == NULL)
    {//不存在任何适配器
        printf("\nNo adapters found! Make sure WinPcap is installed.\n");
        return 0;
    }
    int crtAdapter = 0;
    for (adapter = allAdapters; adapter != NULL; adapter = adapter->next)
    {//遍历输入适配器信息(名称和描述信息)
        printf("\n%d.%s ", ++crtAdapter, adapter->name);
        printf("-- %s\n", adapter->description);
    }
    printf("\n");
    //选择要捕获数据包的适配器
    int adapterNumber;
    printf("Enter the adapter number between 1 and %d:", crtAdapter);
    scanf_s("%d", &adapterNumber);
    if (adapterNumber < 1 || adapterNumber > crtAdapter)
    {
        printf("\nAdapter number out of range.\n");
        // 释放适配器列表
        pcap_freealldevs(allAdapters);
        return -1;
    }
    adapter = allAdapters;
    for (crtAdapter = 0; crtAdapter < adapterNumber - 1; crtAdapter++)
        adapter = adapter->next;
    // 打开指定适配器
    adapterHandle = pcap_open(adapter->name, // name of the adapter
        65536,         // portion of the packet to capture
                       // 65536 guarantees that the whole 
                        // packet will be captured
        PCAP_OPENFLAG_PROMISCUOUS, // promiscuous mode
        1000,             // read timeout - 1 millisecond
        NULL,          // authentication on the remote machine
        errorBuffer    // error buffer
    );
    if (adapterHandle == NULL)
    {//指定适配器打开失败
        fprintf(stderr, "\nUnable to open the adapter\n", adapter->name);
        // 释放适配器列表
        pcap_freealldevs(allAdapters);
        return -1;
    }

    printf("\nCapture session started on  adapter %s\n", adapter->name);

    pcap_freealldevs(allAdapters);//释放适配器列表
    // 开始捕获数据包
    int retValue;
    while ((retValue = pcap_next_ex(adapterHandle,
        &packetHeader,
        &packetData)) >= 0)
    {
        // timeout elapsed if we reach this point
        if (retValue == 0)
            continue;
        //打印捕获数据包的信息
        printf("length of packet: %d\n", packetHeader->len);
    }
    // if we get here, there was an error reading the packets
    if (retValue == -1)
    {
        printf("Error reading the packets: %s\n", pcap_geterr(adapterHandle));
        return -1;
    }
    pcap_close(adapterHandle);
    return 0;
}

3.打印数据包的目的地址和源地址
下面尝试捕获udp数据报并对目标地址和源地址进行输出

可以在参考一下这两个链接查看过滤规则 复杂点的 简单点的

#include
#include
#include
// #include
// #include

#define WPCAP
#define HAVE_REMOTE
#include
#include"remote-ext.h"

#include
#pragma comment(lib,"wpcap.lib")
#pragma comment(lib,"packet.lib")
#pragma comment(lib,"ws2_32.lib")//ntohs头文件及链接库

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

using namespace std;

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

/* IPv4 header */
typedef 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
}ip_header;

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

/* prototype of the packet handler */
void packet_handler(u_char* param, const struct pcap_pkthdr* header, const u_char* pkt_data);

int main()
{
	pcap_if_t* alldevs;
	pcap_if_t* d;
	pcap_t* adhandle;//数据包
	int i = 0;
	int inum;
	u_int netmask;
	char packet_filter[] = "ip and udp";
	char errbuf[PCAP_ERRBUF_SIZE];
	struct bpf_program fcode;

	/* 获取本地机器设备列表 */
	/*pcap_findalldevs_ex函数指定本机时指定参数"rpcap://" 或 预定义宏PCAP_SRC_IF_STRING
	当指定远程机器时需要按照"rpcap://host:port"的格式,默认端口号为2002
	远程机器有密码时需要指定用户名和密码。*/
	if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL /* auth is not needed */, &alldevs, errbuf) == -1)
	{
		fprintf(stderr, "Error in pcap_findalldevs_ex: %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");
	}

	if (i == 0)
	{
		printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
		return 1;
	}
	printf("Enter the interface number (1-%d):", i);
	scanf_s("%d", &inum);

	/* Check if the user specified a valid adapter */
	if (inum < 1 || inum > i)
	{
		printf("\nAdapter number out of range.\n");

		/* Free the device list */
		pcap_freealldevs(alldevs);
		return -1;
	}

	/* Jump to the selected adapter */
	for (d = alldevs, i = 0; i < inum - 1; d = d->next, i++);
	/* Open the adapter */
	adhandle = pcap_open_live(d->name,	// name of the device
		65536,			// portion of the packet to capture. 
					   // 65536 grants that the whole packet will be captured on all the MACs.
		PCAP_OPENFLAG_PROMISCUOUS,				// promiscuous mode (nonzero means promiscuous)
		1000,			// read timeout
		errbuf			// error buffer
	);
	if (adhandle == NULL)
	{
		fprintf(stderr, "\nUnable to open the adapter. %s is not supported by WinPcap\n");
		/* Free the device list */
		pcap_freealldevs(alldevs);
		return -1;
	}
	
	if (pcap_datalink(adhandle) != DLT_EN10MB)//判断链路层数据类型
	{
		fprintf(stderr, "\nThis program works only on Ethernet networks.\n");
		/* Free the device list */
		pcap_freealldevs(alldevs);
		return -1;
	}

	if (d->addresses != NULL)
		/* Retrieve the mask of the first address of the interface */
		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;
	//compile the filter
	if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) < 0)//把用户输入的过滤字符串编译进过滤信息的,这个过滤信息可以决定哪些包是用户可获取到的 。
	{
		fprintf(stderr, "\nUnable to compile the packet filter. Check the syntax.\n");
		/* Free the device list */
		pcap_freealldevs(alldevs);
		return -1;
	}

	/* 不再需要设备列表了,释放它 */
	pcap_freealldevs(alldevs);
	/* start the capture */
	pcap_loop(adhandle, 0, packet_handler, NULL);
	//pcap_close(adhandle);
	return 0;
}

void packet_handler(u_char* param, const pcap_pkthdr* header, const u_char* pkt_data)
{
	printf("抓到数据了  ");
	struct tm* ltime;
	char timestr[16];
	ip_header* ih;
	udp_header* uh;
	u_int ip_len;
	u_short sport, dport;
	time_t local_tv_sec;
	/* convert the timestamp to readable format */
	local_tv_sec = header->ts.tv_sec;
	ltime = new struct tm;
	time(&local_tv_sec);
	localtime_s(ltime, &local_tv_sec);
	//ltime=localtime(&local_tv_sec);//该函数在vs2010以后被弃用,改用增加了安全的localtime_s
	strftime(timestr, sizeof timestr, "%H:%M:%S", ltime);

	/* print timestamp and length of the packet */
	printf("%s.%.6d len:%d \n", timestr, header->ts.tv_usec, header->len);
	/* retireve the position of the ip header */
	ih = (ip_header*)(pkt_data +
		14); //length of ethernet header

	/* retireve the position of the udp header */
	ip_len = (ih->ver_ihl & 0xf) * 4;
	uh = (udp_header*)((u_char*)ih + ip_len);
	/* convert from network byte order to host byte order */
	sport = ntohs(uh->sport);
	dport = ntohs(uh->dport);
	/* print ip addresses and udp ports */
	printf("%d.%d.%d.%d.%d -> %d.%d.%d.%d.%d\n",
		ih->saddr.byte1,
		ih->saddr.byte2,
		ih->saddr.byte3,
		ih->saddr.byte4,
		sport,
		ih->daddr.byte1,
		ih->daddr.byte2,
		ih->daddr.byte3,
		ih->daddr.byte4,
		dport);
}

你可能感兴趣的:(网络,tcp/ip)