【网络编程】捕获网卡IP数据报

news2024/11/30 2:33:31

本文将通过winsock从应用层捕捉网络层的IP数据报。

唉,原来的时候一直希望能在应用层实现网络游戏加速,发现可以捕捉网卡IP数据报后觉得可能有希望写出来。后面想了想得出结论:可以捕获没卵用,因为没法拦截(包已经发出去了,才反馈给你的,充其量自己就是个监听者),然后又搜了搜那我争取拦截呗,又发现了应用层下似乎只能通过lsp劫持实现,然后游戏呢绝壁检测你的,最终得出结论,还得上驱动【呃虚拟网卡可以吗,我不晓得,去研究一下吧】。

1.使用winsock

	//初始化套接字
	WSADATA WSAData;
	if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0)
	{
		cout << endl << "WSASTartup初始化失败" << endl;
		return;
	}

需要俩头文件

#include <winsock.h>

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

相当于初始化加载winsock.dll,然后winsock返回给你一个WSAData告诉你本机中winsock的信息

2.创建套接字

SOCKET sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP); //三个参分别为通信发生的区字段,套接字的类型,与IP协议
	if (sock == INVALID_SOCKET)
	{
		cout << endl << "创建Socket失败!" << endl;
		closesocket(sock);
		WSACleanup();
	}

socket(a,b,c)

a为AF_INET 【通信发生的区字段,具体啥意思,还有啥我不知道捏,自行百度吧。】

b为SOCK_STREAM,SOCK_DGRAM,SOCK_RAW三个之一。【套接字的类型】

SOCK_STREAM(tcp)SOCK_DGRAM(UDP)SOCK_RAW(IP)

c为参数

IPPROTO_IP = 0,   /* Dummy protocol for TCP   */
IPPROTO_ICMP = 1,   /* Internet Control Message Protocol */
IPPROTO_IGMP = 2,   /* Internet Group Management Protocol */
IPPROTO_IPIP = 4,   /* IPIP tunnels (older KA9Q tunnels use 94) */
IPPROTO_TCP = 6,   /* Transmission Control Protocol */
IPPROTO_EGP = 8,   /* Exterior Gateway Protocol   */
IPPROTO_PUP = 12,   /* PUP protocol     */
IPPROTO_UDP = 17,   /* User Datagram Protocol   */
IPPROTO_IDP = 22,   /* XNS IDP protocol    */
IPPROTO_DCCP = 33,   /* Datagram Congestion Control Protocol */
IPPROTO_RSVP = 46,   /* RSVP protocol    */
IPPROTO_GRE = 47,   /* Cisco GRE tunnels (rfc 1701,1702) */

IPPROTO_IPV6 = 41,   /* IPv6-in-IPv4 tunnelling   */

IPPROTO_ESP = 50,            /* Encapsulation Security Payload protocol */
IPPROTO_AH = 51,             /* Authentication Header protocol       */
IPPROTO_BEETPH = 94,        /* IP option pseudo header for BEET */
IPPROTO_PIM    = 103,   /* Protocol Independent Multicast */

IPPROTO_COMP   = 108,                /* Compression Header protocol */
IPPROTO_SCTP   = 132,   /* Stream Control Transport Protocol */
IPPROTO_UDPLITE = 136, /* UDP-Lite (RFC 3828)    */

IPPROTO_RAW = 255,   /* Raw IP packets    */
IPPROTO_MAX

对于socket(AF_INET, SOCK_RAW, IPPROTO_IP),其原型为

int socket (int domain, int type, int protocol);

1 参数protocol用来指明所要接收的协议包,如果是象IPPROTO_TCP(6)这种非0、非255的协议,当操作系统内核碰到ip头中protocol域和创建socket所使用参数protocol相同的IP包,就会交给这个raw socket来处理,因此,一般来说,要想接收什么样的数据包,就应该在参数protocol里来指定相应的协议。当内核向此raw socket交付数据包的时候,是包括整个IP头的,并且已经是重组好的IP包。

2 如果protocol是IPPROTO_RAW(255),这时候,这个socket只能用来发送IP包,而不能接收任何的数据。发送的数据需要自己填充IP包头,并且自己计算校验和。

3 对于protocol为0(IPPROTO_IP)的raw socket。用于接收任何的IP数据包。其中的校验和和协议分析由程序自己完成

【上面那段我抄的,差不多意思能明白点,但是这个socket函数的b和c参数不是冗余了吗,感觉是有点捏。想了想也有可能是下面这样滴】

b参数指明这个socket能盛放啥类型。c参数指明内核你要给我捕捉啥协议的。【小白理解。可能有错】

3.hostent结构体的说明

4.地址信息的表示

sockaddr_in结构体

struct sockaddr_in

{

    short sin_family;        //协议族Address family

    unsigned short sin_port;    //16位TCP/UDP端口号

    struct in_addr sin_addr;    //32位IP地址

    unsigned char sin_zero[8];  //没有实际意义,只是为了跟SOCKADDR结构在内存中对齐

};

结构体sockaddr_in的成员分析

成员sin_family:

每种协议适用的地址族均不同。比如,IPv4使用4字节地址族,IPv6使用16字节地址族,可以参考表1-2保存的sin_family地址信息

表1-2   地址族
地址族(Adddress Family)含义
AF_INETIPv4网络协议中使用的地址族
AF_INET6IPv6网络协议中使用的地址族
AF_LOCAL本地通信中采用的Unix协议的地址族

AF_LOCAL只是为了说明具有多种地址族而添加的

成员sin_port:

该成员保存16位端口号,且以网络字节序保存(后续还会说明何为网络字节序)

成员sin_addr:

该成员保存32位IP地址信息,且也以网络字节序保存。为理解好该成员,应同时观察结构体in_addr。但结构体in_addr声明为uint32_t,因此只需当做32位整数即可

成员sin_zero:

无特殊含义,只是为了结构体sockaddr_in的大小与sockaddr结构体保持一致而插入的成员。必须填充为0,否则无法得到想要的结果,后续还会介绍sockaddr

【以下个人小白理解,可能有错误。】

【操作系统内部维护了一个类似socket列表的东西,socket呢就是负责你进程使用操作系统的通信资源的,一开始socket被申请出来了,但是占用的本机IP和端口都没有声明。这时候你可以调用bind来指定,指定之后,你的程序就用声明的这一块资源来做事,声明的本机IP和端口就被占用了。操作系统就不会把这个ip和端口分配给别的进程亦或者说别的socket来使用】

5.WSAIoctl

控制一个socket的模式,自行百度吧

6.所有代码,没说的东西都是没啥技术含量的。翻翻书就会的

代码在vs2019编译通过,vs2019有安全审查【可能导致编译不通过】,取消的话

【VS socket】不兼容老版本函数的问题_aaaabbbwwww的博客-CSDN博客

#include <iostream> 
#include <winsock2.h> 
#include <ws2tcpip.h> 
#include <fstream>
#include <windows.h> 
#pragma comment(lib,"ws2_32.lib") //指定连接到网络应用和internet

#define IO_RCVALL _WSAIOW(IOC_VENDOR,1)

typedef struct IP_HEAD
{
	union //定义联合
	{
		unsigned char Version;
		unsigned char HeadLen;
	};
	unsigned char ServiceType;
	unsigned short TotalLen;
	unsigned short Identifier;
	union
	{
		unsigned short Flags;
		unsigned short FragOffset;
	};
	unsigned char TimeToLive;
	unsigned char Protocol;
	unsigned short HeadChecksum;
	unsigned int SourceAddr;
	unsigned int DestinAddr;
	unsigned char Options;
}ip_head; //定义IP头部的数据结构

void main(int argc, char* argv[])
{

	using namespace std;
	ofstream outfile("C://logfile.txt", ios::out);
	/*
	if(argc!=2)
	{
	cout<<endl<<"请以下格式输入命令行:PackParse packet_sum"<<endl;
	return;
	}
	*/

	//初始化套接字
	WSADATA WSAData;
	if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0)
	{
		cout << endl << "WSASTartup初始化失败" << endl;
		return;
	}

	//创建套接字
	SOCKET sock = socket(AF_INET, SOCK_RAW, IPPROTO_IP); //三个参分别为通信发生的区字段,套接字的类型,与IP协议
	if (sock == INVALID_SOCKET)
	{
		cout << endl << "创建Socket失败!" << endl;
		closesocket(sock);
		WSACleanup();
	}

	/*
	BOOL flag=TRUE;
	if(setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char *) &flag,sizeof(flag))==SOCKET_ERROR)
	{
	cout<<endl<<"setsockopt操作失败:"<<WSAGetLastError()<<endl;
	closesocket(sock);
	WSACleanup();

	}
	*/

	char hostName[128]; //获取主机名 
	if (gethostname(hostName, 128) == SOCKET_ERROR)
	{
		cout << endl << "gethostname操作失败:" << WSAGetLastError() << endl;
		closesocket(sock);
		WSACleanup();

	}

	hostent* pHostIP; //获取本地IP
	if ((pHostIP = gethostbyname(hostName)) == NULL)
	{
		cout << endl << "gethostbyname操作失败:" << WSAGetLastError() << endl;
		closesocket(sock);
		WSACleanup();
	}

	sockaddr_in host_addr; //绑定到本机套接字
	host_addr.sin_family = AF_INET;
	host_addr.sin_port = htons(9003);
	host_addr.sin_addr = *(in_addr*)pHostIP->h_addr_list[0];
	if (bind(sock, (PSOCKADDR)&host_addr, sizeof(host_addr)) == SOCKET_ERROR)
	{
		cout << endl << "bind操作失败:" << WSAGetLastError() << endl;
		closesocket(sock);
		WSACleanup();
	}

	DWORD dwBufferLen[10]; //修改本机套接字类型,以接受所有数据
	DWORD dwBufferInLen = 1;
	DWORD dwBytesReturned = 0;
	if (WSAIoctl(sock, IO_RCVALL, &dwBufferInLen, sizeof(dwBufferInLen), &dwBufferLen, sizeof(dwBufferLen), &dwBytesReturned, NULL, NULL) == SOCKET_ERROR)
	{
		cout << endl << "WSAIoctl操作失败:" << WSAGetLastError() << endl;
		closesocket(sock);
		WSACleanup();
	}


	cout << endl << "开始解析IP包:" << endl;
	char buffer[65535]; //设置缓冲区
	//int packsum=atoi("3"); //字符串转换为整形
	while(1)
	{
		if (recv(sock, buffer, 65535, 0) > 0) //四个参数分别是套接字描述符,缓冲区的地址,缓冲区大小,附加标志
		{
			dec(cout);
			ip_head ip = *(ip_head*)buffer;
			cout << "-----------------------" << endl;
			cout << "版本:" << (ip.Version >> 4) << endl; //要右移4位获取头部长度字段,第一个char的高四位bit存放version。当前是IPv4。第一个char的低四位bit存放报头长度,它指出了按32   bit   长标定的报头长度,报头的实际长度是   h_len   <<   2   。如果报头长度不是32   bit   的整数倍,则由填充域添0补充。
			cout << "头部长度:" << ((ip.HeadLen & 0x0f) * 4) << endl; //获取头部长度字段按32bit为一单位,故要乘以4
			cout << "服务类型:Priority" << (ip.ServiceType >> 5) << ", Service" << ((ip.ServiceType >> 1) & 0x0f) << endl;
			cout << "总长度:" << ntohs(ip.TotalLen) << endl;//获取总长度字段 
			cout << "标识符:" << ntohs(ip.Identifier) << endl;//获取标识字段 
			cout << "标志位:" << ((ip.Flags >> 15) & 0x01) << ",DF= " << ((ip.Flags >> 14) & 0x01) << ",Mf=" << ((ip.Flags >> 13) & 0x01) << endl; //获得标志字段
			cout << "片偏移:" << (ip.FragOffset & 0x1fff) << endl; //获取分段偏移字段
			cout << "生存周期:" << (int)ip.TimeToLive << endl; //获取生存时间字段
			cout << "协议:Protocol" << (int)ip.Protocol << endl; //获取协议字段
			cout << "头部校验和:" << hex << ntohs(ip.HeadChecksum) << hex << endl; //获取头校验和字段
			cout << "原地址:" << inet_ntoa(*(in_addr*)&ip.SourceAddr) << endl; //获取源IP地址字段
			cout << "目的IP地址:" << inet_ntoa(*(in_addr*)&ip.DestinAddr) << endl; //获取目的IP地址字段

			char str[100];
			int is = 128;
			//cout << "版本:" << itoa(is, str, 2) << endl; //要右移4位获取头部长度字段,第一个char的高四位bit存放version。当前是IPv4。第一个char的低四位bit存放报头长度,它指出了按32   bit   长标定的报头长度,报头的实际长度是   h_len   <<   2   。如果报头长度不是32   bit   的整数倍,则由填充域添0补充。
			/*cout<<"头部长度:"<<ip.HeadLen<<endl; //获取头部长度字段按32bit为一单位,故要乘以4
			cout<<"服务类型:"<<ip.ServiceType<<", Service"<<ip.ServiceType<<endl;
			cout<<"总长度:"<<ip.TotalLen<<endl;//获取总长度字段
			cout<<"标识符:"<<ip.Identifier<<endl;//获取标识字段
			cout<<"标志位:"<<ip.Flags<<endl; //获得标志字段
			cout<<"片偏移:"<<ip.FragOffset<<endl; //获取分段偏移字段
			cout<<"生存周期:"<<(int)ip.TimeToLive<<endl; //获取生存时间字段
			cout<<"协议:Protocol"<<(int)ip.Protocol<<endl; //获取协议字段
			cout<<"头部校验和:"<<ip.HeadChecksum<<endl; //获取头校验和字段
			cout<<"原地址:"<<inet_ntoa(*(in_addr *)&ip.SourceAddr)<<endl; //获取源IP地址字段
			cout<<"目的IP地址:"<<inet_ntoa(*(in_addr *)&ip.DestinAddr)<<endl; //获取目的IP地址字段
			*/
			outfile << "-----------------------" << endl;
			dec(outfile);
			outfile << "版本:" << (ip.Version >> 4) << endl;
			outfile << "头部长度:" << ((ip.HeadLen & 0x0f) * 4) << endl;
			outfile << "服务类型:Priority" << (ip.ServiceType >> 5) << ", Service" << ((ip.ServiceType >> 1) & 0x0f) << endl;
			outfile << "总长度:" << ntohs(ip.TotalLen) << endl;
			outfile << "标识符:" << ntohs(ip.Identifier) << endl;
			outfile << "标志位:" << ((ip.Flags >> 15) & 0x01) << ",DF= " << ((ip.Flags >> 14) & 0x01) << ",Mf=" << ((ip.Flags >> 13) & 0x01) << endl;
			outfile << "片偏移:" << (ip.FragOffset & 0x1fff) << endl;
			outfile << "生存周期:" << (int)ip.TimeToLive << endl;
			outfile << "协议:Protocol" << (int)ip.Protocol << endl;
			outfile << "头部校验和:" << hex << ntohs(ip.HeadChecksum) << endl;
			outfile << "原地址:" << inet_ntoa(*(in_addr*)&ip.SourceAddr) << endl;
			outfile << "目的IP地址:" << inet_ntoa(*(in_addr*)&ip.DestinAddr) << endl;
		}
	}

	closesocket(sock);
	WSACleanup();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/84976.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RocketMQ的事务消息是如何实现的?

RocketMQ的事务消息实现方法如下&#xff1a; 1、首先生产者订单系统先发送⼀条half消息到Broker&#xff0c;half消息对消费者而⾔是不可⻅的 2、再创建订单&#xff0c;根据创建订单成功与否&#xff0c;向Broker发送commit或rollback 3、并且⽣产者订单系统还可以提供Broker…

Spark 3.0 - 11.ML 随机森林实现二分类实战

目录 一.引言 二.随机森林实战 1.数据预处理 2.随机森林 Pipeline 3.模型预测与验证 三.总结 一.引言 之前介绍了 决策树 &#xff0c;而随机森林则可以看作是多颗决策树的集合。在 Spark ML 中&#xff0c;随机森林中的每一颗树都被分配到不同的节点上进行并行计算&…

Crack:Aspose.3D for .NET 22.11.X

Aspose.3D for .NETAspose.3D for .NET 是一个功能丰富的游戏软件和计算机辅助设计 (CAD) API&#xff0c;无需任何 3D 建模和渲染软件依赖即可操作文档。API 支持 Discreet3DS、WavefrontOBJ、FBX&#xff08;ASCII、二进制&#xff09;、STL&#xff08;ASCII、二进制&#x…

[附源码]Nodejs计算机毕业设计基于web的家教管理系统Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分…

linux信号:SIGINT、SIGKILL、SIGSTOP、SIGCONT

目录 1. SIGINT 2. SIGKILL 3. SIGSTOP与SIGCONT 简介 SignalStandardActionCommentSIGINTP1990TermInterrupt form keybordSIGKILLP1990TermKill signalSIGSTOPP1990TermInterrupt form keybord1. SIGINT 我们在shell交互式进程中常用的ctrl c 就是对当前运行的程序进行…

[附源码]Node.js计算机毕业设计电影票网上订票系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

2022年山东食品安全管理员模拟试题及答案

百分百题库提供食品安全管理员考试试题、食品安全管理员考试预测题、食品安全管理员考试真题、食品安全管理员证考试题库等&#xff0c;提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 一、单选题 1.下列哪项措施与保证食品安全无关&#xff1f; A…

2022gwb_web3

可以通过反序列化出一个 Webclome 类从而任意构造原生类&#xff0c;但只能调用 getSize 方法获取文件或目录 的大小&#xff0c;试了试直接拿根目录的 /flag 就别想了&#xff0c;先看看网站目录有没有藏什么东西&#xff08;扫目录什么也扫 不出来&#xff09;&#xff0c;EX…

再学C语言2:概览

重新把C语言梳理一遍&#xff0c;学习在VSCode中进行C语言编程 一、C语言起源 1972年&#xff0c;贝尔实验室的Dennis Ritchie在C语言的基础上设计出一种新的语言&#xff0c;即C语言 C是作为从事实际编程工作的程序员的一种工具儿出现&#xff0c;是为编程人员开发的语言 二…

【脚本项目源码】Python制作桌面宠物,这么可爱的萌宠你不想拥有吗?

前言 本文给大家分享的是如何通过利用Python制作桌面宠物&#xff0c;废话不多直接开整~ 开发工具 Python版本&#xff1a; 3.6 相关模块&#xff1a; random模块 os模块 cfg模块 sys模块 PyQt5模块 环境搭建 安装Python并添加到环境变量&#xff0c;pip安装需要的相…

skynet设计原理和使用

skynet设计原理一、多核并发编程方式二、skynet2.1、skynet简介2.2、环境准备2.3、编译安装2.4、Actor 模型2.5、消息队列2.6、actor公平调度三、skynet的使用3.1、第一个skynet程序3.2、skynet网络消息3.3、skynet定时消息3.4、skynet actor间消息四、vscode调试skynet总结后言…

Python比较难的知识点: 迭代器与生成器

迭代器与生成器是Python比较难的知识点, 在学Python之前, 我已经有了多年的C语言与MATLAB的使用经验了, 但是学这些知识点, 还是有一定的困难, 总觉得是一知半解的. 现在, 经过一段时间的学习和梳理, 感觉是搞懂了, 写下这篇文章与大家分享. 学习具体概念技术之前, 得知道这些…

c++ - 第17节 - AVL树和红黑树

1.AVL树 1.1.AVL树的概念 二叉搜索树虽可以缩短查找的效率&#xff0c;但如果数据有序或接近有序二叉搜索树将退化为单支树&#xff0c;查找元素相当于在顺序表中搜索元素&#xff0c;效率低下。因此&#xff0c;两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发…

Mybatis:MyBatis的逆向工程(10)

Mybaits笔记框架&#xff1a;https://blog.csdn.net/qq_43751200/article/details/128154837 Mybatis中文官方文档&#xff1a; https://mybatis.org/mybatis-3/zh/index.html Mybati的逆向工程1. 正向工程 VS 逆向工程2. 创建逆向工程的步骤&#xff08;MyBatis3Simple清新简洁…

Go 1.20要来了,看看都有哪些变化-第1篇

前言 Go官方团队在2022.12.08发布了Go 1.20 rc1(release candidate)版本&#xff0c;Go 1.20的正式release版本预计会在2023年2月份发布。 让我们先睹为快&#xff0c;看看Go 1.20给我们带来了哪些变化。(文末有彩蛋&#xff01;) 安装方法&#xff1a; $ go install golan…

[附源码]Nodejs计算机毕业设计基于web的火车订票管理系统Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分…

阅读器消退之际:文石造产品,掌阅塑生态

配图来自Canva可画 阅读器正在变得小众&#xff0c;似乎自Kindle以来营造的那种“阅读的生活方式”&#xff0c;已经被证明是一个伪命题&#xff1a;会阅读的人&#xff0c;无论如何都会去阅读&#xff1b;不会阅读的人&#xff0c;阅读器的归宿终究是一个“泡面盖”。于是&am…

Android原生项目接入flutter_boost4.0

折腾了好几天&#xff0c;经验思维导致的&#xff0c;记录一下踩坑。 官方接入步骤官方文档 接入原生&#xff0c;就3个步骤&#xff0c;我都能折腾好久&#xff0c;浪费时间。 flutter部分很简单&#xff0c;按文档配置就行&#xff0c;在pubspec.yaml依赖就好了。 &#…

Ceph性能瓶颈分析与优化(混合盘篇)

原文链接: Ceph性能瓶颈分析与优化(混合盘篇) - 知乎背景ssdhdd的混合盘场景在各个存储厂商中算是一种典型应用场景。 但是经过测试(4k随机写)发现&#xff0c;加了nvme ssd做ceph的wal和db后&#xff0c;性能提升仅一倍以内且nvme盘性能余量较大。所以希望通过对问题瓶颈进行…

目标检测数据标注案例-高清地图中障碍物(汽车)标注

计算机视觉在无人机中领域中有何作用? 无人机能够在空中识别、分类和追踪目标。无人机的摄像头和感应器可以捕获数据并进行分析&#xff0c;以提取重要信息。 AI可以自动提取视觉数据信息&#xff0c;准确识别、说明和追踪图像和视频中的目标。例如高空检测工作&#xff0c;…