网络嗅探器程序设计

一、实验目的

(1) 理解网络嗅探器的基本工作原理与实现方法。
(2) 掌握Raw Socket的基本工作原理。
(3) 掌握TCP/IP、ICMP等协议及Socket编程方法。

二、实验要求

(1) 利用原始套接字编写一个网络嗅探器捕获网络数据包。
(2) 分析基本的数据报信息。
(3) 实现简单的过滤器功能。

三、实验思路

先一直嗅探到达网卡的数据,记录并保存下来,然后停止嗅探;根据需要对数据进行筛选。

四、实验源码

# -*- coding: utf-8 -*-
"""
    简单嗅探器的实现
    @author WQ
    @time 2021/5/7
"""
import socket
pcaps=[]
#捕获
def sniffIpData(ip):
    #host_ip = socket.gethostbyname(socket.gethostname())           
    host_ip=ip  #获取IP 即设置要捕获的网卡
    sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP) #创建套接字、可接受协议类型为UDP、TCP、ICMP、IP
    sniffer.bind((host_ip, 0))
    sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) #设置套接字options、包装ip头部
    sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)          #接受所有的数据,设置网卡为混杂模式
    print("[*]正在嗅探数据.....") 
    count=10
    while count:
        recv_data, addr = sniffer.recvfrom(1500)    #接收数据,缓冲区为1500
        if recv_data:
            try:
                decodeIpData(recv_data)
            except:
                continue
        else:
            continue
        count-=1
    sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)			# 关闭混杂模式
    sniffer.close() #关闭套接字
    return recv_data
#提取协议名
def check_protocol(flag):
    if flag==1:
        reasult="ICMP"
    elif flag==2:
        reasult="IGMP"
    elif flag==6:
        reasult="TCP"
    elif flag==17:
        reasult="UDP"
    elif flag==89:
        reasult="OSPF"
    else:
        reasult=flag
    return reasult
#解析
def decodeIpData(package):
    ip_data = {
    
    }
    #RFC791
    ip_data['version'] = package[0] >> 4                            #版本
    ip_data['headLength'] = package[0] & 0x0f                       #头长度  #& 按位与操作
    ip_data['DSField'] = package[1]                                 # Tos服务字段
    ip_data['totalLength'] = (package[2] << 8) + package[3]         #总长度
    ip_data['identification'] = (package[4] << 8) + package[5]      #标识分片
    ip_data['flag'] = package[6] >> 5                               #标志位
    ip_data['moreFragment'] = ip_data['flag'] & 1                   #标识后面可否还有分片
    ip_data['dontFragment'] = (ip_data['flag'] >> 1) & 1            #能否分片 0可分片
    ip_data['fragmentOffset'] = ((package[6] & 0x1f) << 8) + package[7] #片偏移
    ip_data['TTL'] = package[8]                                     #生存周期
    ip_data['protocol'] = check_protocol(package[9])                #协议 其中1,标识ICMP、2标识IGMP、6标识TCP、17标识UDP、89标识OSPF。
    ip_data['headerCheckSum'] = (package[10] << 8) + package[11]    #校验和
    #以IP地址形式存储
    ip_data['sourceAddress'] = "%d.%d.%d.%d" % (package[12], package[13], package[14], package[15])
    ip_data['destinationAddress'] = "%d.%d.%d.%d" % (package[16], package[17], package[18], package[19])
    ip_data['options'] = []                                         #可选项
    #根据headerLength求出options
    if ip_data['headLength'] > 5:                                   #一般来说此处的值为0101,表示头长度为20字节、若超出则大于5(0101)
        temp = 5
        while temp < ip_data['headLength']:
            ip_data['options'].append(package[temp * 4] + 0)
            ip_data['options'].append(package[temp * 4] + 1)
            ip_data['options'].append(package[temp * 4] + 2)
            ip_data['options'].append(package[temp * 4] + 3)
            temp += 1
    #根据totalLength求出data
    ip_data['data'] = ""
    temp = ip_data['headLength'] * 4
    while temp < ip_data['totalLength']:
        ip_data['data']+=(str(hex(package[temp])).upper().replace("0X",""))
        temp += 1
    pcaps.append(ip_data)
    #for i in ip_data.keys():
        #print("{}:{}".format(i,ip_data[i]))
    return ip_data
#过滤
def filter(options=1):
    if options==1:
        for pcap in pcaps:
            for i in pcap.keys():
                print("{}:{}".format(i,pcap[i]))
            print("\n")
    elif options==2:
        source=input("请输入源IP地址:")
        dest=input("请输入目的IP地址:")
        index=0
        for pcap in pcaps:
            if pcap["sourceAddress"] == source and pcap["destinationAddress"]==dest:
                index+=1
                print("第{}条记录".format(index))
                for i in pcap.keys():
                    print("{}:{}".format(i,pcap[i]))
                print("\n")     
        if index==0:
            print("IP输入错误或者无该记录!")
    elif options==3:
        protocol=input("请输入协议名:")
        index=0
        for pcap in pcaps:
            if pcap['protocol']==protocol:
                index+=1
                print("第{}条记录".format(index))
                for i in pcap.keys():
                    print("{}:{}".format(i,pcap[i]))
                print("\n")    
        if index==0:
            print("协议名错误或无该记录!")
#开始捕获
def sniffer(target):
    sniffIpData(ip=target)
    print('''
    ----菜单
    
    --------1. 输出全部记录(默认)
    --------2. 根据IP筛选
    --------3. 根据协议筛选
    --------4. 退出
    ''')
    while True:
        options=int(input("输入选项:"))
        if options==4:
            break
        filter(options)
target=input("请输入要嗅探网卡的IP:")
sniffer(target)

五、实验结果
在这里插入图片描述
在这里插入图片描述
根据协议进行筛选数据:
在这里插入图片描述
根据IP地址筛选:
在这里插入图片描述

Guess you like

Origin blog.csdn.net/weixin_44033675/article/details/118154865