设计并实现一个具有图形用户界面的网络嗅探器,可以对网卡抓到的 IP 数据包进行解析。
要求:
(1)设计一个类,实现网卡在混杂模式下的抓包。
(2)设计一个类,实现对抓到的数据包中的 IP 报文解析。
(3)设计一个图形化用户界面的 Python GUI 程序,调用(1)(2)设计的类,实现图形界面下的网络嗅探器。
Sniff 类的实现代码如下:
import socket
class Sniff:
def __init__(self,IP=socket.gethostbyname(socket.gethostname())):
HOST = IP
s = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.IPPROTO_IP)
s.bind((HOST,0))
s.setsockopt(socket.IPPROTO_IP,socket.IP_HDRINCL,1)
s.ioctl(socket.SIO_RCVALL,socket.RCVALL_ON)
self.s=s
def getIPPacket(self):
packet=self.s.recvfrom(65565)
packet=packet[0]
return packet
def __exit__(self):
self.s.ioctl(socket.SIO_RCVALL,socket.RCVALL_OFF)
IPParser 类的实现代码如下:
import socket
from struct import *
from time import ctime,sleep
from os import system
from Sniff import Sniff
class IPParser:
def getIPHParse(self,sniff):
iph_data=[]
self.packet=sniff.getIPPacket()
ip_header=self.packet[0:20]#截取数据包前20字节,即IP首部
iph=unpack('!BBHHHBBH4s4s',ip_header)#将IP首部按照指定的格式解包
time=ctime()
#解析IP首部各个字段
ip_version=iph[0]>>4#右移获取高四位,IPVersion
ihl=iph[0]&0xF #与1111与获取低四位
iph_length=ihl*4
ip_TOS=iph[1]
packet_length=iph[2]
ip_id=iph[3]
ip_off=iph[4]*0x1FFF
ttl=iph[5]
protocol=iph[6] #协议:1ICMP 6TCP 17UDP
ip_checksum=iph[7]
s_addr=socket.inet_ntoa(iph[8])
d_addr=socket.inet_ntoa(iph[9])
iph_data.append(time)
iph_data.append(str(ip_version))
iph_data.append(str(ihl))
iph_data.append(str(iph_length))
iph_data.append(str(ip_TOS))
iph_data.append(str(packet_length))
iph_data.append(str(ip_id))
iph_data.append(str(ip_off))
iph_data.append(str(ttl))
if protocol==1:
iph_data.append("1(ICMP)")
elif protocol==6:
iph_data.append("6(TCP)")
elif protocol==17:
iph_data.append("17(UDP")
iph_data.append(str(ip_checksum))
iph_data.append(str(s_addr))
iph_data.append(str(d_addr))
return iph_data
GUI 主程序实现
SniffGUI 程序如下所示:
from tkinter import *
from Sniff import *
from IPParser import *
from tkinter import messagebox
class SniffGUI:
def __init__(self):
window=Tk()
window.title("抓包体验")
Label(window,text="抓包体验:",font=('黑体',28,'bold')).pack()
framel=Frame(window)
framel.pack()
scrollbarx=Scrollbar(framel,orient="horizontal")
scrollbary=Scrollbar(framel,orient="vertical")
scrollbarx.pack(side="bottom",fill=X)
scrollbary.pack(side="right", fill=Y)
self.text=Text(framel,wrap='none',width=50,height=10,xscrollcommand=scrollbarx.set,yscrollcommand=scrollbary.set)
scrollbarx.config(command=self.text.xview)
scrollbary.config(command=self.text.yview)
self.text.pack()
self.text.insert('end',format('抓包时间','26s'))
self.text.insert('end', format('ip版本', '28s'))
self.text.insert('end', format('首部长度', '26s'))
self.text.insert('end', format('总长度', '27s'))
self.text.insert('end', format('区分服务', '26s'))
self.text.insert('end', format('报文长度', '26s'))
self.text.insert('end', format('标识', '28s'))
self.text.insert('end', format('片偏移', '28s'))
self.text.insert('end', format('生存时间', '26s'))
self.text.insert('end', format('协议', '26s'))
self.text.insert('end', format('校验和', '27s'))
self.text.insert('end', format('源IP地址', '27s'))
self.text.insert('end', format('目的IP地址', '26s'))
self.text.insert('end', '\n')
btSubmit=Button(window,text="开始抓包",padx=20,command=self.textSubmit)
btSubmit.pack()
window.mainloop()
def textSubmit(self):
messagebox.showinfo("提示","抓包开始")
mysniff=Sniff(" 10.84.83.21")
myipparse=IPParser()
iph_data=[]
packet_data=[]
iph_data=myipparse.getIPHParse(mysniff)
for i in range (len(iph_data)):
self.text.insert('end',format(iph_data[i],'30s'))
self.text.insert('end','\n')
SniffGUI()