把本学期所学的知识,自己做的课程设计,分享一下。
原理
IP首部检验和原理:在发送方,先把IP数据报首部划分为许多16位字的序列,并把检验和字段置零。用反码算术运算把所有16位字相加后,将得到的和的反码写入检验和字段。接收方收到数据报后,将首部的所有16位字再使用反码算术运算相加一次。将得到的和取反码,即得出接收方检验和的计算结果。若首部未发生任何变化,则此结果必为0,于是就保留这个数据报。否则即认为出差错,并将此数据报丢弃。
程序流程图

代码
from scapy.all import *
import struct
ipNum = 0
def sumcheck(head, ichksum):
# 置0
checksum = 0
# IPV4报文头部长度
headlen = len(head)
print("IPV4报文头部长度:", headlen)
if headlen % 2 == 1:
head += b"\0" #加多一个字节8位
s = 0
# 把存在字符串head解析出来,!表示使用网络字节顺序解析, H表示一个unsigned short
while s < headlen:
t = struct.unpack('!H', head[s:s + 2])[0] #每次解析两个字节即16位
# 将解析的16位赋值给checksum
checksum = checksum + t
s = s + 2 #长度+2
# 减去掉校验和,即累加和的检验和字段置0
checksum = checksum - ichksum
#进位处理
while ((checksum >> 16) > 0):
# 高16位加到低位
checksum = (checksum >> 16) + (checksum&0xffff)
#反码并强制转换位16进制
checksum=~checksum & 0xffff
return checksum
if __name__ == "__main__":
print
'开始抓包'
# 下面的iface是电脑网卡的名称 count是捕获报文的数目
dpkt = sniff(iface="Realtek PCIe FE Family Controller",count=100 )
print(
'抓包成功')
#备份pcap文件,dpkt 是上面抓取的流量变量
wrpcap("g://P.pcap", dpkt)
print
'保存抓包完成'
#还原之前保存的pcap文件
pcks = rdpcap('g://P.pcap')
print
'解析pcap包'
ArpNum = 0
IcmpNum = 0
ipNum = set()
for p in pcks:
status1 = p.payload.name # 可能是ARP的报文
status2 = p.payload.payload.name # 可能是TCP报文 也可能是ICMP的报文
if status1 == 'IP':
ipNum.add(p.payload.src) # 将ip报文的源地址,和目的地址存在set集合里面(set去重)
ipNum.add(p.payload.dst) # 将目的地址存在set集合里面
print("********** IP ******************************")
print("版本(4位): %s" % p[IP].version)
print("首部长度(4位): %s" % p[IP].ihl)
print("区分服务(8位): %s" % hex(p[IP].tos))
print("报文总长度(16位):%s" % p[IP].len)
print("标识(16位):%s" % p[IP].id) # IP分片标识重组
print("标志(3位): %s" % p[IP].flags) # MF=1还有分片,MF=0,后面没有分片了,DF=0允许分片
print("段偏移(13位): %s" % p[IP].frag)
print("生存时间(8位): %s" % p[IP].ttl)
print("上层协议类型(8位):%s " % p[IP].proto)
print("校验和(16位): %s" % hex(p[IP].chksum))
print("源IP地址: %s" % p[IP].src)
print("目的IP地址: %s" % p[IP].dst)
print("**********IP检验和检验********************")
Ippack = p[Ether].payload
checksum = p[IP].chksum # 取出校验和
print("IP首部的校验和是:%s" % hex(checksum))
x = raw(Ippack)
#以分割符" "返回一个字符串
ipString = "".join("%02x" % orb(x) for x in x)
#ip首部长度
headlen = p[IP].ihl * 4 * 2
#遍历出以" "为分割符的字符串
showIp = ipString[0:headlen]
#输出该字符串
print("IP报文头部信息:%s" % showIp)
bytess = bytearray.fromhex(showIp)
#得到检验和
checksum3= sumcheck(bytess, checksum)
print("验证IP首部的检验和:%s" % hex(checksum3))
#发送方16位累加和
checksum4=~checksum3&0xffff
print("发送方16位累加和为 %s" % hex(checksum4))
#得到接收方16位累加和
checksum5=(checksum3&0xffff)+(checksum4&0xffff)
print("接收方累加和 %s"% hex(checksum5))
#对运算和取反码,若首部未发生任何变化,则此结果必然为0,保留此数据报。否则认为出错,丢弃此数据报。
jchecksum=~checksum5&0xffff
print("接收方检验和的计算结果为: %s"%jchecksum)
if (jchecksum == 0):
print("IP检验和正确")
else:
print("IP检验和不正确")
else:
if status2=="ICMP":
print("********** ICMP ********************")
p.show()
IcmpNum=IcmpNum+1
if status1=="ARP":
print("********** ARP ********************")
p.show()
ArpNum=ArpNum+1
print('IP:' + str(len(ipNum))+"个" ' ARP:' + str(ArpNum)+"个"+' ICMP:' + str(IcmpNum )+"个") # 报文数量的输出
需要导入SCAPY库,这个自行百度!

本文分享了一次课程设计,通过Scapy库解析并实现了IP首部检验和的计算过程。首先解释了IP首部检验和的原理,即在发送端将首部16位字相加取反码填入,接收端重新计算和取反码,如果结果为0则表明无错误。接着,介绍了程序的流程,并提示读者自行搜索并导入所需的SCAPY库。
1万+

被折叠的 条评论
为什么被折叠?



