python//网络嗅探器

python编写网络嗅探器

网络嗅探器

网络嗅探器又称网络监听器,简称Sniffer子系统,放置于网络节点上,对网络中的数据帧进行捕获的一种被动监听手段,是一种常用的收集有用信息的方法。

嗅探器原理

原理上来说,在一个实际的系统中,数据的收发是由网卡来完成的,网卡接收到传输来的数据,网卡内的单片程序接收数据帧的目的MAC地址,根据计算机上的网卡驱动程序设置的接收模式判断该不该接收,认为该接收就接收后产生中断信号通知CPU,认为不该接收就丢掉不管,所以不该接收的数据网卡就截断了,计算机根本就不知道。对于网卡来说一般有四种接收模式:
a)广播方式:该模式下的网卡能够接收网络中的广播信息。
b)组播方式:设置在该模式下的网卡能够接收组播数据。
c)直接方式:在这种模式下,只有目的网卡才能接收该数据。
d)混杂模式:在这种模式下的网卡能够接收一切通过它的数据,而不管该数据是否是传给它的。
首先,在以太网中是基于广播方式传送数据的,也就是说,所有的物理信号都要经过我的机器。其次,网卡可以置于一种模式叫混杂模式(promiscuous),在这种模式下工作的网卡能够接收到一切通过它的数据,而不管实际上数据的目的地址是不是他。
这就是SNIFF工作的基本原理:让网卡接收一切他所能接收的数据。

使用第三方scapy库 使用sniff()函数

sniff(count=0, store=1, offline=None, prn=None, lfilter=None, L2socket=None, timeout=None, opened_socket=None, stop_filter=None, iface=None, *arg, **karg)

返回PacketList类型的数据包对象;

count: 要捕获数据包的总数. 0 表示无限制;
store: 是否要保存捕获的数据包;
prn: 回调函数,会作用于每个数据包
ex: prn = lambda x: x.summary()
lfilter: 过滤函数,不满足条件的数据包会被丢弃;
ex: lfilter = lambda x: x.haslayer(Padding)
offline: 从pcap文件中读取数据包;
timeout: 捕获指定时间内的数据包;L2socket: 通过给定的 L2socket 进行数据捕获;
opened_socket: 通过给定的 socket 进行数据捕获;
stop_filter: 过滤函数,满足条件后将结束数据捕获;
ex: stop_filter = lambda x: x.haslayer(TCP)
iface: 指定端口或端口数组

模块分析

本软件使用的主要模块及其功能
1.抓包界面模块
2.抓包模块
3.数据包分析模块
4.界面控制模块
在这里插入图片描述

实现过程

分析算法:第一:得到数据包,先将其转存到内存里,以备以后再用。
第二:分析当前的数据包。
1.抓取数据包并保存。
2.处理抓到的数据包。
3.将抓到的数据包保存为pcap格式的文件。
4.绘制GUI界面。
第三:结束分析。

主函数分析

def capture_packet():
    # 设置过滤条件
    filters = fitler_entry.get()
    print("抓包条件:"+filters)
    # 设置停止抓包的条件stop_filter
    stop_sending.clear()
    global packet_list
    # 清空列表
    packet_list.clear()
    # 抓取数据包并将抓到的包存在列表中
    sniff(prn=(lambda x: process_packet(x)), filter=filters, stop_filter=(lambda x: stop_sending.is_set()))


分析:抓取数据包并对抓到的数据包进行相应处理。

ef process_packet(packet):
    if pause_flag == False:
        global packet_list
        # 将抓到的包存在列表中
        packet_list.append(packet)
       #packet.show()
        # 抓包的时间
        packet_time= timestamp2time(packet.time)
        src = packet[Ether].src
        dst = packet[Ether].dst
        type = packet[Ether].type
        types = {0x0800:'IPv4',0x0806:'ARP',0x86dd:'IPv6',0x88cc:'LLDP',0x891D:'TTE'}
        if type in types:
           proto = types[type]
        else:
             proto = 'LOOP'  # 协议
        # IP
        if proto == 'IPv4':
            # 建立协议查询字典
            protos = {1: 'ICMP', 2: 'IGMP', 4: 'IP', 6: 'TCP', 8: 'EGP', 9: 'IGP', 17: 'UDP', 41: 'IPv6', 50: 'ESP', 89:'OSPF'}
            src = packet[IP].src
            dst = packet[IP].dst
            proto=packet[IP].proto
            if proto in protos:
                proto=protos[proto]
        # tcp
        if TCP in packet:
            protos_tcp = {80: 'Http', 443: 'Https', 23: 'Telnet', 21: 'Ftp', 20: 'ftp_data', 22: 'SSH', 25: 'SMTP'}
            sport = packet[TCP].sport
            dport = packet[TCP].dport
            if sport in protos_tcp:
                proto = protos_tcp[sport]
            elif dport in protos_tcp:
                proto = protos_tcp[dport]
        elif UDP in packet:
            if packet[UDP].sport == 53 or packet[UDP].dport == 53:
                proto = 'DNS'
        length = len(packet)  # 长度
        info = packet.summary()  # 信息
        global packet_id  # 数据包的编号
        packet_list_tree.insert("", 'end', packet_id, text=packet_id,
                            values=(packet_id, packet_time, src, dst, proto, length, info))
        packet_list_tree.update_idletasks()  # 更新列表,不需要修改
        packet_id = packet_id + 1

分析:处理函数,依据protocols进行分层提取信息,将参数传入树状数据(packet_list_tree)中,在Frame中显示。

结果展示

在这里插入图片描述

  • 8
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值