Scapy抓包以及IP首部检验和计程序实现Python实现

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

把本学期所学的知识,自己做的课程设计,分享一下。

原理

     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库,这个自行百度!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

5210丫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值