TCP/IP 网络嗅探器开发实例

news2024/11/15 8:47:36

主要内容

实例使用环境

知识储备

IP数据报格式

IP头结构体定义

TCP头格式

TCP头结构体定义

实例的调用演示

 实例的完整代码

initsock.h

protoinfo.h文件 

 Sniffer.cpp文件

实例总结

基于原始套接字的网络封包嗅探的工作过程

Sniffer节点调用分析

在Visual Studio2019 的调用事项

问题一:程序的打开问题

问题二:解决编译器的C4996代码问题


主要内容

1,了解利用原始套接字进行通信程序的编写,编译和执行。

2,利用原始套接字编程将网卡设置为混杂模式,对局域网(自组网/机房网络/宿舍网络或其他)上传输的数据包进行捕获与分析;

3,能分析出捕获的IP数据包的生存时间、协议、头部校验和、源IP地址以及目标IP地址等内容。并将上述解析结果规范显示出来。

实例使用环境

操作系统:  Microsoft Windows 11

编程环境:  Visual Studio 2019


知识储备

IP数据报格式

IP数据报格式

IP头结构体定义

IP头结构体
typedef struct _IPHeader         // 20字节的IP头
{
    UCHAR     iphVerLen;         // 4位首部长度+4位IP版本号           
    UCHAR     ipTOS;             // 8位服务类型                       
    USHORT    ipLength;          // 16位封包总长度,即整个IP报的长度  
    USHORT    ipID;              // 16位封包标识,惟一标识发送的每一个数据报 
    USHORT    ipFlags;           // 3位标志位+13报片偏移 
    UCHAR     ipTTL;             // 8位生存时间,就是TTL              
    UCHAR     ipProtocol;        // 8位协议,TCP、UDP、ICMP等         
    USHORT    ipChecksum;        // 16位IP首部校验和              
    ULONG     ipSource;          // 32位源IP地址                 
    ULONG     ipDestination;     // 32位目标IP地址                    
} IPHeader, * PIPHeader;

 

TCP头格式

TCP包头格式

TCP头结构体定义

typedef struct _TCPHeader       // 20字节的TCP头
{
    USHORT sourcePort;          // 16位源端口号    
    USHORT destinationPort;     // 16位目的端口号 
    ULONG sequenceNumber;       // 32位序列号     
    ULONG acknowledgeNumber;    // 32位确认号    
    UCHAR   dataoffset;         // 高4位表示数据偏移,低6位保留字 
    UCHAR   flags;              // 6位标志位       
    USHORT windows;             // 16位窗口大小    
    USHORT checksum;            // 16位校验和      
    USHORT urgentPointer;       // 16位紧急数据偏移量   
} TCPHeader, * PTCPHeader;

 


实例的调用演示

程序成功绑定了本机的IP地址(注意不能是任意)

程序尝试嗅探主机中的IP数据封包,并成功解析出源IP地址以及目标IP地址,协议及对应端口等内容。


 实例的完整代码

initsock.h

#include <winsock2.h>
#pragma comment(lib, "WS2_32")	// 链接到WS2_32.lib

class CInitSock
{
public:
	CInitSock(BYTE minorVer = 2, BYTE majorVer = 2)
	{
		// 初始化WS2_32.dll
		WSADATA wsaData;
		WORD sockVersion = MAKEWORD(minorVer, majorVer);
		if (::WSAStartup(sockVersion, &wsaData) != 0)
		{
			exit(0);
		}
	}
	~CInitSock()
	{
		::WSACleanup();
	}
};

protoinfo.h文件 

// protoinfo.h文件

/*

定义协议格式
定义协议中使用的宏

 */
#ifndef __PROTOINFO_H__
#define __PROTOINFO_H__


#define ETHERTYPE_IP    0x0800
#define ETHERTYPE_ARP   0x0806

typedef struct _ETHeader         // 14字节的以太头
{
	UCHAR	dhost[6];			// 目的MAC地址destination mac address
	UCHAR	shost[6];			// 源MAC地址source mac address
	USHORT	type;				// 下层协议类型,如IP(ETHERTYPE_IP)、ARP(ETHERTYPE_ARP)等
} ETHeader, * PETHeader;


#define ARPHRD_ETHER 	1

// ARP协议opcodes
#define	ARPOP_REQUEST	1		// ARP 请求	
#define	ARPOP_REPLY		2		// ARP 响应


typedef struct _ARPHeader		// 28字节的ARP头
{
	USHORT	hrd;				//	硬件地址空间,以太网中为ARPHRD_ETHER
	USHORT	eth_type;			//  以太网类型,ETHERTYPE_IP ??
	UCHAR	maclen;				//	MAC地址的长度,为6
	UCHAR	iplen;				//	IP地址的长度,为4
	USHORT	opcode;				//	操作代码,ARPOP_REQUEST为请求,ARPOP_REPLY为响应
	UCHAR	smac[6];			//	源MAC地址
	UCHAR	saddr[4];			//	源IP地址
	UCHAR	dmac[6];			//	目的MAC地址
	UCHAR	daddr[4];			//	目的IP地址
} ARPHeader, * PARPHeader;


// 协议
#define PROTO_ICMP    1
#define PROTO_IGMP    2
#define PROTO_TCP     6
#define PROTO_UDP     17

typedef struct _IPHeader		// 20字节的IP头
{
	UCHAR     iphVerLen;      // 版本号和头长度(各占4位)
	UCHAR     ipTOS;          // 服务类型 
	USHORT    ipLength;       // 封包总长度,即整个IP报的长度
	USHORT    ipID;			  // 封包标识,惟一标识发送的每一个数据报
	USHORT    ipFlags;	      // 标志
	UCHAR     ipTTL;	      // 生存时间,就是TTL
	UCHAR     ipProtocol;     // 协议,可能是TCP、UDP、ICMP等
	USHORT    ipChecksum;     // 校验和
	ULONG     ipSource;       // 源IP地址
	ULONG     ipDestination;  // 目标IP地址
} IPHeader, * PIPHeader;


// 定义TCP标志
#define   TCP_FIN   0x01
#define   TCP_SYN   0x02
#define   TCP_RST   0x04
#define   TCP_PSH   0x08
#define   TCP_ACK   0x10
#define   TCP_URG   0x20
#define   TCP_ACE   0x40
#define   TCP_CWR   0x80

typedef struct _TCPHeader		// 20字节的TCP头
{
	USHORT	sourcePort;			// 16位源端口号
	USHORT	destinationPort;	// 16位目的端口号
	ULONG	sequenceNumber;		// 32位序列号
	ULONG	acknowledgeNumber;	// 32位确认号
	UCHAR	dataoffset;			// 高4位表示数据偏移
	UCHAR	flags;				// 6位标志位
	//FIN - 0x01
	//SYN - 0x02
	//RST - 0x04 
	//PUSH- 0x08
	//ACK- 0x10
	//URG- 0x20
	//ACE- 0x40
	//CWR- 0x80

	USHORT	windows;			// 16位窗口大小
	USHORT	checksum;			// 16位校验和
	USHORT	urgentPointer;		// 16位紧急数据偏移量 
} TCPHeader, * PTCPHeader;

typedef struct _UDPHeader
{
	USHORT			sourcePort;		// 源端口号		
	USHORT			destinationPort;// 目的端口号		
	USHORT			len;			// 封包长度
	USHORT			checksum;		// 校验和
} UDPHeader, * PUDPHeader;

#endif // __PROTOINFO_H__

 Sniffer.cpp文件

// Sniffer.cpp文件
#pragma warning(disable:4996)
#include "initsock.h"
#include "protoinfo.h" 

#include <stdio.h>
#include <mstcpip.h>

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

CInitSock theSock;

void DecodeTCPPacket(char* pData)
{
	TCPHeader* pTCPHdr = (TCPHeader*)pData;

	printf(" Port: %d -> %d \n", ntohs(pTCPHdr->sourcePort), ntohs(pTCPHdr->destinationPort));

	// 下面还可以根据目的端口号进一步解析应用层协议
	switch (::ntohs(pTCPHdr->destinationPort))
	{
	case 21:
		break;
	case 80:
	case 8080:
		break;
	}
}

void DecodeIPPacket(char* pData)
{
	IPHeader* pIPHdr = (IPHeader*)pData;
	in_addr source, dest;
	char szSourceIp[32], szDestIp[32];

	printf("\n\n-------------------------------\n");

	// 从IP头中取出源IP地址和目的IP地址
	source.S_un.S_addr = pIPHdr->ipSource;
	dest.S_un.S_addr = pIPHdr->ipDestination;
	strcpy(szSourceIp, ::inet_ntoa(source));
	strcpy(szDestIp, ::inet_ntoa(dest));

	printf("	%s -> %s \n", szSourceIp, szDestIp);
	// IP头长度
	int nHeaderLen = (pIPHdr->iphVerLen & 0xf) * sizeof(ULONG);

	switch (pIPHdr->ipProtocol)
	{
	case IPPROTO_TCP: // TCP协议
		DecodeTCPPacket(pData + nHeaderLen);
		break;
	case IPPROTO_UDP:
		break;
	case IPPROTO_ICMP:
		break;
	}
}


void main()
{
	// 创建原始套节字
	SOCKET sRaw = socket(AF_INET, SOCK_RAW, IPPROTO_IP);

	// 获取本地IP地址
	char szHostName[56];
	SOCKADDR_IN addr_in;
	struct  hostent* pHost;
	gethostname(szHostName, 56);
	if ((pHost = gethostbyname((char*)szHostName)) == NULL)
		return;

	// 在调用ioctl之前,套节字必须绑定
	addr_in.sin_family = AF_INET;
	addr_in.sin_port = htons(0);
	memcpy(&addr_in.sin_addr.S_un.S_addr, pHost->h_addr_list[0], pHost->h_length);

	printf(" Binding to interface : %s \n", ::inet_ntoa(addr_in.sin_addr));
	if (bind(sRaw, (PSOCKADDR)&addr_in, sizeof(addr_in)) == SOCKET_ERROR)
		return;

	// 设置SIO_RCVALL控制代码,以便接收所有的IP包	
	DWORD dwValue = 1;
	if (ioctlsocket(sRaw, SIO_RCVALL, &dwValue) != 0)
		return;

	// 开始接收封包
	char buff[1024];
	int nRet;
	while (TRUE)
	{
		nRet = recv(sRaw, buff, 1024, 0);
		if (nRet > 0)
		{
			DecodeIPPacket(buff);
		}
	}
	closesocket(sRaw);
}

实例总结

基于原始套接字的网络封包嗅探工作过程

使用原始套接字写嗅探器的流程:

1 使用socket创建基于IP协议的原始套接字。

2 获取本地IP地址。

3 将原始套接字绑定到本地IP地址上。

4 使用ioctlsocket函数设置套接字选项SIO_RCVALL,即接受所有数据。

5 无尽调用recv函数。

Sniffer节点调用分析

    通常的套接字程序只能响应与自己MAC地址相匹配的或是以广播形式发出的数据帧,对于其他形式的数据帧网络接口采取的动作是直接丢弃。为了使网卡接收所有经过它的封包,要将其设置为混杂模式。

    程序运行之后,首先要创建原始套接字,将它绑定到一个明确的本地地址(不能为ADDR_ANY),然后设置SIO_RCVALL控制代码,最后进入无限循环,不断调用recv函数接收经过本地网卡的IP封包。

    程序接收到IP封包之后,调用自定义函数DecodeIPPaccket进行解包。这个函数萃取出封包中的协议头,向用户打印出协议信息,本次实验Sniffer程序仅解析了封包中的IP头和TCP头

在Visual Studio2019 的调用事项

问题一:程序的打开问题

由于网络嗅探器程序需要较高的使用权限,所以要以编译器要以管理员的身份打开使用。

问题二:解决编译器的C4996代码问题

由于代码样例的使用规则与现行的编译器的代码定义规则(安全性过高)存在不兼容的问题,在尝试过许多方法后,尝试解决思路如下:

如果都没很好的解决问题,最后只能输入#pragma warning(disable:4996)强制忽略掉C4996所带来的警告程序恢复了正常运行。

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

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

相关文章

[附源码]计算机毕业设计基于springboot的高校车辆租赁管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

组合设计模式

一、组合模式 1、定义 组合模式&#xff08;Composite Pattern&#xff09;又称作整体-部分&#xff08;Part-Whole&#xff09;模式&#xff0c;其宗旨是通过将单个对象&#xff08;叶子节点&#xff09;和组织对象&#xff08;树枝节点&#xff09;用相同的接口进行表示&…

Egg 1. 快速开始 Quick Start 1.3 一步步 Step by Step 1.3.6 添加扩展 ~ 1.4 结论

Egg Egg 本文仅用于学习记录&#xff0c;不存在任何商业用途&#xff0c;如侵删 文章目录Egg1. 快速开始 Quick Start1.3 一步步 Step by Step1.3.6 添加扩展1.3.7 添加中间件1.3.8 添加配置1.3.9 添加单元测试1.4 结论1. 快速开始 Quick Start 1.3 一步步 Step by Step 1.3.…

求矩阵的行列式和逆矩阵 det()和inv()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 求矩阵的行列式和逆矩阵 det()和inv() [太阳]选择题 请问对以下Python代码说法错误的是&#xff1f; import numpy as np A np.array([[0,1],[2,3]]) print ("【显示】矩阵A") pr…

HedgeDoc的反向代理设置

因为 HedgeDoc 支持协同&#xff0c;所以很大可能性需要做反向代理设置&#xff0c;来让更多的人参与&#xff0c;但在上文 『Markdown协作编辑平台HedgeDoc』 中&#xff0c;老苏并未涉及到这部分&#xff0c;本文就是做这方面的补充。 老苏只研究了 nginx proxy manager 做反…

22个Vue 源码中的工具函数

前言 在 vue 源码中&#xff0c;封装了很多工具函数&#xff0c;学习这些函数&#xff0c;一方面学习大佬们的实现方式&#xff0c;另一方面是温习基础知识&#xff0c;希望大家在日常工作中&#xff0c;简单的函数也可以自己封装&#xff0c;提高编码能力。 本次涉及的工具函…

力扣(LeetCode)130. 被围绕的区域(C++)

dfs 只有和边界相连的 OOO 不会被 XXX 包围。遍历边界&#xff0c;搜索边界 OOO 的连通块&#xff0c;标记这些连通块。最后一次遍历矩阵&#xff0c;将标记的格子改回 OOO &#xff0c;其他格子改成 XXX &#xff0c;即为所求。 提示 : 可以用数组标记连通块&#xff0c;也可…

Java基于springboot+vue药店实名制买药系统 前后端分离

开发背景和意义 药品一直以来在人类生活中扮演着非常重要的角色&#xff0c;随着时代的发展&#xff0c;人们基本已经告别了那个缺医少药的年代&#xff0c;各大药房基本随处可以&#xff0c;但是很多时候因为没有时间或者在药店很难找到自己想要购买的药品&#xff0c;所以很…

元宇宙产业委叶毓睿:狂欢过后,万众期待的元宇宙怎么样了?

叶毓睿&#xff08;王学民/摄&#xff09; 自元宇宙出现在大众视野&#xff0c;大众对元宇宙的好奇和探索&#xff0c;从来没有停止过。当元宇宙的热度逐渐下降&#xff0c;我们不禁想要知道&#xff0c;狂欢过后&#xff0c;万众期待的元宇宙怎么样了&#xff1f; 近日&#x…

【吴恩达机器学习笔记】十一、聚类

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?spm1011.2415.3001.5343 &#x1f4e3;专栏定位&#xff1a;为学习吴恩达机器学习视频的同学提供的随堂笔记。 &#x1f4da;专栏简介&#xff1a;在这个专栏&#xff0c;我将整理吴恩达机器学习视频的所有内容的笔记&…

算法刷题入门线性表|单调栈

一、概念 1、栈的定义 栈 是仅限在 一端 进行 插入 和 删除 的 线性表。 栈 又被称为 后进先出 (Last In First Out) 的线性表&#xff0c;简称 LIFO 。 2、栈顶 栈 是一个线性表&#xff0c;我们把允许 插入 和 删除 的一端称为 栈顶。 3、栈底 和 栈顶 相对&#xff0c;另一端…

java计算机毕业设计ssm软件学院社团管理系统l62lq(附源码、数据库)

java计算机毕业设计ssm软件学院社团管理系统l62lq&#xff08;附源码、数据库&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#…

[附源码]计算机毕业设计基于SpringBoot+Vue的健身房会员系统的设计与实现

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Linux系统( Centos 7) 配置与管理Apache服务器实例详细步骤

Linux系统&#xff08; Centos 7&#xff09; 配置与管理Apache服务器实例详细步骤 服务器centos7-1 1.配置网络。 [rootcentos7 ~]# vim /etc/sysconfig/network-scripts/ifcfg-ens33 TYPEEthernet PROXY_METHODnone BROWSER_ONLYno BOOTPROTOstatic DEFROUTEyes IPV…

【WPF】附加事件

【WPF】附加事件什么是附加事件附加事件用法Microsoft 官方文档附加事件案例定义自定义控件注册使用附加事件什么是附加事件 Microsoft 官方概述&#xff1a;   附加事件可用于在非元素类中定义新的 路由事件 &#xff0c;并在树中的任何元素上引发该事件。 为此&#xff0c;…

【WebRTC】拥塞控制 GCC 类图

GoogCcNetworkController : 整个 congestion_controller 模块的中心类&#xff0c;是对外的接口 AcknowledgedBitrateEstimatorInterface AcknowledgedBitrateEstimator : 估算当前的吞吐量。 BitrateEstimator : 使用滑动窗口 卡尔曼滤波计算当前发送吞吐量。 RobustThro…

【Android App】实战项目之仿拼多多的直播带货(附源码和演示 超详细必看)

需要源码请点赞关注收藏后评论区留言私信~~~ 近年来电商业态发生了不小的改变&#xff0c;传统的电商平台把商品分门别类&#xff0c;配上精美的图文说明供消费者挑选&#xff0c;新潮的电商平台则请来明星网红&#xff0c;开启直播秀向广大粉丝推销商品&#xff0c;往往一场直…

微服务应对雪崩的容错方案

引言 书接上篇 微服务绕不过的坎-服务雪崩 &#xff0c;玩微服务不可避免的问题&#xff1a;服务雪崩&#xff0c;那为了应付服务雪崩问题&#xff0c;需要做啥预防性操作呢&#xff1f;答案是&#xff1a;做好容错保护 容错方案 前面说了&#xff0c;要防止雪崩的扩散&…

[附源码]计算机毕业设计springboot疫情期间小学生作业线上管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Android自定义视图

View 自定义视图主要涉及四个方面&#xff1a;绘图、交互、性能和封装 绘图 主要涉及两个对象&#xff1a;画布&#xff08;Canvas&#xff09;和画笔&#xff08;Paint&#xff09;&#xff0c;画布主要解决画什么的问题&#xff0c;在画布上可以绘制各种各样的图形&#x…