对于GUI工具的理解:
首先要有一个模板
对比命令行下的工具,图形化的工具要有事件响应(比如邮件列出菜单)
import tkinter as tk from tkinter.filedialog import * import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) class App(Frame): def __init__(self,master=None): super(App, self).__init__() super().__init__(master) self.master=master self.var = tk.StringVar() self.zapi = "oI5pPuvuGPF5CSSRzCzk4WB8rvIYUkmM" self.initUI() self.textpad=None self.Create() self.pack() def Create(self): menubar=Menu(root) menuFile=Menu(menubar) menubar.add_cascade(label="options",menu=menuFile) menuFile.add_command(label="shellcode",accelerator="ctrl+a",command=self.test) menubar.add_cascade(label="test",menu=menuFile) menuFile.add_command() menuFile.add_command(label="open",accelerator="ctrl+b",command=self.fileopen) menuFile.add_command(label="save",accelerator="ctrl+c",command=self.filesave) menuFile.add_command(label="new",accelerator="ctrl+d",command=self.filenew) root["menu"]=menubar self.textpad=Text(root,width=200,height=10) self.textpad.pack() self.contextMenu=Menu(root) //右键事件 self.contextMenu.add_command(label="一键装逼",command=self.zha) self.contextMenu.add_command(label="bg",command=self.openAskColor) root.bind("<Button-3>",self.createCon) def zha(self): pass def openAskColor(self): pass def fileopen(self): pass def filesave(self): pass def filenew(self): pass def createCon(self,event): self.contextMenu.post(event.x_root,event.y_root) def test(self): pass def initUI(self): group_top = tk.LabelFrame(self, padx=15, pady=10) group_top.pack(padx=10, pady=5) tk.Button(group_top, text="scanIP", width=10, command=self.scanIP).grid(row=0, column=1) self.path_entry = tk.Entry(group_top, width=30) self.path_entry.grid(row=0, column=0, pady=5, padx=5) //添加按钮 tk.Button(group_top, text="开始执行", width=10, command=self.func).grid(row=1, column=1, sticky=tk.E) tk.Button(group_top, text="停止", width=10, command=self.destroy).grid(row=1, column=0, sticky=tk.W) console_frame = tk.Frame(group_top).grid(row=2, column=0, columnspan=2) self.console_text = tk.Text( console_frame, fg="green", bg="black", width=40, height=20, state=tk.DISABLED) scrollbar = tk.Scrollbar(console_frame, command=self.console_text.yview) self.console_text.pack(expand=1, fill=tk.BOTH) self.console_text['yscrollcommand'] = scrollbar.set def output_to_console(self, new_text): self.console_text.config(state=tk.NORMAL) self.console_text.insert(tk.END, new_text) self.console_text.see(tk.END) self.console_text.config(state=tk.DISABLED) def func(self): pass def usage(self): A = """ __ .__ .___ .___ .__ ____________ | | _|__| __| _/__| _/____ |__| / ___/\____ \| |/ / |/ __ |/ __ |\__ \ | | \___ \ | |_> > <| / /_/ / /_/ | / __ \| | /____ >| __/|__|_ \__\____ \____ |(____ /__| \/ |__| \/ \/ \/ \/ """ B = """ *** by YanMu *** """ self.output_to_console(f"{A}\n");self.output_to_console(f"{B}\n") def scanIP(self): pass if __name__ == '__main__': root=Tk() root.title("Pythonstudy by 雷石安全") root.geometry("1200x500+200+300") app = App(master=root) root.resizable(height=False) app.usage() app.mainloop()
代码中pass地方可以写你相应的功能点
demo演示:
然后我们可以在正常的函数除填写我们相应的功能
import tkinter as tk import shodan from tkinter.colorchooser import * from tkinter.filedialog import * import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) class App(Frame): def __init__(self,master=None): super(App, self).__init__() super().__init__(master) self.master=master self.var = tk.StringVar() self.zapi = ""//你的api self.initUI() self.textpad=None self.Create() self.pack() def Create(self): menubar=Menu(root) menuFile=Menu(menubar) menubar.add_cascade(label="options",menu=menuFile) menuFile.add_command(label="shellcode",accelerator="ctrl+a",command=self.test) menubar.add_cascade(label="test",menu=menuFile) menuFile.add_command() menuFile.add_command(label="open",accelerator="ctrl+b",command=self.fileopen) menuFile.add_command(label="save",accelerator="ctrl+c",command=self.filesave) menuFile.add_command(label="new",accelerator="ctrl+d",command=self.filenew) root["menu"]=menubar self.textpad=Text(root,width=200,height=10) self.textpad.pack() self.contextMenu=Menu(root) self.contextMenu.add_command(label="一键装逼",command=self.zha) self.contextMenu.add_command(label="bg",command=self.openAskColor) root.bind("<Button-3>",self.createCon) def zha(self): pass def openAskColor(self): s=askcolor(color="red",title="bg") self.textpad.config(bg=s[1]) def fileopen(self): self.textpad.delete("1.0","end") with askopenfile(title="txt") as f: self.textpad.insert(INSERT,f.read()) self.filename=f.name def filesave(self): with open(self.filename,"w") as f: c=self.textpad.get(1.0,END) f.write(c) def filenew(self): self.filename=asksaveasfile("另存为",initialfile="log.txt",filetypes=[("文本文档","*.txt")],defaultextension=".txt") self.filesave() def createCon(self,event): self.contextMenu.post(event.x_root,event.y_root) def test(self): pass def initUI(self): group_top = tk.LabelFrame(self, padx=15, pady=10) group_top.pack(padx=10, pady=5) tk.Button(group_top, text="scanIP", width=10, command=self.scanIP).grid(row=0, column=1) self.path_entry = tk.Entry(group_top, width=30) self.path_entry.grid(row=0, column=0, pady=5, padx=5) tk.Button(group_top, text="开始执行", width=10, command=self.func).grid(row=1, column=1, sticky=tk.E) tk.Button(group_top, text="停止", width=10, command=self.destroy).grid(row=1, column=0, sticky=tk.W) console_frame = tk.Frame(group_top).grid(row=2, column=0, columnspan=2) self.console_text = tk.Text( console_frame, fg="green", bg="black", width=40, height=20, state=tk.DISABLED) scrollbar = tk.Scrollbar(console_frame, command=self.console_text.yview) self.console_text.pack(expand=1, fill=tk.BOTH) self.console_text['yscrollcommand'] = scrollbar.set def output_to_console(self, new_text): self.console_text.config(state=tk.NORMAL) self.console_text.insert(tk.END, new_text) self.console_text.see(tk.END) self.console_text.config(state=tk.DISABLED) def func(self): se = ""//要搜索的设备 api = shodan.Shodan(self.zapi) res = api.search(se) # a=str(result['ip_str']) for result in res['matches']: url = str(result['ip_str']) + ":" + str(result['port']) + ":" + str( result['location']['country_name']) + ":" + str(result['domains']) # print(url) self.output_to_console(f"{url}\n") def usage(self): A = """ __ .__ .___ .___ .__ ____________ | | _|__| __| _/__| _/____ |__| / ___/\____ \| |/ / |/ __ |/ __ |\__ \ | | \___ \ | |_> > <| / /_/ / /_/ | / __ \| | /____ >| __/|__|_ \__\____ \____ |(____ /__| \/ |__| \/ \/ \/ \/ """ B = """ *** by YanMu *** """ self.output_to_console(f"{A}\n");self.output_to_console(f"{B}\n") def scanIP(self): pa = self.path_entry.get() scapi = shodan.Shodan(self.zapi) hosts = scapi.host(pa) er = str(hosts['ip_str']) + ":" + str(hosts.get('org', 'n/a')) + ":" + str(hosts.get('os', 'n/a')) self.output_to_console(f"{er}\n") for host in hosts['data']: sas = str(host['port']) + ":" + str(host['data']) self.output_to_console(f"{sas}\n") if __name__ == '__main__': root=Tk() root.title("Pythonstudy by 雷石安全") root.geometry("1200x500+200+300") app = App(master=root) root.resizable(height=False) app.usage() app.mainloop()
这里我们填写shodan的搜索为例,当然当时练习的时候尝试写一个记事本的功能来着
GUI个人思路:
有一个样式框架,往里面填东西就行。
你可以把别人命令行式的代码,剪吧剪吧放到自己的工具里面(缺陷:这个demo不能及时反映响应信息)
最后介绍一下,B/S架构思考:
这里我用的tornado框架
还是先有一个模板
import tornado.web import os import shodan import tornado.ioloop import tornado.httpserver from tornado.options import define,options,parse_command_line define("port",default=8888,help="运行端口",type=int) class IndexHandler(tornado.web.RequestHandler): def get(self): self.render("index.html") def write_error(self, status_code, **kwargs): self.write("your caused a %d error."%status_code) class CoupletHandler(tornado.web.RequestHandler): def post(self): first=self.get_argument("first") second=self.get_argument("second") self.render("couplet.html",first=sumurls,second=second) if __name__ == '__main__': parse_command_line() print(""" logo:leishi by caibi-yanmu """) print("http://localhost:{}/".format(options.port)) base_dir=os.path.dirname(__file__) app=tornado.web.Application( handlers=[ (r"/",IndexHandler), (r"/couplet",CoupletHandler) ], template_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),'templates'), static_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),'static'), ) http_server=tornado.httpserver.HTTPServer(app) http_server.listen(options.port) tornado.ioloop.IOLoop.instance().start()
然后我们向这个demo里面加我们的功能点,这里主要方便测试(外表不重要,嘤嘤嘤)
import tornado.web import os import shodan import tornado.ioloop import tornado.httpserver from tornado.options import define,options,parse_command_line define("port",default=8888,help="运行端口",type=int) class IndexHandler(tornado.web.RequestHandler): def get(self): self.render("index.html") def write_error(self, status_code, **kwargs): self.write("your caused a %d error."%status_code) class CoupletHandler(tornado.web.RequestHandler): def post(self): first=self.get_argument("first") second=self.get_argument("second") api=shodan.Shodan(first) sumurls="" try: results=api.search(second) for i in results['matches']: url=i['ip_str']+":"+str(i['port']) sumurls+=url+"\n" except shodan.APIError as e: print(e) self.render("couplet.html",first=sumurls,second=second) if __name__ == '__main__': parse_command_line() print(""" logo:leishi by caibi-yanmu """) print("http://localhost:{}/".format(options.port)) base_dir=os.path.dirname(__file__) app=tornado.web.Application( handlers=[ (r"/",IndexHandler), (r"/couplet",CoupletHandler) ], template_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),'templates'), static_path=os.path.join(os.path.dirname(os.path.abspath(__file__)),'static'), ) http_server=tornado.httpserver.HTTPServer(app) http_server.listen(options.port) tornado.ioloop.IOLoop.instance().start()
这里师傅们可以根据自己的前端代码去填充对应结果
总结:
我们平常写的命令行下的工具无论是在GUI形式下还是B/S形式下,最后核心的功能点不变,所以说,要是我们平常在测试的过程中,完全可以只写在命令行模式下的小工具。