python//網絡嗅探器

python編寫網絡嗅探器

網絡嗅探器

網絡嗅探器又稱網絡監聽器,簡稱Sniffer子系統,放置於網絡節點上,對網絡中的數據幀進行捕獲的一種被動監聽手段,是一種經常使用的收集有用信息的方法。python

嗅探器原理

原理上來講,在一個實際的系統中,數據的收發是由網卡來完成的,網卡接收到傳輸來的數據,網卡內的單片程序接收數據幀的目的MAC地址,根據計算機上的網卡驅動程序設置的接收模式判斷該不應接收,認爲該接收就接收後產生中斷信號通知CPU,認爲不應接收就丟掉無論,因此不應接收的數據網卡就截斷了,計算機根本就不知道。對於網卡來講通常有四種接收模式:
a)廣播方式:該模式下的網卡可以接收網絡中的廣播信息。
b)組播方式:設置在該模式下的網卡可以接收組播數據。
c)直接方式:在這種模式下,只有目的網卡才能接收該數據。
d)混雜模式:在這種模式下的網卡可以接收一切經過它的數據,而無論該數據是不是傳給它的。
首先,在以太網中是基於廣播方式傳送數據的,也就是說,全部的物理信號都要通過個人機器。其次,網卡能夠置於一種模式叫混雜模式(promiscuous),在這種模式下工做的網卡可以接收到一切經過它的數據,而無論實際上數據的目的地址是否是他。
這就是SNIFF工做的基本原理:讓網卡接收一切他所能接收的數據。web

使用第三方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.界面控制模塊
在這裏插入圖片描述app

實現過程

分析算法:第一:獲得數據包,先將其轉存到內存裏,以備之後再用。
第二:分析當前的數據包。
1.抓取數據包並保存。
2.處理抓到的數據包。
3.將抓到的數據包保存爲pcap格式的文件。
4.繪製GUI界面。
第三:結束分析。socket

主函數分析

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()))

分析:抓取數據包並對抓到的數據包進行相應處理。tcp

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中顯示。svg

結果展現

在這裏插入圖片描述