Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >腾讯云上 Winpcap 网络编程四之主机通信

腾讯云上 Winpcap 网络编程四之主机通信

原创
作者头像
崔庆才
修改于 2017-06-19 11:10:39
修改于 2017-06-19 11:10:39
4.9K0
举报
文章被收录于专栏:进击的Coder进击的Coder

学习资源

我的腾讯云主机预装了 Windows Server ,截图如下:

两台主机通信实战

在上一篇我给大家介绍了《腾讯云上Winpcap网络编程三之ARP协议获得MAC地址表》

接下来我们让用户输入要发送的 IP 地址和要发送的数据

代码语言:txt
AI代码解释
复制
u_int ip1,ip2,ip3,ip4;
		scanf_s("%d.%d.%d.%d",&ip1,&ip2,&ip3,&ip4);
		printf("请输入你要发送的内容:\n");
		getchar();
		gets_s(TcpData);
		printf("要发送的内容:%s\n",TcpData);

声明一下 TcpData

代码语言:txt
AI代码解释
复制
	char TcpData[20];   //发送内容

接下来就是重头戏了,需要声明各种结构体,我们发送的是 TCP 数据,这样, TCP 的 TcpData 就作为真正的内容,然后在前面加上 TCP 头,IP 头,帧头,还有校验和要正确。

最后构成一个完整的帧,那么另外声明的结构体如下,前面代码声明过的帧头部结构体就去掉了。

代码语言:txt
AI代码解释
复制
//IP地址格式
struct IpAddress
{
    u_char byte1;
    u_char byte2;
    u_char byte3;
    u_char byte4;
};

//帧头部结构体,共14字节
struct EthernetHeader
{
    u_char DestMAC[6];    //目的MAC地址 6字节
    u_char SourMAC[6];   //源MAC地址 6字节
    u_short EthType;         //上一层协议类型,如0x0800代表上一层是IP协议,0x0806为arp  2字节
};

//IP头部结构体,共20字节
struct IpHeader
{
    unsigned char Version_HLen;   //版本信息4位 ,头长度4位 1字节
    unsigned char TOS;                    //服务类型    1字节
    short Length;                              //数据包长度 2字节
    short Ident;                                 //数据包标识  2字节
    short Flags_Offset;                    //标志3位,片偏移13位  2字节
    unsigned char TTL;                   //存活时间  1字节
    unsigned char Protocol;          //协议类型  1字节
    short Checksum;                       //首部校验和 2字节
	IpAddress SourceAddr;       //源IP地址   4字节
	IpAddress DestinationAddr; //目的IP地址  4字节
};

//TCP头部结构体,共20字节
struct TcpHeader
{
    unsigned short SrcPort;                        //源端口号  2字节
    unsigned short DstPort;                        //目的端口号 2字节
    unsigned int SequenceNum;               //序号  4字节
    unsigned int Acknowledgment;         //确认号  4字节
    unsigned char HdrLen;                         //首部长度4位,保留位6位 共10位
    unsigned char Flags;                              //标志位6位
    unsigned short AdvertisedWindow;  //窗口大小16位 2字节
    unsigned short Checksum;                  //校验和16位   2字节
    unsigned short UrgPtr;						  //紧急指针16位   2字节
};

//TCP伪首部结构体 12字节
struct PsdTcpHeader
{
	IpAddress SourceAddr;                     //源IP地址  4字节
	IpAddress DestinationAddr;             //目的IP地址 4字节
    char Zero;                                                    //填充位  1字节
    char Protcol;                                               //协议号  1字节
    unsigned short TcpLen;                           //TCP包长度 2字节
};

继续 main 函数中对各种结构体的数据进行初始化赋值,并计算校验和。

代码语言:txt
AI代码解释
复制
//结构体初始化为0序列
		memset(&ethernet, 0, sizeof(ethernet));
		BYTE destmac[8];
		//目的 MAC 地址,此处没有对帧的 MAC 地址进行赋值,因为网卡设置的混杂模式,可以接受经过该网卡的所有帧。当然最好的方法是赋值为ARP刚才获取到的MAC地址,当然不赋值也可以捕捉到并解析,在此处仅做下说明。
		destmac[0] = 0x00;
		destmac[1] = 0x11;
		destmac[2] = 0x22;
		destmac[3] = 0x33;
		destmac[4] = 0x44;
		destmac[5] = 0x55;
		//赋值目的MAC地址
		memcpy(ethernet.DestMAC, destmac, 6);
		BYTE hostmac[8];
		//源MAC地址
		hostmac[0] = 0x00;
		hostmac[1] = 0x1a;
		hostmac[2] = 0x4d;
		hostmac[3] = 0x70;
		hostmac[4] = 0xa3;
		hostmac[5] = 0x89;
		//赋值源MAC地址
		memcpy(ethernet.SourMAC, hostmac, 6);
		//上层协议类型,0x0800代表IP协议
		ethernet.EthType = htons(0x0800);
		//赋值SendBuffer
		memcpy(&SendBuffer, ðernet, sizeof(struct EthernetHeader));
		//赋值IP头部信息
		ip.Version_HLen = 0x45;
		ip.TOS = 0;
		ip.Length = htons(sizeof(struct IpHeader) + sizeof(struct TcpHeader) + strlen(TcpData));
		ip.Ident = htons(1);
		ip.Flags_Offset = 0;
		ip.TTL = 128;
		ip.Protocol = 6;
		ip.Checksum = 0;
		//源IP地址
		ip.SourceAddr.byte1 = 127;
		ip.SourceAddr.byte2 = 0;
		ip.SourceAddr.byte3 = 0;
		ip.SourceAddr.byte4 = 1;
		//目的IP地址
		ip.DestinationAddr.byte1 = ip1;
		ip.DestinationAddr.byte2 = ip2;
		ip.DestinationAddr.byte3 = ip3;
		ip.DestinationAddr.byte4 = ip4;
		//赋值SendBuffer
		memcpy(&SendBuffer[sizeof(struct EthernetHeader)], &ip, 20);
		//赋值TCP头部内容
		tcp.DstPort = htons(102);
		tcp.SrcPort = htons(1000);
		tcp.SequenceNum = htonl(11);
		tcp.Acknowledgment = 0;
		tcp.HdrLen = 0x50;
		tcp.Flags = 0x18;
		tcp.AdvertisedWindow = htons(512);
		tcp.UrgPtr = 0;
		tcp.Checksum = 0;
		//赋值SendBuffer
		memcpy(&SendBuffer[sizeof(struct EthernetHeader) + 20], &tcp, 20);
		//赋值伪首部
		ptcp.SourceAddr = ip.SourceAddr;
		ptcp.DestinationAddr = ip.DestinationAddr;
		ptcp.Zero = 0;
		ptcp.Protcol = 6;
		ptcp.TcpLen = htons(sizeof(struct TcpHeader) + strlen(TcpData));
		//声明临时存储变量,用来计算校验和
		char TempBuffer[65535];
		memcpy(TempBuffer, &ptcp, sizeof(struct PsdTcpHeader));
		memcpy(TempBuffer + sizeof(struct PsdTcpHeader), &tcp, sizeof(struct TcpHeader));
		memcpy(TempBuffer + sizeof(struct PsdTcpHeader) + sizeof(struct TcpHeader), TcpData, strlen(TcpData));
		//计算TCP的校验和
		tcp.Checksum = checksum((USHORT*)(TempBuffer), sizeof(struct PsdTcpHeader) + sizeof(struct TcpHeader) + strlen(TcpData));
		//重新把SendBuffer赋值,因为此时校验和已经改变,赋值新的
		memcpy(SendBuffer + sizeof(struct EthernetHeader) + sizeof(struct IpHeader), &tcp, sizeof(struct TcpHeader));
		memcpy(SendBuffer + sizeof(struct EthernetHeader) + sizeof(struct IpHeader) + sizeof(struct TcpHeader), TcpData, strlen(TcpData));
		//初始化TempBuffer为0序列,存储变量来计算IP校验和
		memset(TempBuffer, 0, sizeof(TempBuffer));
		memcpy(TempBuffer, &ip, sizeof(struct IpHeader));
		//计算IP校验和
		ip.Checksum = checksum((USHORT*)(TempBuffer), sizeof(struct IpHeader));
		//重新把SendBuffer赋值,IP校验和已经改变
		memcpy(SendBuffer + sizeof(struct EthernetHeader), &ip, sizeof(struct IpHeader));
		//发送序列的长度
		int size = sizeof(struct EthernetHeader) + sizeof(struct IpHeader) + sizeof(struct TcpHeader) + strlen(TcpData);
		int result = pcap_sendpacket(adhandle, SendBuffer,size);
		if (result != 0)
		{
			printf("Send Error!\n");
		} 
		else
		{
			printf("Send TCP Packet.\n");
			printf("Dstination Port:%d\n", ntohs(tcp.DstPort));
			printf("Source Port:%d\n", ntohs(tcp.SrcPort));
			printf("Sequence:%d\n", ntohl(tcp.SequenceNum));
			printf("Acknowledgment:%d\n", ntohl(tcp.Acknowledgment));
			printf("Header Length:%d*4\n", tcp.HdrLen >> 4);
			printf("Flags:0x%0x\n", tcp.Flags);
			printf("AdvertiseWindow:%d\n", ntohs(tcp.AdvertisedWindow));
			printf("UrgPtr:%d\n", ntohs(tcp.UrgPtr));
			printf("Checksum:%u\n", ntohs(tcp.Checksum));
			printf("Send Successfully!\n");
		}

校验和方法如下:

代码语言:txt
AI代码解释
复制
//获得校验和的方法
unsigned short checksum(unsigned short *data, int length)
{
    unsigned long temp = 0;
    while (length > 1)
    {
        temp +=  *data++;
        length -= sizeof(unsigned short);
    }
    if (length)
    {
        temp += *(unsigned short*)data;
    }
    temp = (temp >> 16) + (temp &0xffff);
    temp += (temp >> 16);
    return (unsigned short)(~temp);
}

记得在声明一下这个方法。如果放在 main 函数前当然就不用声明啦。

另外需要声明的变量有

代码语言:txt
AI代码解释
复制
		struct EthernetHeader ethernet;    //以太网帧头
    struct IpHeader ip;                            //IP头
    struct TcpHeader tcp;                      //TCP头
    struct PsdTcpHeader ptcp;             //TCP伪首部

代码语言:txt
AI代码解释
复制
unsigned char SendBuffer[200];       //发送队列

接下来的运行结果:

代码语言:txt
AI代码解释
复制
获取MAC地址完毕,请输
121.250.216.112
请输入你要发送的内容
what is tcp
要发送的内容:what i
Send TCP Packet.
Dstination Port:102
Source Port:1000
Sequence:11
Acknowledgment:0
Header Length:5*4
Flags:0x18
AdvertiseWindow:512
UrgPtr:0
Checksum:17149
Send Successfully!

截图如下:

好啦,发送帧到此就告一段落啦!如果有疑问请留言。

帧的接收很简单,直接贴源码如下:

代码语言:txt
AI代码解释
复制
#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>


char *iptos(u_long in);       //u_long即为 unsigned long
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);
//struct tm *ltime;					//和时间处理有关的变量

struct IpAddress
{
    u_char byte1;
    u_char byte2;
    u_char byte3;
    u_char byte4;
};

//帧头部结构体,共14字节
struct EthernetHeader
{
    u_char DestMAC[6];    //目的MAC地址 6字节
    u_char SourMAC[6];   //源MAC地址 6字节
    u_short EthType;         //上一层协议类型,如0x0800代表上一层是IP协议,0x0806为arp  2字节
};

//IP头部结构体,共20字节
struct IpHeader
{
    unsigned char Version_HLen;   //版本信息4位 ,头长度4位 1字节
    unsigned char TOS;                    //服务类型    1字节
    short Length;                              //数据包长度 2字节
    short Ident;                                 //数据包标识  2字节
    short Flags_Offset;                    //标志3位,片偏移13位  2字节
    unsigned char TTL;                    //存活时间  1字节
    unsigned char Protocol;           //协议类型  1字节
    short Checksum;                        //首部校验和 2字节
    IpAddress SourceAddr;           //源IP地址   4字节
    IpAddress DestinationAddr;   //目的IP地址  4字节
};

//TCP头部结构体,共20字节
struct TcpHeader
{
    unsigned short SrcPort;                        //源端口号  2字节
    unsigned short DstPort;                        //目的端口号 2字节
    unsigned int SequenceNum;               //序号  4字节
    unsigned int Acknowledgment;         //确认号  4字节
    unsigned char HdrLen;                         //首部长度4位,保留位6位 共10位
    unsigned char Flags;                              //标志位6位
    unsigned short AdvertisedWindow;  //窗口大小16位 2字节
    unsigned short Checksum;                  //校验和16位   2字节
    unsigned short UrgPtr;						  //紧急指针16位   2字节
};

//TCP伪首部结构体 12字节
struct PsdTcpHeader
{
    unsigned long SourceAddr;                     //源IP地址  4字节
    unsigned long DestinationAddr;             //目的IP地址 4字节
    char Zero;                                                    //填充位  1字节
    char Protcol;                                               //协议号  1字节
    unsigned short TcpLen;                           //TCP包长度 2字节
};


int main(){

	EthernetHeader *ethernet;    //以太网帧头
    IpHeader *ip;                            //IP头
    TcpHeader *tcp;                      //TCP头
    PsdTcpHeader *ptcp;             //TCP伪首部

	pcap_if_t  * alldevs;       //所有网络适配器
	pcap_if_t  *d;					//选中的网络适配器
	char errbuf[PCAP_ERRBUF_SIZE];   //错误缓冲区,大小为256
	char source[PCAP_ERRBUF_SIZE];
	pcap_t *adhandle;           //捕捉实例,是pcap_open返回的对象
	int i = 0;                            //适配器计数变量
	struct pcap_pkthdr *header;    //接收到的数据包的头部
    const u_char *pkt_data;			  //接收到的数据包的内容
	int res;                                    //表示是否接收到了数据包
	u_int netmask;                       //过滤时用的子网掩码
	char packet_filter[] = "tcp";        //过滤字符
	struct bpf_program fcode;                     //pcap_compile所调用的结构体

	u_int ip_len;                                       //ip地址有效长度
	u_short sport,dport;                        //主机字节序列
	u_char packet[100];                       //发送数据包目的地址
	pcap_dumper_t *dumpfile;         //堆文件

	//time_t local_tv_sec;				//和时间处理有关的变量
    //char timestr[16];					//和时间处理有关的变量

	
	//获取本地适配器列表
	if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,NULL,&alldevs,errbuf) == -1){
		//结果为-1代表出现获取适配器列表失败
		fprintf(stderr,"Error in pcap_findalldevs_ex:\n",errbuf);
		//exit(0)代表正常退出,exit(other)为非正常退出,这个值会传给操作系统
		exit(1);
	}
	//打印设备列表信息
	for(d = alldevs;d !=NULL;d = d->next){
		printf("-----------------------------------------------------------------\nnumber:%d\nname:%s\n",++i,d->name);
		if(d->description){
			//打印适配器的描述信息
			printf("description:%s\n",d->description);
		}else{
			//适配器不存在描述信息
			printf("description:%s","no description\n");
		}
		//打印本地环回地址
		printf("\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no");
		
		 pcap_addr_t *a;       //网络适配器的地址用来存储变量
		 for(a = d->addresses;a;a = a->next){
			 //sa_family代表了地址的类型,是IPV4地址类型还是IPV6地址类型
			 switch (a->addr->sa_family)
			 {
				 case AF_INET:  //代表IPV4类型地址
					 printf("Address Family Name:AF_INET\n");
					 if(a->addr){
						 //->的优先级等同于括号,高于强制类型转换,因为addr为sockaddr类型,对其进行操作须转换为sockaddr_in类型
						 printf("Address:%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: //代表IPV6类型地址
					 printf("Address Family Name:AF_INET6\n");
					 printf("this is an IPV6 address\n");
					 break;
				 default:
					 break;
			 }
		 }
	}
	//i为0代表上述循环未进入,即没有找到适配器,可能的原因为Winpcap没有安装导致未扫描到
	if(i == 0){
		printf("interface not found,please check winpcap installation");
	}

	int num;
	printf("Enter the interface number(1-%d):",i);
	//让用户选择选择哪个适配器进行抓包
	scanf_s("%d",&num);
	printf("\n");

	//用户输入的数字超出合理范围
	if(num<1||num>i){
		printf("number out of range\n");
		pcap_freealldevs(alldevs);
		return -1;
	}
	//跳转到选中的适配器
	for(d=alldevs, i=0; i< num-1 ; d=d->next, i++);

	//运行到此处说明用户的输入是合法的
	if((adhandle = pcap_open(d->name,		//设备名称
														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;
	}
	

	//打印输出,正在监听中
	printf("\nlistening on %s...\n", d->description);

	//所在网络不是以太网,此处只取这种情况
	if(pcap_datalink(adhandle) != DLT_EN10MB)
    {
        fprintf(stderr,"\nThis program works only on Ethernet networks.\n");
        //释放列表
        pcap_freealldevs(alldevs);
        return -1;
    }

	//先获得地址的子网掩码
	if(d->addresses != NULL)
        //获得接口第一个地址的掩码 
        netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
    else
        // 如果接口没有地址,那么我们假设一个C类的掩码
        netmask=0xffffff;

	//pcap_compile()的原理是将高层的布尔过滤表
	//达式编译成能够被过滤引擎所解释的低层的字节码
	if(pcap_compile(adhandle,	//适配器处理对象
										&fcode,
										packet_filter,   //过滤ip和UDP
										1,                       //优化标志
										netmask           //子网掩码
										)<0)
	{
		//过滤出现问题
		fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax.\n");
        // 释放设备列表
        pcap_freealldevs(alldevs);
        return -1;
	}

	//设置过滤器
    if (pcap_setfilter(adhandle, &fcode)<0)
    {
        fprintf(stderr,"\nError setting the filter.\n");
        //释放设备列表
        pcap_freealldevs(alldevs);
        return -1;
    }


	//利用pcap_next_ex来接受数据包
	while((res = pcap_next_ex(adhandle,&header,&pkt_data))>=0)
	{
		if(res ==0){
			//返回值为0代表接受数据包超时,重新循环继续接收
			continue;
		}else{
			//运行到此处代表接受到正常从数据包
			//header为帧的头部
			printf("%.6ld len:%d ", header->ts.tv_usec, header->len);
			// 获得IP数据包头部的位置
			ip = (IpHeader *) (pkt_data +14);    //14为以太网帧头部长度
			//获得TCP头部的位置
			ip_len = (ip->Version_HLen & 0xf) *4;
			printf("ip_length:%d ",ip_len);
			tcp = (TcpHeader *)((u_char *)ip+ip_len);
			char * data;
			 data = (char *)((u_char *)tcp+20);
			 //将网络字节序列转换成主机字节序列
			sport = ntohs( tcp->SrcPort );
			dport = ntohs( tcp->DstPort );
			printf("srcport:%d desport:%d\n",sport,dport);
			printf("%d.%d.%d.%d.%d -> %d.%d.%d.%d.%d\n",
					ip->SourceAddr.byte1,
					ip->SourceAddr.byte2,
					ip->SourceAddr.byte3,
					ip->SourceAddr.byte4,
				    sport,
				    ip->DestinationAddr.byte1,
				    ip->DestinationAddr.byte2,
				    ip->DestinationAddr.byte3,
				    ip->DestinationAddr.byte4,
				    dport);
			printf("%s\n",data);
		}

	}

	
	//释放网络适配器列表
	pcap_freealldevs(alldevs);

	/**
	int pcap_loop  ( pcap_t *  p,  
								  int  cnt,  
								  pcap_handler  callback,  
								  u_char *  user   
								 );
     typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
                 const u_char *);
	*/
	//开始捕获信息,当捕获到数据包时,会自动调用这个函数
	//pcap_loop(adhandle,0,packet_handler,NULL);

	int inum;
	scanf_s("%d", &inum);

	return 0;

}

/* 每次捕获到数据包时,libpcap都会自动调用这个回调函数 */
/**
pcap_loop()函数是基于回调的原理来进行数据捕获的,如技术文档所说,这是一种精妙的方法,并且在某些场合下,
它是一种很好的选择。但是在处理回调有时候会并不实用,它会增加程序的复杂度,特别是在多线程的C++程序中
*/
/*
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
    struct tm *ltime = NULL;
    char timestr[16];
    time_t local_tv_sec;

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

    printf("%s,%.6ld len:%d\n", timestr, header->ts.tv_usec, header->len);

}
*/
/* 将数字类型的IP地址转换成字符串类型的 */
#define IPTOSBUFFERS    12
char *iptos(u_long in)
{
    static char output[IPTOSBUFFERS][3*4+3+1];
    static short which;
    u_char *p;

    p = (u_char *)&in;
    which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
    sprintf_s(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
    return output[which];
}

运行截图如下

Thank You

如有问题,欢迎留言~

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
运用Npcap库实现SYN半开放扫描
Npcap 是一款高性能的网络捕获和数据包分析库,作为 Nmap 项目的一部分,Npcap 可用于捕获、发送和分析网络数据包。本章将介绍如何使用 Npcap 库来实现半开放扫描功能。TCP SYN 半开放扫描是一种常见且广泛使用的端口扫描技术,用于探测目标主机端口的开放状态。由于这种方法并不完成完整的 TCP 三次握手过程,因此具有更高的隐蔽性和扫描效率。
王 瑞
2024/08/10
2360
运用Npcap库实现SYN半开放扫描
腾讯云上Winpcap网络编程三之ARP协议获得MAC地址表
学习文档 这里我们直接进入正题吧,关于Winpcap的基础知识讲解这里就不再赘述了。在这里给大家提供一些学习网址: Winpcap网络编程及通信编程 Winpcap中文技术文档 学习内容 获取设备列表
崔庆才
2017/03/30
2.9K0
18.1 Socket 原生套接字抓包
原生套接字抓包的实现原理依赖于Windows系统中提供的ioctlsocket函数,该函数可将指定的网卡设置为混杂模式,网卡混杂模式(Promiscuous Mode)是常用于计算机网络抓包的一种模式,也称为监听模式。在混杂模式下,网卡可以收到经过主机的所有数据包,而非只接收它所对应的MAC地址的数据包。
王 瑞
2023/10/25
4980
18.1 Socket 原生套接字抓包
pcap文件格式及文件解析[通俗易懂]
文件头结构体 sturct pcap_file_header { DWORD magic; DWORD version_major; DWORD version_minor; DWORD thiszone; DWORD sigfigs; DWORD snaplen; DWORD linktype; } 说明: 1、标识位:32位的,这个标识位的值是16进制的 0xa1b2c3d4。 a 32-bit magic number ,The magic number has the value hex a1b2c3d4. 2、主版本号:16位, 默认值为0x2。 a 16-bit major version number,The major version number should have the value 2. 3、副版本号:16位,默认值为0x04。 a 16-bit minor version number,The minor version number should have the value 4. 4、区域时间:32位,实际上该值并未使用,因此可以将该位设置为0。 a 32-bit time zone offset field that actually not used, so you can (and probably should) just make it 0; 5、精确时间戳:32位,实际上该值并未使用,因此可以将该值设置为0。 a 32-bit time stamp accuracy field tha not actually used,so you can (and probably should) just make it 0; 6、数据包最大长度:32位,该值设置所抓获的数据包的最大长度,如果所有数据包都要抓获,将该值设置为65535;例如:想获取数据包的前64字节,可将该值设置为64。 a 32-bit snapshot length” field;The snapshot length field should be the maximum number of bytes perpacket that will be captured. If the entire packet is captured, make it 65535; if you only capture, for example, the first 64 bytes of the packet, make it 64. 7、链路层类型:32位, 数据包的链路层包头决定了链路层的类型。 a 32-bit link layer type field.The link-layer type depends on the type of link-layer header that the packets in the capture file have: 以下是数据值与链路层类型的对应表 0 BSD loopback devices, except for later OpenBSD 1 Ethernet, and Linux loopback devices 以太网类型,大多数的数据包为这种类型。 6 802.5 Token Ring 7 ARCnet 8 SLIP 9 PPP 10 FDDI 100 LLC/SNAP-encapsulated ATM 101 raw IP, with no link 102 BSD/OS SLIP 103 BSD/OS PPP 104 Cisco HDLC 105 802.11 108 later OpenBSD loopback devices (with the AF_value in network byte order) 113 special Linux cooked capture 114 LocalTalk
全栈程序员站长
2022/09/20
10K0
C/C++ Npcap包实现ARP欺骗
npcap 是Nmap自带的一个数据包处理工具,Nmap底层就是使用这个包进行收发包的,该库,是可以进行二次开发的,不过使用C语言开发费劲,在进行渗透任务时,还是使用Python构建数据包高效,唯一的区别是使用Python的库,可以节约我们寻找数据包结构的时间.
王 瑞
2022/12/28
7400
C/C++ Npcap包实现数据嗅探
npcap 是Nmap自带的一个数据包处理工具,Nmap底层就是使用这个包进行收发包的,该库,是可以进行二次开发的,不过使用C语言开发费劲,在进行渗透任务时,还是使用Python构建数据包高效,这东西没啥意义.
王 瑞
2022/12/28
1.1K0
C/C++ 运用Npcap发送UDP数据包
Npcap 是一个功能强大的开源网络抓包库,它是 WinPcap 的一个分支,并提供了一些增强和改进。特别适用于在 Windows 环境下进行网络流量捕获和分析。除了支持通常的网络抓包功能外,Npcap 还提供了对数据包的拼合与构造,使其成为实现 UDP 数据包发包的理想选择。本章将通过Npcap库构造一个UDP原始数据包,并实现对特定主机的发包功能,通过本章的学习读者可以掌握如何使用Npcap库伪造特定的数据包格式。
王 瑞
2023/11/26
1.2K0
C/C++ 运用Npcap发送UDP数据包
18.3 NPCAP 构建中间人攻击
ARP欺骗(ARP Spoofing)是一种网络攻击手段,其目的是通过欺骗目标主机来实现网络攻击。ARP协议是一种用于获取MAC地址的协议,因此欺骗者可以使用ARP欺骗来迫使其目标主机将网络流量发送到攻击者控制的设备上,从而实现网络攻击。
王 瑞
2023/10/27
4000
18.3 NPCAP 构建中间人攻击
使用Libpcap捕获局域网中的数据包
void handler(u_char *, const struct pcap_pkthdr *, const u_char *);是一个回调函数,用于处理数据包。它接受三个参数:
Andromeda
2023/11/23
7610
用户空间协议栈设计和netmap综合指南,将网络效率提升到新高度
应用层: 最接近用户的一层,为用户程序提供网络服务。主要协议有HTTP、FTP、TFTP、SMTP、DNS、POP3、DHCP等。 表示层: 数据的表示、安全、压缩。管理数据的解密和加密。 会话层: 负责在网络中的两个节点之间的建立、维持和终止通信。 传输层: 模型中最重要的一层,负责传输协议的流控和差错校验。数据包离开网卡后进入的就是传输层;主要协议有:TCP、UDP等。 网络层: 将网络地址翻译成对应的物理地址。主要协议有:ICMP、IP等。 数据链路层: 建立逻辑连接、进行硬件地址寻址、差错校验等功能,解决两台相连主机之间的通信问题。主要协议有SLIP、以太网协议/MAC帧协议、ARP和RARP等。 物理层: 模型的最低层,建立、维护、断开物理连接,传输比特流。常见的物理媒介有光纤、电缆、中继器等。主要协议有RS232等。
Lion 莱恩呀
2024/09/14
1400
用户空间协议栈设计和netmap综合指南,将网络效率提升到新高度
扯谈网络编程之自己实现ping
ping是基于ICMP(Internet Control Message Protocol)协议实现的。而ICMP协议是在IP层实现的。
全栈程序员站长
2022/07/07
6380
网络安全ICMP重定向攻击
第一条是缺省路由,意思是说,当一个数据包的目的网段不在路由记录中,那么,路由器该把那个数据包发送到哪里,缺省路由是由网关default gateway决定的。
matt
2022/10/25
1.3K0
网络安全ICMP重定向攻击
Winpcap基础代码
Winpcap基础代码     使用Winpcap进行网络数据的截获和发送都需要的一段代码: #include<PCAP.H> #pragma comment(lib, "wpcap.lib") //#pragma comment(lib, "ws2_32.lib") #include<iostream> using namespace std; //回调函数 void packet_handler(u_char*param,const struct pcap_pkthdr*header,const u
Florian
2018/02/05
9300
不使用ip和port如何进行网络通讯(raw socket应用例子)
主要应用方向是上位机和嵌软(如stm32单片机)通讯,不在单片机中嵌入web server,即mac层通讯。
用户5908113
2023/09/09
4460
不使用ip和port如何进行网络通讯(raw socket应用例子)
TCP/IP协议头部结构体(网摘小结)
================================================================================ IP协议   IP协议(Internet Protocol)是网络层协议,用在因特网上,TCP,UDP,ICMP,IGMP数据都是按照IP数据格式发送得。IP协议提供的是不可靠无连接得服务。IP数据包由一个头部和一个正文部分构成。正文主要是传输的数据,我们主要来理解头部数据,可以从其理解到IP协议。  IP数据包头部格式(RFC791)
阳光岛主
2019/02/20
2.1K0
数据包发送与嗅探
实验过程中采用过libnet与libpcap,最后全部转为Raw Socket发送与嗅探。
公众号guangcity
2019/09/20
2.7K0
数据包发送与嗅探
C/C++网络编程时注意的问题小结
1.网络编程在自己定义结构体实现协议的时候,一定要注意字节对齐这个问题。否则sizeof和强制转换指针的时候都会出现很难发现的bug。 什么是字节对齐自行百度。 1 #pragma pack (1)//字节对齐的控制!非常注意! 2 //定义一个以太网头部 3 typedef struct ehhdr 4 5 { 6 7 UCHAR eh_dst[6]; /* destination ethernet addrress */ 8 9 UCHAR
ascii0x03
2018/04/12
7190
18.3 NPCAP自定义数据包过滤
NPCAP 库是一种用于在Windows平台上进行网络数据包捕获和分析的库。它是WinPcap库的一个分支,由Nmap开发团队开发,并在Nmap软件中使用。与WinPcap一样,NPCAP库提供了一些API,使开发人员可以轻松地在其应用程序中捕获和处理网络数据包。NPCAP库可以通过WinPcap API进行编程,因此现有的WinPcap应用程序可以轻松地迁移到NPCAP库上。
王 瑞
2023/10/26
5860
18.3 NPCAP自定义数据包过滤
SeedLab——Packet Sniffing and Spoofing Lab
在这个实验中,攻击者需要能够嗅探数据包,但在容器内运行嗅探程序会有问题,因为容器实际上连接到一个虚拟交换机,所以它只能看到自己的流量,无法看到其他容器之间的数据包。为了解决这个问题,我们在攻击者容器中使用主机模式(host mode)。
Andromeda
2023/11/22
1.1K0
SeedLab——Packet Sniffing and Spoofing Lab
tcpdump命令高级过滤方式
​ 长度4比特。这个字段的作用是为了描述IP包头的长度,因为在IP包头中有变长的可选部分。该部分占4个bit位,单位为32bit(4个字节),即本区域值= IP头部长度(单位为bit)/(84),因此,一个IP包头的长度最长为“1111”,即154=60个字节。IP包头最小长度为20字节。
吴易娃
2024/01/12
8370
相关推荐
运用Npcap库实现SYN半开放扫描
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档