请结合附件:Ping的实现原理与ping.cpp的内容,编写一个程序,使其能够实现简单的ping的功能,即判断目标网站是否可以连接,然后通过Wireshark进行抓包分析其ICMP协议,指出哪个数据包是ping的请求(request),哪个数据包是对这个请求的回应(reply)(如果reply数据包存在的话)。


相关知识:

ICMP (Internet Control Message Protocol) Internet控制报文协议,它是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息(即提供TCP/IP网络上设备、服务协议及路由器可用性的信息),ICMP允许主机或路由器报告差错情况和提供有关异常情况的报告,目的是为了更有效地转发IP数据报和提高交付成功的机会。

注:控制消息指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。

ICMP的两个主要应用是Ping和Traceroute。

需要编写程序,实现简单的ping的功能,主要需要了解以下内容:

要点1:ICMP协议相关知识

ICMP不是高层协议,而是IP层的协议。ICMP报文是装在IP数据报中,作为其中的数据部分。

①ICMP报文的格式

ICMP协议的类型码与代码根据不同情况,各自取值。8bits类型和8bits代码字段:一起决定了ICMP报文的类型,常见的有:

A.类型8、代码0:回射请求。

B.类型0、代码0:回射应答。

C.类型11、代码0:超时。

ICMP报文的前4个字节是统一的格式,共有三个字段:即类型、代码和检验和。接着的4个字节的内容与ICMP的类型有关。(这8个字节为ICMP报文的首部)

②ICMP报文的种类

从类型值来看ICMP报文可分为二大类:

A.差错报告报文;

类型值

ICMP报文类型

描述

3

终点不可达

当路由器或主机不能交付数据报 时就向源点发送终点不可达报文

5

改变路由(Redirect)

路由器把改变路由报文发送给主机,让主机知道下次应将数据报发送给另外的路由器(可通过更好的路由)。

11

时间超过

当路由器收到生存时间为零的数据报时,除丢弃该数据报外,还要向源点发送时间超过报文。当终点在预先规定的时间内不能收到一个数据报的全部数据报片时,就把已收到的数据报片都丢弃,并向源点发送时间超过报文

12

参数问题

(Parameter Problem)

当路由器或目的主机收到的数据报的首部中有的字段的值不正确时,就丢弃该数据报,并向源点发送参数问题报文。

B.询问报文。

类型值

ICMP报文类型

描述

8或0

回送(Echo)

请求(Request)或回答(Reply)报文

ICMP回送请求报文是由主机或路由器向一个特定的目的主机发出的询问。收到此报文的主机必须给源主机或路由器发送ICMP回送回答报文。这种询问报文用来测试目的站是否可达以及了解其有关状态。

13或14

时间截(Timestamp)请求或回答

ICMP时间戳请求报文是请某个主机或路由器回答当前的日期和时间。在ICMP时间戳回答报文中有一个32位的字段,其中写入的整数代表从1900年1月1日到当前时刻一共有多少秒。可用来进行时钟同步和测量时间

要点2:IP地址的点分十进制表示

机器中存放的IP地址是32位二进制代码。以8位为一组,采用点分十进制记法可以进一步提高可读性,如图所示:

在实验代码中,使用到的两个函数inet_addr()和Inet_ntoa()完成的就是32位二进制表示的IP地址与点分十进制记法之间的转换:

①inet_addr函数(点分十进制->32位二进制)需要一个字符串作为其参数,该字符串指定了以点分十进制格式表示的IP地址(例如:192.168.0.16)。而且inet_addr函数会返回一个适合分配给S_addr的u_long类型的数值。

②Inet_ntoa函数(32位二进制->点分十进制)会完成相反的转换,它接受一个in_addr结构体类型的参数并返回一个以点分十进制格式表示的IP地址字符串

注:在vs2013以上的版本会出现这个两个无法使用的错误信息及相对应的解决方法如图所示:

这两个函数是随IPv6出现的新函数,对于IPv4地址和IPv6地址都适用。对比与使用方法可参见:https://blog.csdn.net/gujintong1110/article/details/45390653

要点3:校验和的计算(具体实现可参见参考代码ping.cpp)

在发送数据时,为了计算数据包的检验和。应该按如下步骤:

1.把校验和字段设置为0;

2.把需要校验的数据看成以16位为单位的数字组成,依次进行二进制反码求和;

3.把得到的结果存入校验和字段中

在接收数据时,计算数据包的检验和相对简单,按如下步骤:

1.把首部看成以16位为单位的数字组成,依次进行二进制反码求和,包括校验和字段;

2.检查计算出的校验和的结果是否为0;

3.如果等于0,说明被整除,校验和正确。否则,校验和就是错误的,协议栈要抛弃这个数据包。

注:IP、ICMP、UDP和TCP报文头都有检验和字段,大小都是16bit这四种报文的校验和算法一样,但是在作用范围存在不同:

IP校验和只校验20字节的IP报头;

ICMP校验和覆盖整个报文(ICMP报头+ICMP数据)

UDP和TCP校验和不仅覆盖整个报文,而且还有12个字节的IP伪首部,包括源IP地址(4字节)、目的IP地址(4字节)、协议(2字节)、TCP/UDP包长(2字节)

另外UDP、TCP数据报的长度可以为奇数字节,所以在计算校验和时需要在最后增加填充字节0(填充字节只是为了计算校验和,可以不被传送)

要点4:两个关键函数sendto()和recvfrom()

①sendto()用于已连接的数据报或流式套接口发送数据。

对于sendto()函数,成功则返回实际传送出去的字符数,失败返回-1,错误原因存于errno 中。

②recvfrom()用于从(已连接)套接口上接收数据,并捕获数据发送源的地址

对于recvfrom()函数,成功则返回接收到的字符数,失败则返回-1,错误原因存于errno中。

注:可以通过WSAGetLastError()得到错误代码,对应MSDN参考文档即可知道错误的原因。

具体解析可参见:https://blog.csdn.net/qq_32744005/article/details/51772694

-------------------------------------------------------------------------------------------------------------------------------------------------

鉴于之前网络编程课就已经做过ping的实验了,所以这个代码就不用打了,直接贴上来,偷懒一下...

-------------------------------------------------------------------------------------------------------------------------------------------------

代码:

#define _CRT_SECURE_NO_WARNINGS

#define _WINSOCK_DEPRECATED_NO_WARNINGS

#include <stdio.h>

#include <winsock2.h>

#pragma comment(lib, "WS2_32")

typedef struct _IPHeader

{

unsigned char      iphVerLen;

unsigned char      ipTOS;

unsigned short     ipLength;

unsigned short     ipID;

unsigned short     ipFlags;

unsigned char     ipTTL;

unsigned char     ipProtocol;

USHORT    ipChecksum;

ULONG     ipSource;

ULONG     ipDestination;

} IPHeader, *PIPHeader;

typedef struct icmp_hdr

{

unsigned char   icmp_type;

unsigned char   icmp_code;

unsigned short  icmp_checksum;

unsigned short  icmp_id;

unsigned short  icmp_sequence;

unsigned long   icmp_timestamp;

} ICMP_HDR, *PICMP_HDR;

typedef struct _EchoRequest {

ICMP_HDR icmphdr;

char cData[32];

}ECHOREQUEST, *PECHOREQUEST;

#define REQ_DATASIZE 32

typedef struct _EchoReply {

IPHeader iphdr;

ECHOREQUEST echoRequest;

}ECHOREPLAY, *PECHOREPLAY;

USHORT checksum(USHORT* buff, int size)

{

u_long cksum = 0;

while (size > 1)

{

cksum = cksum + *buff;

buff = buff + 1;

size = size - sizeof(USHORT);

}

if (size == 1)

{

USHORT u = 0;

u = (USHORT)(*(UCHAR*)buff);

cksum = cksum + u;

}

cksum = (cksum >> 16) + (cksum & 0x0000ffff);

cksum = cksum + (cksum >> 16);

u_short  answer = (u_short)(~cksum);

return (answer);

}

int main() {

WSADATA wsaData;

WORD version = MAKEWORD(2, 2);

int ret = WSAStartup(version, &wsaData);

if (ret != 0) {

printf(" 加载Winsock库错误! \n");

return 0;

}

char szDestIp[100];

printf("输入所要连接的外网地址:\n");

scanf("%s", szDestIp);

SOCKET sRaw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

SOCKADDR_IN dest;

dest.sin_family = AF_INET;

dest.sin_port = htons(0);

dest.sin_addr.S_un.S_addr = inet_addr(szDestIp);

ECHOREQUEST echoReq;

echoReq.icmphdr.icmp_type = 8;

echoReq.icmphdr.icmp_code = 0;

echoReq.icmphdr.icmp_id = (USHORT)GetCurrentProcessId();

echoReq.icmphdr.icmp_checksum = 0;

echoReq.icmphdr.icmp_sequence = 0;

memset(&echoReq.cData, 'E', 32);

USHORT   nSeq = 0;     SOCKADDR_IN from;

int nLen = sizeof(from);

int fail = 0;

int success = 0;

int i = 0;

int a[4];

int isFail = 0;

int timeQ;

while (TRUE) {

static int nCount = 0;   int nRet;

if (nCount++ == 4)   break;

echoReq.icmphdr.icmp_checksum = 0;

echoReq.icmphdr.icmp_timestamp = GetTickCount();

echoReq.icmphdr.icmp_sequence = nSeq++;

echoReq.icmphdr.icmp_checksum = checksum((USHORT*)&echoReq, sizeof(echoReq));

nRet = sendto(sRaw, (char*)&echoReq, sizeof(echoReq), 0, (SOCKADDR *)&dest, sizeof(dest));

if (nRet == SOCKET_ERROR) {

printf(" sendto() failed: %d \n", WSAGetLastError());

system("pause");

return 0;

}

ECHOREPLAY echoReply;

nRet = recvfrom(sRaw, (char*)&echoReply, sizeof(ECHOREPLAY), 0, (sockaddr*)&from, &nLen);

if (nRet == SOCKET_ERROR) {

if (WSAGetLastError() == WSAETIMEDOUT) {

printf(" timed out\n");

printf("时间超时\n");

fail++;

continue;

}

printf(" recvfrom() failed: %d\n", WSAGetLastError());

isFail = 1;

printf("来自172.16.4.42的回复:无法访问目标主机\n");

success++;

continue;

}

if (nRet < sizeof(ECHOREPLAY)) {

printf(" Too few bytes from %s \n", inet_ntoa(from.sin_addr));

}

if (echoReply.echoRequest.icmphdr.icmp_type != 0) {

printf(" nonecho type %d recvd \n", echoReply.echoRequest.icmphdr.icmp_type);

system("pause");

return 0;

}

if (echoReply.echoRequest.icmphdr.icmp_id != GetCurrentProcessId()) {

printf(" someone else's packet! \n");

system("pause");

return 0;

}

printf(" %d bytes Reply from %s: \n", nRet, inet_ntoa(from.sin_addr));

printf(" icmp_seq = %d. ", echoReply.echoRequest.icmphdr.icmp_sequence);

int nTick = GetTickCount();

success++;

printf(" time: %d ms", nTick - echoReply.echoRequest.icmphdr.icmp_timestamp);

a[i] = nTick - echoReply.echoRequest.icmphdr.icmp_timestamp;

i++;

printf(" TTL= %d ", echoReply.iphdr.ipTTL);

//printf(echoReply.echoRequest.cData);

printf(" \n");

Sleep(1000);

}

printf("%s 的ping的统计信息:\n", szDestIp);

printf("数据包:已发送 = %d,已接收 = %d,丢失 = %d\n", success, success, fail);

if (isFail != 1) {

printf("往返程的估计时间:(以毫秒记)\n");

int timeC = a[0];

int timeD = a[0];

int timeA = a[0];

int j;

for (j = 1; j < 4; j++) {

if (timeC < a[j]) {

timeC = a[j];

}

if (timeD > a[j]) {

timeD = a[j];

}

timeA = timeA + a[j];

}

timeA = timeA / 4;

printf("最短 = %d 最长 = %d 平均 = %d\n", timeD, timeC, timeA);

}

else {

}

WSACleanup();

system("pause");

return 0;

}

-------------------------------------------------------------------------------------------------------------------------------------------------

解释:编写ping程序发送数据包,主要用了两个函数-sendto和recvfrom。这两个函数是基于udp协议的。

-------------------------------------------------------------------------------------------------------------------------------------------------

测试:

Cmd

自己编写的ping程序

-------------------------------------------------------------------------------------------------------------------------------------------------

问题1:Ping的实现原理与ping.cpp的内容,编写一个程序,使其能够实现简单的ping的功能,即判断目标网站是否可以连接

由实验结果可知,ping 123.125.114.144(百度网址)可以有返回的数据包,说明可以ping通。证明该目标网站可以连接

------------------------------------------------------------------------------

使用wireshark工具抓包分析:(具体过程可以参考实验9)

问题2:然后通过Wireshark进行抓包分析其ICMP协议,指出哪个数据包是ping的请求(request),哪个数据包是对这个请求的回应(reply)(如果reply数据包存在的话)。

通过实验结果可知,ping 123.125.114.144(百度网址)可以有返回的数据包,说明可以其中可以看见是使用ICMP协议,通过上图红框圈出的标记,可以看见request和reply。

request是请求的意思,所有可以知道这个数据包时ping的请求,reply是回应的意思,可以知道这个数据包是对请求的回应。


通过这个实验,我们认识了ping代码的编写。深刻地认识了udp的原理。

UDP:

UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI(Open System Interconnection,开放式系统互联) 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,IETF RFC 768是UDP的正式规范。UDP在IP报文的协议号是17。

UDP协议全称是用户数据报协议,在网络中它与TCP协议一样用于处理数据包,是一种无连接的协议。在OSI模型中,在第四层——传输层,处于IP协议的上一层。UDP有不提供数据包分组、组装和不能对数据包进行排序的缺点,也就是说,当报文发送之后,是无法得知其是否安全完整到达的。UDP用来支持那些需要在计算机之间传输数据的网络应用。包括网络视频会议系统在内的众多的客户/服务器模式的网络应用都需要使用UDP协议。UDP协议从问世至今已经被使用了很多年,虽然其最初的光彩已经被一些类似协议所掩盖,但是即使是在今天UDP仍然不失为一项非常实用和可行的网络传输层协议。

与所熟知的TCP(传输控制协议)协议一样,UDP协议直接位于IP(网际协议)协议的顶层。根据OSI(开放系统互联)参考模型,UDP和TCP都属于传输层协议。UDP协议的主要作用是将网络数据流量压缩成数据包的形式。一个典型的数据包就是一个二进制数据的传输单位。每一个数据包的前8个字节用来包含报头信息,剩余字节则用来包含具体的传输数据。

--来自百度百科--  https://baike.baidu.com/item/UDP/571511?fr=aladdin

由这个实验可以看出udp和tcp的不同,udp建立连接需要三次握手,结束连接四次挥手。而udp不需要这个步骤。

编写ping程序有什么用呢?其实我们可以编写ping程序来进行dos攻击或ddos攻击。针对以上的程序,我们把ping ip地址,该为指定ip(想要攻击的目标),使用while循环来进行不断的发送数据包,就可以进行dos攻击。如果我们抓了不少肉鸡的话。可以几台肉鸡乃至10几台肉鸡来对某个服务器ip一起发送ping请求。可以把这个服务器打掉。

https://blog.csdn.net/pygain/article/details/52134480 - 浅谈DOS与DDOS攻击的原理

DOS粗略讲解:

1.TCP饿死:

UDP这种传输方式不会控制自己在通信通道里的流量,可理解为不讲道理的人。他们来到了一个热闹地区的KFC中,但是他们不买东西只排队将所有食物的价格都问一遍,占满所有的座位和过道。而常规的TCP服务通过自己的弹窗机制来控制流量,好比讲道理的人,座位被占满了,TCP自然会离开KFC导致正常的服务不能进行。最终的结果就是UDP将整个通道打满堵死。

2.攻击原理

DOS攻击:一台或多台计算机对受攻击服务器的某一个端口发送大量无关的UDP报文,导致整个通道内的正常服务无法进行。

DDOS攻击:大量的肉鸡对服务器的不同端口发送巨型流量的UDP报文,无法通关关闭端口的方式来进行隔离,破坏力极强,严重会造成服务器当机。

网络安全学习第10篇 - ping程序的实现,抓包分析ping数据包以及ping工具对于网络安全方面的威胁相关推荐

  1. 网络安全学习第6篇 - 爆破及PE文件解释

    1.请采用暴力破解的方式去尝试破解crack.exe文件(在实验报告中说明破解原理即可,无需提交破解后的文件) 2.请依据参考文档中的内容编写一个小程序,使其可以实现如下功能: ①判断一个文件是否为P ...

  2. FlyAI资讯:收藏!深度学习必读10篇经典算法论文总结!

    前言 目录 前言 1998年:LeNet 2012年:AlexNet 2014年:VGG 2014年:GoogLeNet 2015年:Batch Normalization 2015年:ResNet ...

  3. 网络安全学习第4篇-使用特征码和MD5对勒索病毒进行专杀,并对加密文件进行解密

    请使用IDA或其它分析工具分析本次的样本文件,写一个简要的行为分析报告,并编写一个针对于这次样本的专杀(恢复)程序. 要求: 1.样本分析只要说明主要行为即可.提示:sub_401320主要用于文件加 ...

  4. 计算机网络个人项目设计:java实现,基于Jnetpcap的网络嗅探抓取,发送数据包单机程序(模仿wireshark)

    开发环境 java javaFX(fxml加控制器的那种,用到图形化的JavaFX Scene Builder设计界面) 用到封装好的jar包:Jnetpcap,需安装winpcap idea开发 基 ...

  5. 【融职培训】Web前端学习 第10章 小程序开发4 小程序开发

    一,数据绑定 VUE:vue动态绑定一个变量的变量元素的某个属性的时候,会在变量前面加上冒号:,例: <p:title="tit">我的title属性绑定了数据< ...

  6. 【小迪安全】web安全|渗透测试|网络安全 | 学习笔记-10

    目录 目录 第58天:权限提升-网站权限后台漏洞第三方获取 第59天:权限提升-Win溢出漏洞及AT&SC&PS提权 第60天:权限提升-MY&MS&ORA等SQL数据 ...

  7. 网络安全学习第15篇 - 游戏内存修改

    请依据实验文档<游戏辅助的实现>中的内容,自行编写一个游戏内存数据修改程序,使其可以对某款游戏的某一项或某几项数值进行修改.有余力的同学可以任选一款游戏尝试修改. 实验报告的最后请简述,作 ...

  8. 编写简单的服务和客户端(C++)---ROS学习第10篇

    文章目录 1. 编写服务节点 2. 编写客户端节点 3. 构建节点 4. 运行可执行文件 1. 编写服务节点 这里,我们将创建简单的服务(Service)节点add_two_ints_server,该 ...

  9. 网络安全学习记录-10

    数据库注入 1.Mysql 注入-Dns 注入 注入没有回显: DNS 注入->让盲注变成显错注入 Load_File()读取文件 UNC路径 windows SMB 服务(共享文件)//des ...

最新文章

  1. Scrum敏捷开发工具实力推荐
  2. QuadricSLAM: 面向机器人的物体级语义SLAM系统
  3. mysql5.7.22并行回放_MySQL 5.7并行复制时代
  4. Python基础入门:正则re.sub使用自定义替换方法
  5. 将页面中表格数据导出excel格式的文件(vue)
  6. 数据集哪些特征有多大的null列表
  7. 论文浅尝 - ACL2020 | 利用常识知识图对会话流进行显式建模
  8. linux tail命令_操作手册
  9. idea代码上传到gitee组织流程
  10. esp8266时钟_ESP8266(Non-OS SDK) 驱动 waveshare 2.9 寸墨水屏(二)- 程序移植、修改与测试
  11. MultiActionController
  12. HDU1407 测试你是否和LTC水平一样高【暴力】
  13. Installing third-party firmware on x3-55 letv (by quqi99)
  14. 通用有限元软件简介及比较
  15. HashMap 底层实现原理
  16. 资源搜索神器 海量精品资源教程 大大啦啦资源神器
  17. js 获取字符长度(英文1,中文2)
  18. 网络安全守护神(SOC)
  19. C/C++游戏项目完整教程:《坦克大战》
  20. 全球与中国涂料和油墨用丙烯酸树脂市场发展规划展望及未来需求预测报告2021年版

热门文章

  1. centos系统中php Curl 无法访问https 的解决办法
  2. 我连Punk男都算不上 (一)
  3. 如何修复“Windows/System32/Config/System中文件丢失或损坏”故障
  4. 学计算机等级考试电脑版软件,猎证全国计算机等级考试学习系统
  5. Jmeter学习笔记
  6. QDAS转换器中间XML格式说明文档
  7. C语言:【换钱问题】人民币问题
  8. 1316:数的计数(Noip2001)
  9. JAVAWEB JavaScript 正则表达式
  10. matlab中min和max的使用