目录

简介

报文格式

差错报文

常见类型

不发送ICMP差错报文的情况

询问报文

常见类型

实战

简单Ping命令实现

抓包

手算校验和

全部代码

Traceroute

抓包

ICMP重定向攻击

原理

攻击

防御

参考


简介

ICMP(Internet Control Message Protocol,网际控制报文协议)是TCP/IP协议簇的一个子协议,用于在主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。

报文格式

ICMP报文分为两类:一类通知出错原因 ,一类用于诊断查询。

ICMP报文格式
  • 类型:占一字节,标识ICMP报文的类型,从类型值来看ICMP报文可以分为两大类。第一类是取值为1~127的差错报文,第2类是取值128以上的信息报文。
  • 代码:占一字节,标识对应ICMP报文的代码,它与类型字段一起共同标识了ICMP报文的详细类型。
  • 校验和:占两个字节,这是对包括ICMP报文数据部分在内的整个ICMP数据报的校验和,以检验报文在传输过程中是否出现了差错

差错报文

差错报文格式

常见类型

  • 3    目标/终点不可达:无法交付。当路由器或主机不能交付数据报时就向源点发送终点不可达报文。
  • 4    源点抑制
  • 5    重定向/改变路由:更好路由。路由器把改变路由报文发送给主机,让主机知道下次应将数据报发送给另外的路由器(可通过更好的路由)。
  • 11   超时:TTL=0。当路由器收到生存时间TTL=0的数据报时,除丢弃数据包外,还要向源点发送时间超过报文。当终点在预先规定的时间内不能收到一个数据报的全部数据报片时,就把已收到的数据报片都丢弃,并向源点发送时间超过报文。
  • 12  参数问题:首部字段有问题。当路由器或目的主机收到的数据报的首部中有的字段的值不正确时,就丢弃该数据报,并向源点发送参数问题报文。

4已弃用

不发送ICMP差错报文的情况

  • ICMP差错报告报文不再发送ICMP差错报告报文(否则可能死循环)
  • 对第一个分片的数据报片的所有后续数据报片都不发送ICMP差错报告报文。
  • 目的地址是多/广播地址的数据报都不发送ICMP差错报告报文。
  • 作为链路层广播的数据报都不发送ICMP差错报告报文。
  • 对具有特殊地址(如127.0.0.0或0.0.0.0)的数据报不发送ICMP差错报告报文。

询问报文

常见类型

  • 0    回送应答:收到回送请求报文的主机必须给源主机或路由器发送ICMP回送应答报文,表示本身可达以及自身状态。
  • 8    回送请求:主机或路由器向特定目的主机发出的询问,测试目的主机是否可达以及了解其相关状态。
  • 13  时间戳请求:请某个主机或路由器回答当前的日期和时间,用来进行时钟同步和测量时间。
  • 14  时间戳响应:收到时间戳请求报文的主机回答当前的日期和时间,用来进行时钟同步和测量时间。
  • 15  路由器应答
  • 16  路由器请求
  • 17  地址子网请求
  • 18  地址子网应答

后4个已经弃用了

实战

简单Ping命令实现

PING(Packet InterNet Groper)分组网间探测,用来测试两台主机之间的连通性。当然,也可能由于防火墙或具有白名单功能的路由器而无法Ping通。

抓包

打开WireShark,筛选icmp数据报,cmd命令,ping一下 www.baidu.com。

ping百度结果

回送请求报文
  • 类型:8(08),表示回送请求类型。
  • 代码:0(00)。
  • 校验和:4d 54,correct,校验正确。
  • Identifier、Sequence number:00 01 00 07。
  • 数据:如上图蓝色阴影部分。

回送应答报文
  • 类型:0(00),表示回送请求类型。
  • 代码:0(00)。
  • 校验和:45 54,correct,校验正确。
  • Identifier、Sequence number:00 01 00 07。
  • 数据:如上图蓝色阴影部分。

综上,Ping命令测试两个主机之间的连通性,使用了ICMP发送请求和回答报文

手算校验和

ICMP报文中的各个部分中,校验和是相对较难的。先看一下如何计算。

RFC 792校验和描述

首先,校验和字段置为0,然后,对首部中每个16bit进行二进制反码求和,结果存在校验和字段中。

回送请求报文

08 00 4d 54 00 01 00 07 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69

校验码置0

08 00 00 00 00 01 00 07 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f 70 71 72 73 74 75 76 77 61 62 63 64 65 66 67 68 69

16bit一组

0800 0000 0001 0007 6162 6364 6566 6768 696a 6b6c 6d6e 6f70 7172 7374 7576 7761 6263 6465 6667 6869

校验和计算过程

按列计算,右侧第一列加和结果为7(111),剩1,进11,右侧第二列加和结果为9+1(进位)=10(1010),剩0进101。同理,最后将超出16位部分加和,结果回加到低位,得到求和结果,取反得到校验和。不习惯按列加的可以两两相加(待加个数超过16个时没有按列快,因为按列总是16列),以下代码使用的是两两加和

全部代码

"""
--coding:utf-8--
@File: Ping.py
@Author:frank yu
@DateTime: 2020.12.13 10:35
@Contact: frankyu112058@gmail.com
@Description:Implement of Ping
"""
import random
import socket
import struct
import timedef checksum(msg):""":param msg:icmp message(bytes):return:checksum(bytes)"""check_sum = 0n = len(msg)def carry_around_add(a, b):c = a + breturn (c & 0xffff) + (c >> 16)for i in range(0, n, 2):w = msg[i] + (msg[i + 1] << 8)check_sum = carry_around_add(check_sum, w)res = ~check_sum & 0xffffres = res >> 8 | (res << 8 & 0xff00)return resdef icmp_packet(sequence_number):""":param sequence_number::return: binary of icmp packet"""icmp_type = 8  # ICMP Echo Requesticmp_code = 0  # zeroicmp_checksum = 0  # set to zero firsticmp_Identifier = 1  # Identifiericmp_Sequence_number = sequence_numbericmp_Data = b'abcdefghijklmnopqrstuvwabcdefghi'  # dataicmp_message = struct.pack('>2B3H32s', icmp_type, icmp_code, icmp_checksum, icmp_Identifier, icmp_Sequence_number,icmp_Data)icmp_checksum = checksum(icmp_message)icmp_message = struct.pack('>2B3H32s', icmp_type, icmp_code, icmp_checksum, icmp_Identifier, icmp_Sequence_number,icmp_Data)return icmp_messagedef icmp_request(dst_addr, pkt, timeout=2):"""send icmp packet and return socket for listening:param timeout: timeout:param dst_addr: ip of destination address:param pkt: packet of icmp:return: socket of icmp,time"""icmp_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)icmp_socket.settimeout(timeout)icmp_socket.sendto(pkt, (dst_addr, 80))send_time = time.time()return icmp_socket, send_timedef icmp_reply(icmp_socket, send_time, sequence_num):"""monitor the icmp socket and return how much time spent if receives reply msg:param icmp_socket:socket which sent icmp msg before:param send_time: time when send icmp request:param sequence_num:sequence num:return:time and TTL/-1,-1"""try:recv_pkt, addr = icmp_socket.recvfrom(1024)# print(recv_pkt)recv_time = time.time()icmpHeader = recv_pkt[20:28]type, _, _, _, sequence = struct.unpack(">2B3H", icmpHeader)if type == 0 and sequence == sequence_num:return recv_time - send_time, recv_pkt[8]except socket.timeout:return -1, -1def ping(host):""":param host:domain name or ip addr:return: None"""Sequence_number = random.randint(0, 10 ** 4)# 若为ip,不变;若为域名,转为iptry:dst_addr = socket.gethostbyname(host)except socket.gaierror:print(f'something wrong, please check your input.')exit(0)miss, short, long, alltime = 0, 10 ** 9, 0, []print(f"正在 Ping {host} [{dst_addr}] 具有 32 字节的数据:")for i in range(0, 4):# 构造icmp数据包icmp_pkt = icmp_packet(Sequence_number + i)# print(icmp_pkt)# 发送并记录时间icmp_socket, send_time = icmp_request(dst_addr, icmp_pkt)# 接收并计算时间差times, TTL = icmp_reply(icmp_socket, send_time, Sequence_number + i)if times >= 0:print(f"来自 {dst_addr} 的回复: 字节=32 时间={int(times * 1000)}ms TTL={TTL}")if short > times:short = timesif long < times:long = timesalltime.append(times * 1000)time.sleep(1)else:print("请求超时。")miss += 1print()print(f'{dst_addr} 的 Ping 统计信息:\n'f'    数据包: 已发送 = 4,已接收 = {4 - miss},丢失 = {miss} ({int(miss / 4 * 100)}% 丢失),')if miss < 4:print('往返行程的估计时间(以毫秒为单位):\n'f'    最短 = {int(short * 1000)}ms,最长 = {int(long * 1000)}ms,平均 = {int(sum(alltime) / (4 - miss))}ms')return Noneif __name__ == '__main__':host = input('please input domain name or ip addr:')ping(host)

结果如下:

结果截图

主机A ping 主机B ---> 构建 ICMP 包 ----> 构建 IP 分组 ----> 解析硬件地址封装成帧 ----> 物理层发送 ----> 网络层传输 ----> 到达主机B ----> 提取IP数据包交给IP层协议 ----> 提取信息交给ICMP协议,构建ICMP应答包 ----> 发送给主机A

Traceroute

这是UNIX系统的名字,在Windows中是tracert。

一个分组从源点到终点的路,使用了ICMP时间超过差错报告报文。

抓包

tracert 百度抓包

标题
  • 类型:11(0b),表示超时类型。
  • 代码:0(00)。
  • 校验和:f4 ff,correct,校验正确。
  • Unused:00 00 00 00。
  • 数据:剩下的部分。

标题
  • 类型:3(03),表示终点不可达类型。
  • 代码:3(03),表示终点不可达中的端口不可达类型。
  • 校验和:b9 dd,correct,校验正确。
  • Unused:00 00 00 00。
  • 数据:剩下的部分。

Traceroute从源主机向目的主机发送一连串的IP数据报,封装的是无法交付的UDP数据报(端口大于30000)。第一个数据报P1的生存时间TTL设置为1。当P1到达路径上的第一个路由器R1时,路由器R1先收下它,接着把TTL的值减1。由于TTL等于零了,R1就把P1丢弃了,并向源主机发送一个ICMP时间超过差错报告报文,源主机接着发送第二个数据报P2,并把TTL设置为2。P2先到达路由器R1,R1收下后把TTL减1再转发给路由器R2。R2收到P2时TTL为1,但减1后TTL变为零了。R2就丢弃P2,并向源主机发送一个ICMP时间超过差错报告报文。这样一直继续下去。当最后一个数据报刚刚到达目的主机时,数据报的TTL是1。主机不转发数据报,也不把TTL值减1。但因IP数据报中封装的是无法交付的UDP数据报,因此目的主机要向源主机发送ICMP终点不可达差错报告报文。这样,源主机达到了自己的目的,因为这些路由器和最后目的主机发来的ICMP报文正好给出了源主机想知道的路由信息一到达目的主机所经过的路由器的IP地址,以及到达其中的每一个路由器的往返时间。

ICMP重定向攻击

原理

ICMP重定向信息是路由器向主机提供实时的路由信息,当一个主机收到ICMP重定向信息(上面提到,type=5)时,它就会根据这个信息来更新自己的路由表。由于缺乏必要的合法性检查,如果一个黑客想要被攻击的主机修改它的路由表,黑客就会发送ICMP重定向信息给被攻击的主机,让该主机按照黑客的要求来修改路由表

攻击

攻击机

操作系统:kali

使用软件:netwox

IP:10.28..214.132

靶机

操作系统:Win10

IP:10.28..214.51

网关:10.28.128.1

靶机Ping网关与攻击机

攻击机攻击

打开ettercap,点击对勾

ettercap -G

点击搜索主机,打开主机列表

选择ICMP重定向攻击

输入网关MAC地址和IP地址

打开wireshark抓包,靶机浏览器打开几个网页。可以看到ICMP重定向报文。

点击可查看,网关已被修改为攻击机IP。

Ettercap显示靶机在访问的外网站点IP及端口。

攻击机可以获得靶机发送的数据,但是无法接收从外网返回的数据,属于半个中间人攻击。

防御

(1)网关端:

关闭ICMP重定向(no ip redirects)。

变长子网掩码划分网段。

使用网络控制列表(ACL)和代理。

(2)主机端:

可以使用防火墙等过滤掉ICMP报文,或使用反间谍软件监控。

结合防ARP、IP欺骗等进行防御。

参考

《TCP/IP详解卷1》第六、七、八章

《谢希仁 计算机网络第7版》4.4

stackoverflow-checksum-icmp-python-with-wireshark

RFC 792

ettercap的YouTube频道

ettercap的GitHub

更多内容查看:网络安全-自学笔记

喜欢本文的请动动小手点个赞,收藏一下,有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!如有侵权,请及时联系。如果您感觉有所收获,自愿打赏,可选择支付宝18833895206(小于),您的支持是我不断更新的动力。

网络-ICMP协议、Ping命令实现与ICMP攻击相关推荐

  1. ICMP协议Ping命令的应用

    ICMP的全称是InternetControlMessageProtocol,它是TCP/IP协议族的一个子协议,属于网络层协议,用于在IP主机.路由器之间传递控制消息.从技术角度来讲,就是让我们能够 ...

  2. C语言实现ICMP协议Ping命令

    From: http://www.360doc.com/content/12/0429/19/1317564_207540510.shtml 大部分人用ping命令只是作为查看另一个系统的网络连接是否 ...

  3. c语言实现icmp协议ping命令,利用ICMP协议实现ping命令

    一.实现原理 ping利用ICMP协议包来侦测另一个主机是否可达.Ping的原理是使用了类型码为8的ICMP回送请求包,收到请求的主机则用类型码为0的ICMP回应报文.如果应答包和请求包的标示号.序号 ...

  4. 计算机网络 day6 arp病毒 - ICMP协议 - ping命令 - Linux手工配置IP地址

    目录 arp协议 arp病毒\欺骗 arp病毒的运行原理 arp病毒产生的后果: 解决方法: ICMP协议 ICMP用在哪里? ICMP协议数据的封装过程 ​编辑 为什么icmp协议封装好数据后,还要 ...

  5. 常见的使用ICMP协议的命令

    本文将介绍几种使用ICMP协议的命令,这些命令在网络测试和排错都有重要的作用. 1.ping命令 ping命令是检查网络是否畅通的常用命令,使用 ping 主机ip 后返回的数据包如图: 我们输入pi ...

  6. Windows下禁止ping命令(禁用ICMP协议访问)

    怎么样禁止入,如何禁止Ping命令,关闭ping命令PING命令是个危险的命令,用它可以知道你的操作系统,IP等,为了安全禁PING是个很好的方法,也是防DDOS攻击的.应该是有外部网络试图连接你的U ...

  7. icmp协议_CCNA - Part7:网络层 - ICMP 应该是你最熟悉的协议了

    ICMP 协议 在之前网络层的介绍中,我们知道 IP 提供一种无连接的.尽力而为的服务.这就意味着无法进行流量控制与差错控制.因此在 IP 数据报的传输过程中,出现各种的错误是在所难免的,为了通知源主 ...

  8. ICMP协议服务器怎么开启关闭ICMP协议?

    一.ICMP协议简介 ICMP(Internet Control Message Protocol)Internet控制报文协议.它是TCP/IP协议簇的一个子协议,用于在IP主机.路由器之间传递控制 ...

  9. linux ssh关闭icmp,ICMP协议服务器怎么开启关闭ICMP协议?

    一.ICMP协议简介 ICMP(Internet Control Message Protocol)Internet控制报文协议.它是TCP/IP协议簇的一个子协议,用于在IP主机.路由器之间传递控制 ...

最新文章

  1. python3.6.4安装教程-python3.6.4如何安装到树莓派3代
  2. PHP自动加载类的实例
  3. python_day02 上节课知识点回顾
  4. iphone android传照片大小,iPhone与安卓跨平台如何传照片图文教程
  5. 给未来的自己一封信计算机,给未来的自己的一封信范文(精选5篇)
  6. java this关键字表示当前对象,可以访问属性、方法、构造方法
  7. MySQL抽稀_python安装mysql的依赖包mysql-python操作
  8. 于掌控板实现简单的抢答器系统
  9. Microsoft Dynamics CRM 2015 之安装SQL Server 2012过程中出现“启用windows功能NetFx3时出错...
  10. android 计算屏幕尺寸来区分phone和pad
  11. java游戏和flash游戏区别,小游戏的基本种类
  12. 中国象棋局面识别 -3. 棋谱字符串生成
  13. vue项目生成微信支付二维码(web端),其他二维码也可以生成
  14. linux下system函数
  15. 广州楼市:400W,高升值潜力的热门板块!
  16. android 重新编译内核,[原创]华为内核重新编译踩坑记
  17. 记账本app的需求分析
  18. L1-029 是不是太胖了 (5 分)C语言
  19. python实现矩阵转置,乘法。 不使用numpy模块
  20. Office2016只安装三件套方法(word,ppt,excel)

热门文章

  1. 移动网速测试数据及对比,附2019年北京移动校园卡套餐信息
  2. Winamp v5.5.0 Build 1640 Final 简体中文版 [烈火]
  3. 如何设计一份优秀的 PPT 文档?
  4. CASS11最新版免狗下载、安装教程
  5. 初中计算机教学校本教材,中学信息技术校本教材  (38页)-原创力文档
  6. 《敏捷个人》周刊 第11期 (可下载)
  7. 记忆的结构与存储方法
  8. 服务器搭建实战详解--电子邮件服务器之一--基础原理
  9. 记一次《龙之谷》手游代码分析
  10. JavaScript 实现LRU算法