如何计算icmp校验和

前几天看到大佬写的一篇关于icmp远控后门文章,对icmp协议充满了激情,通过查阅资料了解相关所需的知识,实现整个程序首先要了解imcp包请求与回复,在整个请求中最先就涉及到icmp包的构造,然而本章简要讨论校验和,然后将详细通过python编程计算校验和。(后续)


什么是Checksum?

校验和基本上是一个从数据包计算出来的值来检查其完整性。通过完整性,我们可以检查收到的数据是否没有错误。这是因为在网络上传输时,数据包可能会损坏,并且接收端必须知道数据是否已损坏。这是校验和字段添加到报文的原因。在源端,计算校验和并将其作为字段设置在报文中。在目标端,再次计算校验和,并用报文中现有的校验和值进行交叉检查,看看数据包是否正常。


ICMP报文结构

这里写图片描述


校验和说明

参考TCP/IP卷一P26页
这里写图片描述

  1. 将校验和字段置为0。
  2. 将每两个字节(16位)相加(二进制求和)直到最后得出结果,若出现最后还剩一个字节继续与前面结果相加。
  3. (溢出)将高16位与低16位相加,直到高16位为0为止。
  4. 将最后的结果(二进制)取反。
    参考一篇很详细计算IP校验和的例子

wireshark抓取icmp包

这里写图片描述


计算Icmp校验和

imcp报文:

08 00 4d 5a 00 01 00 01 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

校验和是“4d 5a”

将校验和字段置为0

08 00 00 00 00 01 00 01 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 + 0001 + 6162 + 6364 + 6566 + 6768 + 696a + 6b6c +6d6e + 6f70 + 7172 + 7374 + 7576 + 7761 + 6263 + 6465 + 6667 + 6869 =5a4d42418

【2019/12/5更新】
计算反码得到:

hex(~42418 & 0xffff) --> 0x5a4d

主机字节序转网络字节序列(参考小端序大端序

5a4d ---> 4d5a


附上程序

#!/usr/bin/python3.6.4
#-*-coding:utf-8-*-
__author__ = 'Rosefinch'
__date__ = '2018/5/31 10:32'


def chesksum(data):
	"""
	校验
	"""
	n = len(data)
	m = n % 2 #判断data长度是否是偶数字节
	sum = 0 #记录(十进制)相加的结果
	for i in range(0, n - m ,2): #将每两个字节(16位)相加(二进制求和)直到最后得出结果
		sum += ord(data[i]) + (ord(data[i+1]) << 8)#传入data以每两个字节(十六进制)通过ord转十进制,第一字节在低位,第二个字节在高位
	if m: #传入的data长度是奇数,将执行,且把这个字节(8位)加到前面的结果
		sum += ord(data[-1])
	#将高于16位与低16位相加
	sum = (sum >> 16) + (sum & 0xffff)
	sum += (sum >> 16) #如果还有高于16位,将继续与低16位相加
	answer = ~sum & 0xffff#对sum取反(返回的是十进制)
	#主机字节序转网络字节序列(参考小端序转大端序)
	answer = answer >> 8 | (answer << 8 & 0xff00)
	return answer #最终返回的结果就是wireshark里面看到的checksum校验和

if __name__ == "__main__":
	# data = "\x08\x00\x00\x01\x00\x01\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x61\x62\x63\x64\x65\x66\x67\x68\x69"
	data_type = '\x08' # ICMP Echo Request
	data_code = '\x00' # must be zero
	data_checksum = '\x00\x00' # "...with value 0 substituted for this field..."
	data_ID = '\x00\x01' #Identifier
	data_Sequece = '\x00\x01' #Sequence number
	payload_body = 'abcdefghijklmnopqrstuvwabcdefghi' #data
	icmp_message = data_type + data_code + data_checksum + data_ID + data_Sequece + payload_body

	int_ = chesksum(icmp_message)
	print('{:d} --->  {:x}'.format(int_,int_))

19802 ---> 4d5a


参考:
https://tools.ietf.org/html/rfc1071
http://www.ietf.org/rfc/rfc1071.txt
https://stackoverflow.com/questions/20905770/checksum-icmp-python-with-wireshark
https://www.thegeekstuff.com/2012/05/ip-header-checksum/
https://zh.wikipedia.org/wiki/%E4%BA%92%E8%81%94%E7%BD%91%E6%8E%A7%E5%88%B6%E6%B6%88%E6%81%AF%E5%8D%8F%E8%AE%AE

  • 29
    点赞
  • 108
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值