无聊写的,用来抓取未知对端设备的IP地址(仅适用于会发送免费ARP包的设备)
全部代码。
import threading
import tkinter as tk
from tkinter.ttk import Treeview, Combobox, Button, Entry, Scale, Style
from scapy.all import sniff
from scapy.layers.l2 import Ether
from scapy.layers.l2 import ARP
import psutil
class PacketSnifferController:
def __init__(self):
self.win = None
self.packet_count = 10 # 默认捕获数据包数量
def init(self, win):
self.win = win
def start_sniffing(self):
# 获取用户设置的数据包数量
self.packet_count = self.win.tk_input_lrg2klel.get()
# 启动数据包嗅探线程
sniff_thread = threading.Thread(target=self.sniff_packets)
sniff_thread.start()
def sniff_packets(self):
selected_interface = self.win.tk_select_box_lrg2i35c.get()
print(self.packet_count,selected_interface)
# 设置捕获条件,可以根据需要进行修改
# 在这个例子中,只捕获前 self.packet_count 个 ARP 数据包
packets = sniff(iface=selected_interface, count=int(self.packet_count), filter="arp", stop_filter=None)
# 处理捕获到的数据包
for packet in packets:
self.packet_callback(packet)
def packet_callback(self, packet):
# 获取捕获的数据包信息
captured_info = (
packet[Ether].dst,
packet[Ether].src,
packet[Ether].type,
packet[ARP].hwtype,
packet[ARP].ptype,
packet[ARP].hwlen,
packet[ARP].plen,
packet[ARP].op,
packet[ARP].hwsrc,
packet[ARP].psrc,
packet[ARP].hwdst,
packet[ARP].pdst
)
print("Captured info before insertion:", captured_info) # 调试输出
# 插入新行数据,从第一列开始
self.win.tk_table_lrg2fz4k.insert("", tk.END, values=captured_info)
class WinGUI(tk.Tk):
def __init__(self):
super().__init__()
self.__win()
self.tk_button_lrg2fjic = self.__tk_button_lrg2fjic(self)
self.tk_table_lrg2fz4k = self.__tk_table_lrg2fz4k(self)
self.tk_label_lrg2h7am = self.__tk_label_lrg2h7am(self)
self.tk_select_box_lrg2i35c = self.__tk_select_box_lrg2i35c(self)
self.tk_frame_lrg2jofg = self.__tk_frame_lrg2jofg(self)
self.tk_input_lrg2klel = self.__tk_input_lrg2klel(self.tk_frame_lrg2jofg)
self.tk_scale_lrg2krvw = self.__tk_scale_lrg2krvw(self.tk_frame_lrg2jofg)
self.tk_label_lrg2l0vn = self.__tk_label_lrg2l0vn(self.tk_frame_lrg2jofg)
def __win(self):
self.title("数据包嗅探器")
# 设置窗口大小、居中
width = 1600
height = 500
screenwidth = self.winfo_screenwidth()
screenheight = self.winfo_screenheight()
geometry = '%dx%d+%d+%d' % (width, height, (screenwidth - width) / 2, (screenheight - height) / 2)
self.geometry(geometry)
self.resizable(width=False, height=False)
def scrollbar_autohide(self, vbar, hbar, widget):
"""自动隐藏滚动条"""
def show():
if vbar: vbar.lift(widget)
if hbar: hbar.lift(widget)
def hide():
if vbar: vbar.lower(widget)
if hbar: hbar.lower(widget)
hide()
widget.bind("<Enter>", lambda e: show())
if vbar: vbar.bind("<Enter>", lambda e: show())
if vbar: vbar.bind("<Leave>", lambda e: hide())
if hbar: hbar.bind("<Enter>", lambda e: show())
if hbar: hbar.bind("<Leave>", lambda e: hide())
widget.bind("<Leave>", lambda e: hide())
def v_scrollbar(self, vbar, widget, x, y, w, h, pw, ph):
widget.configure(yscrollcommand=vbar.set)
vbar.config(command=widget.yview)
vbar.place(relx=(w + x) / pw, rely=y / ph, relheight=h / ph, anchor='ne')
def h_scrollbar(self, hbar, widget, x, y, w, h, pw, ph):
widget.configure(xscrollcommand=hbar.set)
hbar.config(command=widget.xview)
hbar.place(relx=x / pw, rely=(y + h) / ph, relwidth=w / pw, anchor='sw')
def create_bar(self, master, widget, is_vbar, is_hbar, x, y, w, h, pw, ph):
vbar, hbar = None, None
if is_vbar:
vbar = tk.Scrollbar(master)
self.v_scrollbar(vbar, widget, x, y, w, h, pw, ph)
if is_hbar:
hbar = tk.Scrollbar(master, orient="horizontal")
self.h_scrollbar(hbar, widget, x, y, w, h, pw, ph)
self.scrollbar_autohide(vbar, hbar, widget)
def __tk_button_lrg2fjic(self, parent):
btn = Button(parent, text="开始嗅探", takefocus=False)
btn.place(x=520, y=71, width=67, height=30)
return btn
def __tk_table_lrg2fz4k(self, parent):
# 表头字段 表头宽度
columns = {"目的地址": 119, "源地址": 179, "类型": 100, "硬件类型": 100, "协议类型": 100, "硬件地址长度": 130,
"协议地址长度": 130, "操作码": 100, "源硬件地址": 150, "源协议地址": 150, "目的硬件地址": 150,
"目的协议地址": 150}
tk_table = Treeview(parent, show="headings", columns=list(columns))
for text, width in columns.items(): # 批量设置列属性
tk_table.heading(text, text=text, anchor='center')
tk_table.column(text, anchor='center', width=width, stretch=False) # stretch 不自动拉伸
tk_table.place(x=0, y=166, width=1600, height=334)
return tk_table
def __tk_label_lrg2h7am(self, parent):
label = tk.Label(parent, text="选择网络接口:", anchor="center")
label.place(x=11, y=14, width=112, height=30)
return label
def __tk_select_box_lrg2i35c(self, parent):
cb = Combobox(parent, state="readonly", values=list(psutil.net_if_stats().keys()))
cb.place(x=138, y=16, width=150, height=30)
return cb
def __tk_frame_lrg2jofg(self, parent):
frame = tk.Frame(parent)
frame.place(x=312, y=2, width=200, height=150)
return frame
def __tk_input_lrg2klel(self, parent):
ipt = Entry(parent)
ipt.insert(0, "10") # 设置默认值为 "10"
ipt.place(x=153, y=100, width=41, height=30)
return ipt
def __tk_scale_lrg2krvw(self, parent):
scale = Scale(parent, orient=tk.HORIZONTAL, from_=1, to=100, command=self.update_entry_value)
scale.place(x=11, y=98, width=130, height=30)
return scale
def update_entry_value(self, value):
try:
int_value = int(float(value))
self.tk_input_lrg2klel.delete(0, tk.END)
self.tk_input_lrg2klel.insert(0, str(int_value))
except ValueError:
# 处理无效值的情况,可以在这里添加适当的错误处理或默认值
pass
def __tk_label_lrg2l0vn(self, parent):
label = tk.Label(parent, text="捕获数据包数量", anchor="center")
label.place(x=10, y=28, width=180, height=30)
return label
class Win(WinGUI):
def __init__(self, controller):
self.ctl = controller
super().__init__()
self.__event_bind()
self.__style_config()
self.ctl.init(self)
def __event_bind(self):
self.tk_button_lrg2fjic.config(command=self.ctl.start_sniffing)
def __style_config(self):
# 设置 Treeview 样式
style = Style()
style.configure("Treeview", rowheight=30)
style.configure("Treeview.Heading", font=("Arial", 10, "bold"))
if __name__ == "__main__":
controller = PacketSnifferController()
win = Win(controller)
win.mainloop()