发包工具
一、实现的功能
基于Python+scapy设计协议编辑器,基于Tkinter的Python GUI界面设计。实现了MAC、ARP、IP 、TCP、udp协议的编辑与发送,并且支持生成协议字段的默认值,支持用户输入协议字段值,发包前对协议字段的合理性进行检查,发包前自动计算并显示校验和,支持单次发包、多次发包,支持连续发包,连续发包时可随时停止和计算并显示数据包发送速度的功能。
注:
程序源代码:https://download.csdn.net/download/wmrem/10439779
运行前需要先安装第三方库scapy,安装方法:https://blog.csdn.net/wmrem/article/details/80004819
二、主要函数说明——IP包的编辑与发送为例
1.创建IP包编辑器界面,为每个按钮绑定单击响应时间。
def create_ip_sender():1.设置协议编辑器的界面
ip_fields = 'ip协议的版本:',…… , '目的IP地址:'
entries = create_protocol_editor(protocol_editor_panedwindow, ip_fields)
2.创建发送,默认值,清空按钮,并绑定功能
send_packet_button, reset_button, default_packet_button = create_bottom_buttons(protocol_editor_panedwindow)
3.为"回车键"的Press事件编写事件响应代码,发送IP包
tk.bind('<Return>', (lambda event: send_ip_packet(entries, send_packet_button))) # <Return>代表回车键
4.为"发送"、默认值、按钮的单击事件编写事件响应代码,发送IP包
send_packet_button.bind('<Button-1>', (
lambda event: send_ip_packet(entries, send_packet_button)))
…
2. 在协议字段编辑框中填入默认IP包的字段值,为IP数据包的发送做好准备
def create_default_ip_packet(entries):1.清空各字段的值
clear_protocol_editor(entries)
2.创建默认的IP数据包,并将其各字段的值填入协议编辑器的对应的文本框中
default_ip_packet = IP()
entries[0].insert(0, int(default_ip_packet.version))
…
3.获取协议编辑器文本框的值,创建对应的数据包并开启一个线程用于连续发送数据包。
def send_ip_packet(entries, send_packet_button):if 按钮为发送时:
1. 从协议编辑框中获取要发送的数据包的各个字段的值
ip_version = int(entries[0].get())
…
2.用获取的数据包的各字段的值创建相应的数据包
packet_to_send = IP(version=ip_version,……,src=ip_src, dst=ip_dst)
3.开一个线程用于连续发送数据包,并启动
t = threading.Thread(target=send_packet, args=(packet_to_send,))
t.start()
4.使协议导航树不可用
toggle_protocols_tree_state()
send_packet_button['text'] = '停止'
else 按钮为停止时:
5.按钮为停止时可以终止数据包发送线程
stop_sending.set()
6.恢复协议导航树可用
toggle_protocols_tree_state()
send_packet_button['text'] = '发送'
4.发送数据包的线程函数,并计算数据包发送速度
def send_packet(packet_to_send):stop_sending.clear()
1.计算待发送数据包的长度(用于计算发送速度)
packet_size = len(packet_to_send)
2.推导数据包的协议类型
3.计算发包开始发送时间点
begin_time = datetime.now()
4.连续发送数据包直到进程关闭
while 进程没有关闭:
if 发送Ether:
sendp(packet_to_send, verbose=0) # verbose=0,不在控制回显'Sent 1 packets'.
else:
send(packet_to_send, verbose=0)
5.计算发送的总字节数
total_bytes = packet_size * n
6.计算发包用的总时间
total_time = (end_time - begin_time).total_seconds()
7.计算发包的速度
bytes_per_second = total_bytes / total_time / 1024
三、基础知识准备
1.构造数据包,发送数据包——“/"运算符数据包的拼装,send()用于3层发包,可直接发送IP数据包,自动加以太帧;只发送以太帧使用sendp()。
2.计算校验和——IP包的校验和默认值为None,在IP包被发送时,其校验和被被自动计算并填充在IP包中
以下方式可以在发包前计算IP包的校验和,直接用packet.show2()命令也可以显示校验和。raw(packet)将数据包的内容转换为字节。
3.查看数据包的字段值(使用ls()),查看某层协议数据包对象支持的函数(使用help())
4.ls()列出scapy支持的所有数据包,协议;lsc()列出scapy支持的全部命令;conf列出scapy的当前配置。
四、主要功能实现代码——以IP包为例
1.创建IP包编辑器的界面
# 创建协议字段编辑区
def create_protocol_editor(root, field_names):
"""
创建协议字段编辑区
:param root: 协议编辑区
:param field_names: 协议字段名列表
:return: 协议字段编辑框列表
"""
entries = []
for field in field_names:
row = Frame(root)
label = Label(row, width=15, text=field, anchor='e')
entry = Entry(row, font=('Courier', '12', 'bold'), state='normal') # 设置编辑框为等宽字体
row.pack(side=TOP, fill=X, padx=5, pady=5)
label.pack(side=LEFT)
entry.pack(side=RIGHT, expand=YES, fill=X)
entries.APPend(entry)
return entries
def create_ip_sender():
"""
创建IP包编辑器
:return: None
"""
# IP帧编辑区
ip_fields = 'IP协议的版本:', '首部长度(5-15):', '区分服务:', '总长度:', '标识:', '标志(0-2)DF,MF:', \
'片偏移:', '生存时间:', '协议(数据部分):', '首部校验和:', '源IP地址:', '目的IP地址:'
entries = create_protocol_editor(protocol_editor_panedwindow, ip_fields)
send_packet_button, reset_button, default_packet_button = create_bottom_buttons(protocol_editor_panedwindow)
# 为"回车键"的Press事件编写事件响应代码,发送ARP包
tk.bind('<Return>', (lambda event: send_ip_packet(entries, send_packet_button))) # <Return>代表回车键
# 为"发送"按钮的单击事件编写事件响应代码,发送ARP包
send_packet_button.bind('<Button-1>', (
lambda event: send_ip_packet(entries, send_packet_button))) # <Button-1>代表鼠标左键单击
# 为"清空"按钮的单击事件编写事件响应代码,清空协议字段编辑框
reset_button.bind('<Button-1>', (lambda event: clear_protocol_editor(entries)))
# 为"默认值"按钮的单击事件编写事件响应代码,在协议字段编辑框填入ARP包字段的默认值
default_packet_button.bind('<Button-1>', (lambda event: create_default_ip_packet(entries)))
2.在协议字段编辑框中填入默认IP包的字段值,填入前需要先清空当前值。
def clear_protocol_editor(entries):
"""
清空协议编辑器的当前值
:param entries: 协议字段编辑框列表
:return: None
"""
for entry in entries:
# 如果有只读Entry,也要清空它的当前值
state = entry['state']
entry['state'] = 'normal'
entry.delete(0, END)
entry['state'] = state
# 当前网卡的默认网关
default_gateway = [a for a in os.popen('route print').readlines() if ' 0.0.0.0 ' in a][0].split()[-3]
def create_default_ip_packet(entries):
"""
在协议字段编辑框中填入默认IP包的字段值
:param entries: 协议字段编辑框列表
:return: None
"""
clear_protocol_editor(entries)
default_ip_packet = IP()
entries[0].insert(0, int(default_ip_packet.version))
entries[1].insert(0, 5)
entries[3].insert(0, 20)
entries[2].insert(0, hex(default_ip_packet.tos))
entries[4].insert(0, int(default_ip_packet.id))
entries[5].insert(0, int(default_ip_packet.flags))
entries[6].insert(0, int(default_ip_packet.frag))
entries[7].insert(0, int(default_ip_packet.ttl))
entries[8].insert(0, int(default_ip_packet.proto))
entries[9]['state'] = NORMAL # 可操作
entries[9].insert(0, "单机发送时自动计算")
entries[9]['state'] = disableD # 不可操作
# 目标IP地址设成本地默认网关
entries[11].insert(0, default_gateway)
default_ip_packet = IP(dst=entries[11].get())#可以省略
entries[10].insert(0, default_ip_packet.src)
3.发送IP包
def send_ip_packet(entries, send_packet_button):
"""
发IP包
:param entries:
:param send_packet_button:
:return:
"""
if send_packet_button['text'] == '发送':
ip_version = int(entries[0].get())
ip_ihl = int(entries[1].get())
ip_tos = int(entries[2].get(), 16)
ip_len = int(entries[3].get())
ip_id = int(entries[4].get())
ip_flags = int(entries[5].get())
ip_frag = int(entries[6].get())
ip_ttl = int(entries[7].get())
ip_proto = int(entries[8].get())
ip_src = entries[10].get()
ip_dst = entries[11].get()
# ip_options = entries[12].get()
packet_to_send = IP(version=ip_version, ihl=ip_ihl, tos=ip_tos, len=ip_len, id=ip_id,
frag=ip_frag, flags=ip_flags, ttl=ip_ttl, proto=ip_proto, src=ip_src, dst=ip_dst)
packet_to_send = IP(raw(packet_to_send))
entries[9]['state'] = NORMAL # 重新激活
entries[9].delete(0, END)
entries[9].insert(0, hex(packet_to_send.chksum))
entries[9]['state'] = DISABLED # 不可操作
# 开一个线程用于连续发送数据包
t = threading.Thread(target=send_packet, args=(packet_to_send,))
t.setDaemon(True)
t.start()
# 使协议导航树不可用
toggle_protocols_tree_state()
send_packet_button['text'] = '停止'
else:
# 终止数据包发送线程
stop_sending.set()
# 恢复协议导航树可用
toggle_protocols_tree_state()
send_packet_button['text'] = '发送'
4.线程中运行的用于发送数据包的函数,可以计算发包速度
def send_packet(packet_to_send):
"""
在我们给出的发包程序中,如果电脑速度太快,send_packet函数中的send(...)函数执行前后,
datetetime返回的begin_time和end_time可能是相同的,结果会报除零错误,所以,send_packet函数应该做修改
用于发送数据包的线程函数,持续发送数据包
:type packet_to_send: 待发送的数据包
"""
# print(packet.show(dump=True))
# 对发送的数据包次数进行计数,用于计算发送速度
n = 0
stop_sending.clear()
# 待发送数据包的长度(用于计算发送速度)
packet_size = len(packet_to_send)
# 推导数据包的协议类型
proto_names = ['TCP', 'UDP', 'ICMP', 'IP', 'ARP', 'Ether', 'Unknown']
packet_proto = ''
for pn in proto_names:
if pn in packet_to_send:
packet_proto = pn
break
# 开始发送时间点
begin_time = datetime.now()
while not stop_sending.is_set():
if isinstance(packet_to_send, Ether):
sendp(packet_to_send, verbose=0) # verbose=0,不在控制回显'Sent 1 packets'.
else:
send(packet_to_send, verbose=0)
n += 1
end_time = datetime.now()
total_bytes = packet_size * n
#修改
total_time = (end_time - begin_time).total_seconds()
if total_time == 0:
total_time = 2.23E-308 # 当begin_time和end_time相等时,将total_time设为IEEE 745标准中规定的最小浮点数
bytes_per_second = total_bytes / total_time / 1024
# bytes_per_second = total_bytes / ((end_time - begin_time).total_seconds()) / 1024
status_bar.set('已经发送了%d个%s数据包, 已经发送了%d个字节,发送速率: %0.2fK字节/秒',
n, packet_proto, total_bytes, bytes_per_second)
五、运行结果
相关阅读
动态性网页页面的开发环境依据开发设计视频语音不一样而不一样,关键的方法取决于Python开发设计、JSP开发设计和ASP开发设计的
黑客技术一度被认为是一个神秘的特有领域,随着技术的进步和领域环境的进步,它已经成为一种非常普遍的现象。黑客技术可以用于有害目
在Excel中经常会使用到绘图工具,但可能有些时候手滑点错了,把绘图工具点没了,下面是seo实验室小编带来的关于把excel 2010绘图工具调
ab是一种用于测试Apache超文本传输协议(HTTP)服务器的工具。apache自带ab工具,可以测试apache、IIs、tomcat、nginx等服务器但是ab没
手淘中猜你喜欢流量占比非常高,所以商家不得不越来越重视推荐的流量。淘宝商家想要想要更多获取猜你喜欢流量,图片精细化的运营自然