ICMP(Ping)功能原理及其C++实现简介

news2024/9/24 17:18:19

ICMP(Ping)功能原理及其应用简介

一、 Ping功能简介

1、 原始套接字(Raw Socket)

原始套接字(‌Raw Socket)‌是一种特殊的网络编程接口,‌它允许直接接收和发送网络层的数据包,‌而不是通过传输层。‌这种套接字可以接收本机网卡上的数据帧或者数据包,‌对于监听网络的流量和分析网络数据非常有用。

Ping属于原始套接字的应用。

2 、 ICMP帧简介

① 、帧结构
|    8bit    |    8bit    |        16bit        |   
|____________|____________|_____________________|______
|            |            |                     ||    Type    |    Code    |      Checksum       |  ICMP首部
|            |            |                     ||____________|____________|_____________________|______
|                                               ||                     Data                      |  ICMP数据 
|                                               ||_______________________________________________|______
                 #ICMP协议报文结构(标准)


|    8bit    |    8bit    |        16bit        |   
|____________|____________|_____________________|______
|    Type    |    Code    |      Checksum       ||____________|____________|_____________________|  ICMP首部
|       Identifier        |   Sequence Number   ||_________________________|_____________________|______
|                                               || 可选数据区: 请求报文方发送,应答方重复报文内容  |  ICMP数据 
|                                               ||_______________________________________________|______
            #ICMP协议常用的请求与请求响应结构(ping)
② 、 常用Type、Code 字段含义
Type(类型)Code (代码)内容
00回送应答(Echo Reply)
30网络不可达
31主机不可达
32协议不可达
33端口不可达
34需要进行分片,但设置为不分片
35源站选路失败
36目的网络不认识
37目的主机不认识
39目标网络被强制禁止
310目标主机被强制禁止
311由于TOS,网络不可达
312由于TOS,主机不可达
313由于过滤,通信被强制禁止
314主机越权
315优先权终止生效
40源端被关闭
50对网络重定向
51对主机重定向
52对服务类型和网络重定向
53对服务类型和主机重定向
80请求应答(Ping 请求)
90路由器通告
100路由器请求通告
110传输期间生存时间为0
120坏的IP首部
121缺少必要的选项
170地址掩码请求
180地址掩码应答
③ 、Checksum校验和

对于ICMP协议校验和计算方式,参考RFC官方文档给出的说明:

The checksum is the 16-bit ones's complement of the one's
complement sum of the ICMP message starting with the ICMP Type.
For computing the checksum , the checksum field should be zero.
If the total length is odd, the received data is padded with one
octet of zeros for computing the checksum.  This checksum may be
replaced in the future.

步骤如下:

一、获取ICMP报文(首部+数据部分)

二、将ICMP报文中的校验和字段置为0。

三、将ICMP协议报文中的每两个字节(16位,需要注意大小端问题)两两相加,得到一个累加和。若报文长度为奇数,则最后一个字节(8-bit)  作为高8位,再用0填充一个字节(低8-bit)扩展到16-bit,之后再和前面的累加和继续相加得到一个新的累加和。

四、(若有溢出)将累加和的高16位和低16位相加,直到最后只剩下16位。

五、将最后得到的16位结果取反(按位取反)作为校验和的值。

ICMP协议校验和计算代码示例

/**                                                            
 * icmp_checksum:
 * @size: the icmp data packet length
 * @icmp_data: icmp protocol packet both header and data
 *
 * Calc icmp's checksum:
 * if we divide the ICMP data packet is 16 bit words and sum each of them up
 * then hihg 16bit add low 16bit to sum get a value,  
 * If the total length is odd, 
 * the last byte is padded with one octet of zeros for computing the checksum.
 * Then hihg 16bit add low 16bit to sum get a value,
 * finally do a one's complementing 
 * then the value generated out of this operation would be the checksum.
 * 
 * Return: unsigned short checksum
 */
unsigned short icmp_checksum(char * icmp_packet, int size)
{
 	unsigned short * sum = (unsigned short *)icmp_packet;
 	unsigned int checksum = 0;
 	while (size > 1)
    {
  		checksum += ntohs(*sum++);
  		size -= sizeof(unsigned short);
	 }
 	
    if (size) 
    {
  		*sum = *((unsigned char*)sum);
		  checksum += ((*sum << 8) & 0xFF00);
	 }
 
 	checksum = (checksum >> 16) + (checksum & 0xffff);
 	checksum += checksum >> 16;
 
 	return (unsigned short)(~checksum);
}

校验和计算示例

ICMP协议的ping回送响应报文(大端)为例:

0x08 0x00 0xeb 0xc9 0x00 0x0e 0x00  0x1f 0x00 0x01 0x02 0x03 0x04 0x05 0x06 
  1. 先将ICMP协议的校验和字段置为0
0x08 0x00 0x00 0x00 0x00 0x0e 0x00 0x1f 0x00 0x01 0x02 0x03 0x04 0x05 0x06 
  1. ICMP协议报文中的每两个字节(16位)(需要注意大小端问题,网络字节序是大端模式,如0xebc9, 对于小端主机来说,组成的是0xc9eb,应转化为主机字节序:0xebc9)两两相加,得到一个累加和。若报文长度为奇数,则最后一个字节(8-bit)作为高8位,再用0填充一个字节(低8-bit)扩展到16-bit,之后再和前面的累加和继续相加得到一个新的累加和。
0x0800 + 0x0000 + 0x000e + 0x001f + 0x0001+ 0x0203 + 0x0405 + 0x0600 = 0x1436
  1. 将累加和的高16位和低16位相加,直到最后只剩下16位
0x0000 + 0x1436 = 0x1436
  1. 将最后得到的16位结果取反(按位取反)作为校验和字段的值
0001 0100 0011 0110 (0x1436 取反)
1110 1011 1100 1001 (0xebc9)

3、 Ping帧抓包分析

① 、 Linux系统

Linux系统上,ICMP 数据部分会携带当前时间戳,然后数据内容是从10开始填充。

Ping请求

在这里插入图片描述

Ping响应

在这里插入图片描述

② 、 Windows系统

Windows系统上,ICMP 数据内容是从61asciia)开始填充。

Ping请求

在这里插入图片描述

Ping响应

在这里插入图片描述

4、往返时间和TTL

当返回ICMP回显应答时,要打印出序列号和TTL,并计算往返时间。TTL位于IP首部的生存时间字段。ping程序通过在ICMP报文数据字段中存放发送请求的时间值来计算往返时间。当应答返回时,用当前时间减去存放在ICMP报文中的时间值,即是往返时间。

①、 TTL

TTL(‌Time to Live)‌值表示IP数据包在网络中的最大生存时间,‌即数据包在网络中存在的时间长度。‌TTL值由IP数据包的发送者设置,‌并且在IP数据包从源到目的地的整个转发路径上,‌每经过一个路由器,‌路由器都会将TTL字段的值减1。‌如果IP包的TTL值在到达目的IP之前减少为0,‌路由器将会丢弃该IP包并向IP包的发送者发送ICMP time exceeded消息。‌

在执行ping命令时,‌TTL值可以帮助我们了解数据包在传输过程中经过的路由器数量。‌具体来说,‌TTL值等于系统默认的TTL值减去经过的路由个数。‌例如,‌如果ping命令的结果显示TTL值为54,‌而系统的默认TTL值为64,‌那么可以推断出数据包经过了10个路由器(‌因为64 - 54 = 10)‌。‌

不同的操作系统默认下TTL值是不同的。‌例如,‌Linux系统的TTL值通常为64或255,‌Windows NT/2000/XP系统的TTL值为128,‌Windows 98系统的TTL值为32,‌UNIX主机的TTL值为255。‌通过分析ping命令返回的TTL值,‌我们可以大致判断出目标主机所使用的操作系统类型。‌

②、Windows Ping TTL分析

在Windows环境下,ping www.baidu.com ,分析报文。

在这里插入图片描述

Ping请求

在这里插入图片描述

Ping响应

在这里插入图片描述

5、 C++实现Ping功能

①、 Windows实现
#include <iostream>
#include <string>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")


#define ICMP_PING_DATA_SIZE           32     //填充数据长度;
#define ICMP_TYPE_PING_REQUEST        8
#define ICMP_TYPE_PING_REPLY          0

#define ICMP_PING_TIMES               4      //Ping次数
#define MAX_BUFFER_SIZE               256


typedef unsigned char        uint8;
typedef unsigned short		 uint16;
typedef unsigned int         uint32;

//ICMP校验和计算
uint16 MakeChecksum(char* icmp_packet, int size)
{
	uint16 * sum = (uint16*)icmp_packet;
	uint32 checksum = 0;
	while (size > 1)
	{
		checksum += ntohs(*sum++);
		size -= sizeof(uint16);
	}

	if (size)
	{
		*sum = *((uint8*)sum);
		checksum += ((*sum << 8) & 0xFF00);
	}

	checksum = (checksum >> 16) + (checksum & 0xffff);
	checksum += checksum >> 16;

	return (uint16)(~checksum);
}

int main(int argc, char* argv[])
{
	std::cout << "请输入扫描主机IP地址: ";
	char input[256] = { 0 };
	char* ptr = fgets(input, 256, stdin);
	if (ptr == nullptr)
	{ 
		std::cout << "输入参数异常,结束程序!" << std::endl;
		return 1;
	}

	std::string strHost = std::string(ptr);
	strHost = strHost.substr(0, strHost.length() - 1);

	struct sockaddr_in pingaddr;
	memset((char *)&pingaddr, 0, sizeof(pingaddr));
	pingaddr.sin_family = AF_INET;
	pingaddr.sin_port = 0;
	pingaddr.sin_addr.s_addr = inet_addr(strHost.c_str());


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

	//创建Raw套接字
	SOCKET sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

	uint16 usTxID = 1;
	uint16 usTxSequeNum = 1;
	for (int ii = 0; ii < ICMP_PING_TIMES;++ii)
	{
		//组帧
		uint8 ucCmdBuf[MAX_BUFFER_SIZE] = { 0 };
		uint8* pCurr = ucCmdBuf;

		*pCurr++ = ICMP_TYPE_PING_REQUEST;		 //Type
		*pCurr++ = 0x00;						 //Code
		*pCurr++ = 0x00;						 //Checksum
		*pCurr++ = 0x00;						 //Checksum
		*pCurr++ = HIBYTE(usTxID);				 //Identifier
		*pCurr++ = LOBYTE(usTxID);				 //Identifier
		*pCurr++ = HIBYTE(usTxSequeNum);         //Sequence Number
		*pCurr++ = LOBYTE(usTxSequeNum);	     //Sequence Number

		DWORD dwSendTime = GetTickCount();
		*pCurr++ = HIBYTE(HIWORD(dwSendTime));   //Current TickCount
		*pCurr++ = LOBYTE(HIWORD(dwSendTime));   //Current TickCount
		*pCurr++ = HIBYTE(LOWORD(dwSendTime));   //Current TickCount
		*pCurr++ = LOBYTE(LOWORD(dwSendTime));   //Current TickCount

		//Data
		for (int k = 0; k < ICMP_PING_DATA_SIZE - 4;++k)
		{
			*pCurr++ = 0x61 + k;
		}

		uint16 usCheckSum = MakeChecksum((char*)ucCmdBuf, pCurr - ucCmdBuf);
		ucCmdBuf[2] = HIBYTE(usCheckSum);
		ucCmdBuf[3] = LOBYTE(usCheckSum);


		int txlen = sendto(sock, (char *)&ucCmdBuf, pCurr - ucCmdBuf, 0, (struct sockaddr *) &pingaddr, sizeof(struct sockaddr_in));

		uint8 ucRxBuf[MAX_BUFFER_SIZE] = { 0 };
		struct sockaddr rxaddr;
		int iSize = sizeof(rxaddr);
		int rxlen = recvfrom(sock, (char *)&ucRxBuf, sizeof(ucRxBuf), 0, &rxaddr, &iSize);
		if (rxlen >= 0)
		{
			//IP帧获取TTL
			uint8 ucTTL = ucRxBuf[8];

			//跳过IP Header 20个字节
			uint8* pIcmpFrame = ucRxBuf + 20;

			//比对ID和序号
			uint16 iRxID = pIcmpFrame[4] * 256 + pIcmpFrame[5];
			uint16 iRxSequeNum = pIcmpFrame[6] * 256 + pIcmpFrame[7];
			if (iRxID == usTxID && iRxSequeNum == usTxSequeNum)
			{
				DWORD dwTimeTransmit = pIcmpFrame[8] * 256 * 256 * 256 + pIcmpFrame[9] * 256 * 256 + pIcmpFrame[10] * 256 + pIcmpFrame[11];
				DWORD dwTimeDiff = GetTickCount() - dwTimeTransmit;
				std::cout << "时间=" << dwTimeDiff << "ms" << std::endl;
				std::cout << "TTL=" << (int)ucTTL << std::endl;
			}
			else
			{
				std::cout << "超时" << std::endl;
			}

		}

		usTxID++;
		usTxSequeNum++;

		Sleep(1000);
	}

	
	closesocket(sock);

	WSACleanup();

	system("pause");

	return 0;
}

备注: 注意,程序需要以管理员权限运行。

运行效果如下:

在这里插入图片描述

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

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

相关文章

推荐 3个实用且完全免费的在线工具,每天都会用到,无需登录打开即用

100font 100font是一个专业的免费商用字体下载网站&#xff0c;专注于收集、整理和分享各种免费无版权的商用字体。用户可以在这个平台上找到并下载简体中文、繁体中文、英文、日文、韩文等多种语言类型的字体。 该网站的特点包括清晰的分类和直观的下载流程&#xff0c;用户可…

金字塔原理帮助你理清思路,提升职场表达力

金字塔原理帮助你理清思路 1分钟理清思路&#xff0c;提升职场表达力 金字塔原理概述 原则 解释 模型 结论先行 中心思想和结论只有一个&#xff0c;放在最前面 SCQA模型 以上统下 任一层的思想必须是下一层次思想的概括 演绎推理 归纳推理 归类分组 每组中的思想必…

【Linux网络】其他协议和技术:DNS、ICMP、NAT

本篇博客补充了 TCP/IP 分层模型中&#xff0c;应用层的 DNS 协议、网络层的 ICMP 协议、网络层的 NAT 技术&#xff0c;旨在让读者更加深入理解网络协议栈的设计和网络编程。 目录 一、DNS 协议 1&#xff09;技术背景 2&#xff09;域名与域名解析 二、ICMP 协议 1&…

Webstorm的下载与安装

Webstorm的下载 1 在浏览器的地址栏输入https://www.jetbrains.com/webstorm/&#xff0c;进入主页面 2 点击右上角的Download按钮&#xff0c;进入下载页面&#xff0c;如图所示 Webstorm的安装 按步骤逐步安装即可

tomcat文件上传漏洞练习

1、靶场账号注册 vulfocus 注册后邮箱中点击激活 2、首页选择并开启靶场 复制映射的ip和端口 在浏览器输入ip和端口 改成put并把1.jsp中内容复制进去 3打开哥斯拉&#xff0c;连接上面的网址

TCP协议程序设计

文章目录 前言一、TCP协议程序是什么&#xff1f;二、使用步骤 1.服务器端与客户端2.实操展示总结 前言 TCP网络程序设计是指利用Socket类编写通信程序。利用TCP协议进行通讯的两个应用程序是有主次之分的&#xff0c;一个称为服务器程序&#xff0c;另一个称为客户机程序&…

Go语言编程大全,web微服务数据库十大专题精讲

本课程主要从数据结构、Go Module 依赖管理、IO编程、数据库编程、消息队列、加密技术与网络安全、爬虫与反爬虫、web开发、微服务通用技术、Kitex框架等方面讲解~ 链接&#xff1a;https://pan.quark.cn/s/d65337a0e60d

S32K144 CAN使用

S32K144是恩智浦半导体推出的一款高性能微控制器&#xff08;MCU&#xff09;&#xff0c;主要针对汽车和高可靠性的工业应用。在汽车工业应用中使用CAN总线必不可少。 需要注意的是在ISO 11898(High Speed&#xff0c;速度在5kbps-1Mbps)中&#xff0c;隐形电平电压差在0附件…

收银机打印机相关知识 windows7 查看打印机名称--未来之窗智慧经营收银系统百科

一、名词解释 打印机型号&#xff0c;打印机厂家&#xff0c;打印机接口、打印机驱动&#xff0c;打印机名称 机器的机身都有&#xff0c;打印机品牌&#xff0c;型号 二、什么是打印机接口 2.1 usb接口 一般用在收银小票&#xff0c;结账单&#xff0c;水单 2.2 并口接口 …

RK3568平台开发系列讲解(文件系统篇)什么是 inode?

一、什么是 inode? 为了存储一个文件,除了本身的文件内容块,还需要一个地方来存储文件相关的元信息信息。承载这些文件元数据的数据结构就是 inode(index node),inode 包含了文件元信息,比如文件的所有者、权限、修改时间戳等。 可以使用 ls -i 查看一个文件的 inode 号…

java基础概念11-方法

一、什么是方法 方法&#xff08;method&#xff09;是程序中最小的执行单元。 方法中的程序&#xff0c;要不然就是一起执行&#xff0c;要不然就是一起不执行&#xff01;&#xff01;&#xff01; 二、方法的定义 在Java中&#xff0c;方法定义的一般格式如下&#xff1a;…

牛客 河南萌新联赛2024第(四)场:河南理工大学 B题

比赛链接&#xff1a; 河南萌新联赛2024第&#xff08;四&#xff09;场&#xff1a;河南理工大学_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ (nowcoder.com) B题&#xff1a;小雷的神奇电脑 题目描述&#xff1a; 小雷有一台特殊的电脑&#xff0c;这台电…

搜维尔科技:如何使用 SenseGlove Nova 在其“CAVE”投影室中操纵虚拟物体

AVR 创建了一个创新的基于 PC 的多面沉浸式环境&#xff0c;参与者完全被虚拟图像和声音包围。 需要解决的挑战&#xff1a; 传统的 VR 系统通常缺乏逼真的触觉反馈&#xff0c;限制了用户的沉浸感。AVR Japan 旨在通过将触觉技术融入其 CAVE 系统来解决这一挑战&#xff0c;使…

【8-9月份唯一机械电气计算机主题的IEEE会议】第七届机电一体化与计算机技术工程国际学术会议(MCTE 2024,8月23-25)

由广东博士创新发展促进会、输变电装备技术全国重点实验室联合主办&#xff0c;重庆大学电气工程学院、AEIC学术交流中心协办的第七届机电一体化与计算机技术工程国际学术会议&#xff08;MCTE 2024&#xff09;将于2024年8月23-25日在中国广州隆重举行。 大会诚挚邀请您投递相…

学习日志8.7--Security Zone防火墙安全区域

安全区域实验拓扑开始之前先通过一台主机和防火墙相连&#xff0c;设置主机的IP地址和网关&#xff0c;开启防火墙设置防火墙接口g1/0/1的IP地址为192.168.1.254&#xff0c;将防火墙设置为主机的网关&#xff0c;尝试能不能用主机ping通防火墙。尝试之后&#xff0c;发现失败&…

蚂蚁CodeFuse代码大模型技术解析:基于全仓库上下文的代码补全

背景 2023年CodeFuse完成了百亿级别的代码大模型从0到1的预训练&#xff0c;配合指令微调、量化部署等一系列配套技术&#xff0c;成功将AI大模型能力应用到多个下游研发场景&#xff0c;助力生产提效。在众多下游产品中&#xff0c;CodeFuse代码补全插件直接触及研发过程中最…

性能测试趋势 2024

效率。其主要目标是确保软件满足性能要求并提供令人满意的用户体验。 有效的性能测试需要仔细的规划、真实的场景以及使用适当的工具来模拟真实世界的条件。定期进行性能测试有助于确保软件系统能够处理不同的工作负载并提供积极的用户体验。性能测试的未来正在受到技术发展的…

SSL证书配置

SSL证书配置 证书申请nginx 配置ssl证书 今天群友发现我的博客证书过期了&#xff0c;重新申请一个免费的部署一下 证书申请 点击创建证书 绑定对应的域名&#xff0c;选择快捷签发&#xff0c;点击提交审核 点击验证&#xff0c;如果购买的域名和服务器都在同一个账号下&…

WPF学习(7)- Control基类+ContentControl类(内容控件)+ButtonBase基类

前面给大家介绍完了WPF所有的布局控件&#xff0c;属性以及使用案例&#xff0c;从这里咱们就开始学下内容控件。 Control基类 Control是许多控件的基类。比如最常见的按钮&#xff08;Button&#xff09;、单选(RadioButton)、复选&#xff08;CheckBox&#xff09;、文本框…

AIGC大模型实践总结(非常详细)零基础入门到精通,收藏这一篇就够了

大模型浪潮席卷全球&#xff0c;在各行各业中的重要性愈发凸显&#xff0c;呈现出一股不可逆转的发展趋势。这一年本人所在业产技也在这一过程中持续探索和尝试AIGC。本文一方面是对AIGC实践的总结回顾&#xff0c;同时也是本人学习实践AIGC过程中一些笔记、心得分享。因个人能…