diff --git a/README.md b/README.md index aa28ab5..d323857 100644 --- a/README.md +++ b/README.md @@ -25,9 +25,9 @@ Tool Highlights: * Device Details ### Tool Image: -![Alt text](https://srinivas11789.github.io/PcapXray/Samples/screen2_5_1.png?raw=true) +![Alt text](https://srinivas11789.github.io/PcapXray/Samples/screen2_6_1.png?raw=true) -![Alt text](https://srinivas11789.github.io/PcapXray/Samples/screen2_5_2.png?raw=true) +![Alt text](https://srinivas11789.github.io/PcapXray/Samples/screen2_6_2.png?raw=true) ### Components: * Network Diagram @@ -77,7 +77,7 @@ python Source/main.py * Matplotlib – plot graph (not used as of now) ### Demo -![Alt text](https://srinivas11789.github.io/PcapXray/Samples/demo2_5.gif?raw=true) +![Alt text](https://srinivas11789.github.io/PcapXray/Samples/demo2_6.gif?raw=true) ### Getting started: * Clone the repository @@ -118,12 +118,6 @@ python Source/main.py * Performing the steps in `run.sh` file manually would work to launch the tool via docker (I can help with errors) * Running `run.sh` scripts is an attempt to automate (would not work 100 percent) - tested on mac and linux - will be better soon!... - -### PcapXray 2.0 -* Includes zoom feature -* Improves usability with a Browse files feature -* Report directory fixes for graph images -* Includes some bug fixes ### Immediate Future Tasks: (Target: 3.0) @@ -134,6 +128,7 @@ python Source/main.py - Traffic support: ICMP, DNS - Known file type detection and Extract - Python2 and Python3 +- Interactive map ### Future: * Structured and clean code flow @@ -143,6 +138,13 @@ python Source/main.py * More protocol support * Clean up code +### Credits: +* Thanks for making it better, + - Professor Marc Budofsky + - Kevin Gallagher +* Thanks for all the dependent libraries used +* Logo created with logomakr.com and www.inkscape.org + [![Analytics](https://ga-beacon.appspot.com/UA-114681129-1/PcapXray/readme)](https://github.com/igrigorik/ga-beacon) ## ***Just for Security Fun!*** diff --git a/Samples/demo2_6.gif b/Samples/demo2_6.gif new file mode 100644 index 0000000..e2f6c24 Binary files /dev/null and b/Samples/demo2_6.gif differ diff --git a/Samples/screen2_6_1.png b/Samples/screen2_6_1.png new file mode 100644 index 0000000..eeb8874 Binary files /dev/null and b/Samples/screen2_6_1.png differ diff --git a/Samples/screen2_6_2.png b/Samples/screen2_6_2.png new file mode 100644 index 0000000..038f2b5 Binary files /dev/null and b/Samples/screen2_6_2.png differ diff --git a/Source/Module/interactive_gui.py b/Source/Module/interactive_gui.py new file mode 100644 index 0000000..e1188fa --- /dev/null +++ b/Source/Module/interactive_gui.py @@ -0,0 +1,223 @@ +import sys + +# Tkinter Mac Setting +if sys.platform == 'darwin': + import matplotlib + matplotlib.use('TkAgg') + +import memory + +# This implementation is a modified version of the example of +# embedding CEF Python browser using Tkinter toolkit. +# Reference https://github.com/cztomczak/cefpython/blob/master/examples/tkinter_.py +# +# NOTE: This example often crashes on Mac (Python 2.7, Tk 8.5/8.6) +# during initial app loading with such message: +# "Segmentation fault: 11". Reported as Issue #309. +# +# Tested configurations: +# - Tk 8.5 on Windows/Mac +# - Tk 8.6 on Linux +# - CEF Python v55.3+ +# +# Known issue on Linux: When typing url, mouse must be over url +# entry widget otherwise keyboard focus is lost (Issue #255 +# and Issue #284). + +from cefpython3 import cefpython as cef +import ctypes +try: + # for Python2 + from Tkinter import * + #from Tkinter import Tkversion + import Tkinter as tk + import ttk + import Tkconstants +except ImportError: + # for Python3 + from tkinter import * + import tkinter as tk + from tkinter import ttk +import sys +import os +import platform +import logging as _logging + +# Platforms +WINDOWS = (platform.system() == "Windows") +LINUX = (platform.system() == "Linux") +MAC = (platform.system() == "Darwin") + +# Globals +logger = _logging.getLogger("tkinter_.py") + +# Constants +# Tk 8.5 doesn't support png images +#IMAGE_EXT = ".png" if TkVersion > 8.5 else ".gif" + +interactive_map = "" +browser_frame = "" +FourthFrame = "" +def gimmick_initialize(window, map): + global browser_frame, FourthFrame + if not browser_frame and not FourthFrame: + global interactive_map + interactive_map = map + logger.setLevel(_logging.INFO) + stream_handler = _logging.StreamHandler() + formatter = _logging.Formatter("[%(filename)s] %(message)s") + stream_handler.setFormatter(formatter) + logger.addHandler(stream_handler) + logger.info("CEF Python {ver}".format(ver=cef.__version__)) + logger.info("Python {ver} {arch}".format( + ver=platform.python_version(), arch=platform.architecture()[0])) + logger.info("Tk {ver}".format(ver=tk.Tcl().eval('info patchlevel'))) + assert cef.__version__ >= "55.3", "CEF Python v55.3+ required to run this" + sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error + + FourthFrame = ttk.Frame(window, width=500, height=500, padding="10 10 10 10",relief= GROOVE) + FourthFrame.grid(column=50, row=10, sticky=(N, W, E, S), columnspan=200, rowspan=200, padx=5, pady=5) + + browser_frame = BrowserFrame(FourthFrame) + browser_frame.grid(row=0, column=0,sticky=(N, W, E, S),columnspan=100, rowspan=100, padx=5, pady=5) + + FourthFrame.columnconfigure(50, weight=1) + FourthFrame.rowconfigure(10, weight=1) + browser_frame.columnconfigure(0, weight=1) + browser_frame.rowconfigure(0, weight=1) + + window.update() + else: + if FourthFrame: + FourthFrame.grid_forget() + FourthFrame, browser_frame = "", "" + window.update() + +def show_frame(self, cont): + frame = self.frames[cont] + frame.tkraise() + +class BrowserFrame(tk.Frame): + + def __init__(self, master): + self.closing = False + self.browser = None + # Python2 has a ttk frame error of using self as argument so use tk + #ttk.Frame.__init__(self, master, width=500, height=400, padding="10 10 10 10", relief=GROOVE) + tk.Frame.__init__(self, master, width=500, height=400) + self.bind("", self.on_focus_in) + self.bind("", self.on_focus_out) + self.bind("", self.on_configure) + self.focus_set() + + def embed_browser(self): + window_info = cef.WindowInfo() + rect = [0, 0, self.winfo_width(), self.winfo_height()] + window_info.SetAsChild(self.get_window_handle(), rect) + self.browser = cef.CreateBrowserSync(window_info, url=interactive_map) + assert self.browser + self.browser.SetClientHandler(LoadHandler(self)) + self.browser.SetClientHandler(FocusHandler(self)) + self.message_loop_work() + + def get_window_handle(self): + if self.winfo_id() > 0 and not MAC: + return self.winfo_id() + elif MAC: + raise Exception("Couldn't obtain window handle") + # CEF crashes in mac so temp disable + # * CreateBrowserSync calling window handle crashes with segmentation fault 11 + # * https://github.com/cztomczak/cefpython/issues/309 + # On Mac window id is an invalid negative value (Issue #308). + # This is kind of a dirty hack to get window handle using + # PyObjC package. If you change structure of windows then you + # need to do modifications here as well. + # noinspection PyUnresolvedReferences + """ + try: + from AppKit import NSApp + # noinspection PyUnresolvedReferences + import objc + # Sometimes there is more than one window, when application + # didn't close cleanly last time Python displays an NSAlert + # window asking whether to Reopen that window. + # noinspection PyUnresolvedReferences + return objc.pyobjc_id(NSApp.windows()[-1].contentView()) + except: + raise Exception("Couldn't obtain window handle") + """ + else: + raise Exception("Couldn't obtain window handle") + + def message_loop_work(self): + cef.MessageLoopWork() + self.after(10, self.message_loop_work) + + def on_configure(self, _): + if not self.browser: + self.embed_browser() + + def on_root_configure(self): + # Root event will be called when top window is moved + if self.browser: + self.browser.NotifyMoveOrResizeStarted() + + def on_mainframe_configure(self, width, height): + if self.browser: + if WINDOWS: + ctypes.windll.user32.SetWindowPos( + self.browser.GetWindowHandle(), 0, + 0, 0, width, height, 0x0002) + elif LINUX: + self.browser.SetBounds(0, 0, width, height) + self.browser.NotifyMoveOrResizeStarted() + + def on_focus_in(self, _): + logger.debug("BrowserFrame.on_focus_in") + if self.browser: + self.browser.SetFocus(True) + + def on_focus_out(self, _): + logger.debug("BrowserFrame.on_focus_out") + if self.browser: + self.browser.SetFocus(False) + + def on_root_close(self): + if self.browser: + self.browser.CloseBrowser(True) + self.clear_browser_references() + self.destroy() + + def clear_browser_references(self): + # Clear browser references that you keep anywhere in your + # code. All references must be cleared for CEF to shutdown cleanly. + self.browser = None + + +class LoadHandler(object): + + def __init__(self, browser_frame): + self.browser_frame = browser_frame + +class FocusHandler(object): + + def __init__(self, browser_frame): + self.browser_frame = browser_frame + + def OnTakeFocus(self, next_component, **_): + logger.debug("FocusHandler.OnTakeFocus, next={next}" + .format(next=next_component)) + + def OnSetFocus(self, source, **_): + logger.debug("FocusHandler.OnSetFocus, source={source}" + .format(source=source)) + return False + + def OnGotFocus(self, **_): + """Fix CEF focus issues (#255). Call browser frame's focus_set + to get rid of type cursor in url entry widget.""" + logger.debug("FocusHandler.OnGotFocus") + self.browser_frame.focus_set() + + + diff --git a/Source/Module/plot_lan_network.py b/Source/Module/plot_lan_network.py index e57dc64..1372dec 100644 --- a/Source/Module/plot_lan_network.py +++ b/Source/Module/plot_lan_network.py @@ -13,13 +13,15 @@ import threading import os +from pyvis.network import Network + class plotLan: def __init__(self, filename, path, option="Tor", to_ip="All", from_ip="All"): self.directory = os.path.join(path, "Report") if not os.path.exists(self.directory): os.makedirs(self.directory) - options = option + "_" + to_ip + "_" + from_ip + options = option + "_" + to_ip.replace(".", "-") + "_" + from_ip.replace(".", "-") self.filename = os.path.join(self.directory, filename+"_"+options) self.styles = { @@ -81,6 +83,11 @@ def draw_graph(self, option="All", to_ip="All", from_ip="All"): f = Digraph('network_diagram - '+option, filename=self.filename, engine="circo", format="png") else: f = Digraph('network_diagram - '+option, filename=self.filename, engine="dot", format="png") + + interactive_graph = Network(directed=True, height="750px", width="100%", bgcolor="#222222", font_color="white") + interactive_graph.barnes_hut() + vis_nodes = [] + vis_edges = [] f.attr('node', shape='doublecircle') #f.node('defaultGateway') @@ -90,6 +97,8 @@ def draw_graph(self, option="All", to_ip="All", from_ip="All"): print("Starting Graph Plotting") edge_present = False + mal, tor, http, https, icmp, dns = 0, 0, 0, 0, 0, 0 + if option == "All": # add nodes for session in self.sessions: @@ -136,31 +145,69 @@ def draw_graph(self, option="All", to_ip="All", from_ip="All"): destination = memory.packet_db[session]["Ethernet"]["dst"].replace(":",".") destination += "\n"+"PossibleGateway" dlabel = "" + + # Interactive Graph on Beta, so for now add safety checks ( potential failures in python2) + try: + interactive_graph.add_node(str(curr_node), str(curr_node), title=str(curr_node), color="yellow") + interactive_graph.add_node(str(destination), str(destination), title=str(destination), color="yellow") + except Exception as e: + print("Interactive graph error occurred: "+str(e)) + + #if (curr_node, curr_node, title=curr_node, color="yellow") not in vis_nodes: + # vis_nodes.append((curr_node, curr_node, title=curr_node, color="yellow")) + #if (destination, destination, title=destination, color="yellow") not in vis_nodes: + # vis_nodes.append((destination, destination, title=destination, color="yellow")) if curr_node != destination: if session in memory.possible_tor_traffic: f.edge(curr_node, destination, label='TOR: ' + str(map_dst) ,color="white") + tor += 1 + #interactive_graph.add_edge(curr_node, destination, color="white", value=tor/100, smooth={type: "curvedCCW", roundness: 0.4}) + interactive_graph.add_edge(curr_node, destination, color="white", smooth={"type": "curvedCW", "roundness": tor/10}) + #if edge not in vis_edges:toor + # vis_edges.append(edge) if edge_present == False: edge_present = True elif session in memory.possible_mal_traffic: f.edge(curr_node, destination, label='Malicious: ' + str(map_dst) ,color="red") + mal += 1 + #interactive_graph.add_edge(curr_node, destination, color="red", value=mal/100, smooth={"type": "curvedCW", "roundness": 0.4}) + interactive_graph.add_edge(curr_node, destination, color="red", smooth={"type": "curvedCW", "roundness": mal/10}) + #if edge not in vis_edges: + # vis_edges.append(edge) if edge_present == False: edge_present = True else: if port == "443": f.edge(curr_node, destination, label='HTTPS: ' + map_dst +": "+dlabel, color = "blue") + https += 1 + interactive_graph.add_edge(curr_node, destination, color="blue", smooth={"type": "curvedCCW", "roundness": https/10}) + #if edge not in vis_edges: + # vis_edges.append(edge) if edge_present == False: edge_present = True if port == "80": f.edge(curr_node, destination, label='HTTP: ' + map_dst +": "+dlabel, color = "green") + http += 1 + interactive_graph.add_edge(curr_node, destination, color="green", smooth={"type": "curvedCW", "roundness": http/10}) + #if edge not in vis_edges: + # vis_edges.append(edge) if edge_present == False: edge_present = True if port == "ICMP": f.edge(curr_node, destination, label='ICMP: ' + str(map_dst) ,color="black") + icmp += 1 + interactive_graph.add_edge(curr_node, destination, color="purple", smooth={"type": "curvedCCW", "roundness": icmp/10}) + #if edge not in vis_edges: + # vis_edges.append(edge) if edge_present == False: edge_present = True if port == "53": f.edge(curr_node, destination, label='DNS: ' + str(map_dst) ,color="orange") + dns += 1 + interactive_graph.add_edge(curr_node, destination, color="pink", smooth={"type": "curvedCW", "roundness": dns/10}) + #if edge not in vis_edges: + # vis_edges.append(edge) if edge_present == False: edge_present = True @@ -208,9 +255,18 @@ def draw_graph(self, option="All", to_ip="All", from_ip="All"): destination = memory.packet_db[session]["Ethernet"]["dst"].replace(":",".") destination += "\n"+"PossibleGateway" dlabel = "" + + # Interactive Graph on Beta, so for now add safety checks ( potential failures in python2) + try: + interactive_graph.add_node(str(curr_node), str(curr_node), title=str(curr_node), color="yellow") + interactive_graph.add_node(str(destination), str(destination), title=str(destination), color="yellow") + except Exception as e: + print("Interactive graph error occurred: "+str(e)) if port == "80" and curr_node != destination: f.edge(curr_node, destination, label='HTTP: ' + str(map_dst)+": "+dlabel, color = "green") + http += 1 + interactive_graph.add_edge(curr_node, destination, color="green", smooth={"type": "curvedCW", "roundness": http/10}) if edge_present == False: edge_present = True @@ -257,9 +313,18 @@ def draw_graph(self, option="All", to_ip="All", from_ip="All"): destination = memory.packet_db[session]["Ethernet"]["dst"].replace(":",".") destination += "\n"+"PossibleGateway" dlabel = "" + + # Interactive Graph on Beta, so for now add safety checks ( potential failures in python2) + try: + interactive_graph.add_node(str(curr_node), str(curr_node), title=str(curr_node), color="yellow") + interactive_graph.add_node(str(destination), str(destination), title=str(destination), color="yellow") + except Exception as e: + print("Interactive graph error occurred: "+str(e)) if port == "443" and curr_node != destination: f.edge(curr_node, destination, label='HTTPS: ' + str(map_dst)+": "+dlabel, color = "blue") + https += 1 + interactive_graph.add_edge(curr_node, destination, color="blue", smooth={"type": "curvedCCW", "roundness": https/10}) if edge_present == False: edge_present = True @@ -307,8 +372,17 @@ def draw_graph(self, option="All", to_ip="All", from_ip="All"): destination += "\n"+"PossibleGateway" dlabel = "" + # Interactive Graph on Beta, so for now add safety checks ( potential failures in python2) + try: + interactive_graph.add_node(str(curr_node), str(curr_node), title=str(curr_node), color="yellow") + interactive_graph.add_node(str(destination), str(destination), title=str(destination), color="yellow") + except Exception as e: + print("Interactive graph error occurred: "+str(e)) + if session in memory.possible_tor_traffic and curr_node != destination: f.edge(curr_node, destination, label='TOR: ' + str(map_dst) ,color="white") + tor += 1 + interactive_graph.add_edge(curr_node, destination, color="white", smooth={"type": "curvedCW", "roundness": tor/10}) if edge_present == False: edge_present = True @@ -358,8 +432,17 @@ def draw_graph(self, option="All", to_ip="All", from_ip="All"): destination += "\n"+"PossibleGateway" dlabel = "" + # Interactive Graph on Beta, so for now add safety checks ( potential failures in python2) + try: + interactive_graph.add_node(str(curr_node), str(curr_node), title=str(curr_node), color="yellow") + interactive_graph.add_node(str(destination), str(destination), title=str(destination), color="yellow") + except Exception as e: + print("Interactive graph error occurred: "+str(e)) + if session in memory.possible_mal_traffic and curr_node != destination: f.edge(curr_node, destination, label='Malicious: ' + str(map_dst) ,color="red") + mal += 1 + interactive_graph.add_edge(curr_node, destination, color="red", smooth={"type": "curvedCW", "roundness": mal/10}) if edge_present == False: edge_present = True @@ -406,8 +489,17 @@ def draw_graph(self, option="All", to_ip="All", from_ip="All"): destination += "\n"+"PossibleGateway" dlabel = "" + # Interactive Graph on Beta, so for now add safety checks ( potential failures in python2) + try: + interactive_graph.add_node(str(curr_node), str(curr_node), title=str(curr_node), color="yellow") + interactive_graph.add_node(str(destination), str(destination), title=str(destination), color="yellow") + except Exception as e: + print("Interactive graph error occurred: "+str(e)) + if protocol == "ICMP" and curr_node != destination: f.edge(curr_node, destination, label='ICMP: ' + str(map_dst) ,color="black") + icmp += 1 + interactive_graph.add_edge(curr_node, destination, color="purple", smooth={"type": "curvedCCW", "roundness": icmp/10}) if edge_present == False: edge_present = True @@ -453,8 +545,17 @@ def draw_graph(self, option="All", to_ip="All", from_ip="All"): destination += "\n"+"PossibleGateway" dlabel = "" + # Interactive Graph on Beta, so for now add safety checks ( potential failures in python2) + try: + interactive_graph.add_node(str(curr_node), str(curr_node), title=str(curr_node), color="yellow") + interactive_graph.add_node(str(destination), str(destination), title=str(destination), color="yellow") + except Exception as e: + print("Interactive graph error occurred: "+str(e)) + if port == "53" and curr_node != destination: f.edge(curr_node, destination, label='DNS: ' + str(map_dst) ,color="orange") + dns += 1 + interactive_graph.add_edge(curr_node, destination, color="pink", smooth={"type": "curvedCW", "roundness": dns/10}) if edge_present == False: edge_present = True @@ -464,6 +565,8 @@ def draw_graph(self, option="All", to_ip="All", from_ip="All"): self.apply_styles(f,self.styles) f.render() + + interactive_graph.save_graph(self.filename+".html") def main(): # draw example diff --git a/Source/Module/user_interface.py b/Source/Module/user_interface.py index 64f5725..b08fa09 100644 --- a/Source/Module/user_interface.py +++ b/Source/Module/user_interface.py @@ -1,4 +1,9 @@ import sys + +if sys.platform == 'darwin': + import matplotlib + matplotlib.use('TkAgg') + try: # for Python2 from Tkinter import * @@ -28,6 +33,7 @@ class pcapXrayGui: def __init__(self, base): + # Base Frame Configuration self.base = base base.title("PcapXray") @@ -39,7 +45,7 @@ def __init__(self, base): style.configure("BW.TEntry", foreground="black") # 1st Frame - Initial Frame - InitFrame = ttk.Frame(base, width=50, padding="10 10 10 10",relief= GROOVE) + InitFrame = ttk.Frame(base, width=50, padding="10 0 0 0",relief= GROOVE) InitFrame.grid(column=10, row=10, sticky=(N, W, E, S)) InitFrame.columnconfigure(10, weight=1) InitFrame.rowconfigure(10, weight=1) @@ -61,7 +67,7 @@ def __init__(self, base): FirstFrame = ttk.Frame(base, width=50, padding="10 0 0 0", relief= GROOVE) FirstFrame.grid(column=10, row=20, sticky=(N, W, E, S)) FirstFrame.columnconfigure(10, weight=1) - FirstFrame.rowconfigure(10, weight=1) + FirstFrame.rowconfigure(20, weight=1) self.destination_report = StringVar(value=sys.path[0]) ttk.Label(FirstFrame, text="Output directory path: ",style="BW.TLabel").grid(column=0, row=0, sticky="W") self.report_field = ttk.Entry(FirstFrame, width=30, textvariable=self.destination_report, style="BW.TEntry").grid(column=1, row=0, sticky="W, E") @@ -78,14 +84,18 @@ def __init__(self, base): SecondFrame = ttk.Frame(base, width=50, padding="10 10 10 10",relief= GROOVE) SecondFrame.grid(column=10, row=30, sticky=(N, W, E, S)) SecondFrame.columnconfigure(10, weight=1) - SecondFrame.rowconfigure(10, weight=1) + SecondFrame.rowconfigure(30, weight=1) ttk.Label(SecondFrame, text="Traffic: ", style="BW.TLabel").grid(row=10,column=0,sticky="W") self.option = StringVar() self.options = {'All', 'HTTP', 'HTTPS', 'Tor', 'Malicious', 'ICMP', 'DNS'} #self.option.set('Tor') ttk.OptionMenu(SecondFrame,self.option,"Select",*self.options).grid(row=10,column=1, padx=10, sticky="W") + self.ibutton = ttk.Button(SecondFrame, text="InteractiveMagic!", command=self.gimmick) + self.ibutton.grid(row=10, column=10, padx=10, sticky="E") self.trigger = ttk.Button(SecondFrame, text="Visualize!", command=self.map_select) - self.trigger.grid(row=10,column=11,sticky="E") + self.trigger.grid(row=10,column=11, sticky="E") + self.trigger['state'] = 'disabled' + self.ibutton['state'] = 'disabled' self.img = "" @@ -106,7 +116,6 @@ def __init__(self, base): self.to_menu.set("All") self.option.set("All") - # Third Frame with Results and Descriptioms self.ThirdFrame = ttk.Frame(base, width=100, height=100, padding="10 10 10 10",relief= GROOVE) description = """It is a tool aimed to simplyfy the network analysis and speed the process of analysing the network traffic.\nThis prototype aims to accomplish 4 important modules, @@ -119,10 +128,12 @@ def __init__(self, base): self.yscrollbar = Scrollbar(self.ThirdFrame, orient=VERTICAL) self.yscrollbar.grid(row=0, column=100, sticky=N + S) self.ThirdFrame.grid(column=10, row=40, sticky=(N, W, E, S)) - self.ThirdFrame.columnconfigure(0, weight=1) - self.ThirdFrame.rowconfigure(0, weight=1) - #self.details_fetch = 0 - #self.destination_report = "" + self.ThirdFrame.columnconfigure(10, weight=1) + self.ThirdFrame.rowconfigure(40, weight=1) + + base.resizable(False, False) + base.rowconfigure(0, weight=1) + base.columnconfigure(0, weight=1) def browse_directory(self, option): if option == "pcap": @@ -165,6 +176,7 @@ def pcap_analyse(self): # Disable controls when performing analysis self.trigger['state'] = 'disabled' + self.ibutton['state'] = 'disabled' self.to_menu['state'] = 'disabled' self.from_menu['state'] = 'disabled' @@ -245,11 +257,10 @@ def generate_graph(self): t.start() t1.start() self.progressbar.start() - while t.is_alive() or t1.is_alive(): + while t.is_alive(): self.progressbar.update() t.join() t1.join() - self.progressbar.stop() # Report Generation Control and Filters update (Here?) self.details_fetch = 1 @@ -259,9 +270,11 @@ def generate_graph(self): reportThread.start() reportThread = threading.Thread(target=report_generator.reportGen(self.destination_report.get(), self.filename).deviceDetailsReport,args=()) reportThread.start() + + self.progressbar.stop() # Loding the generated map - options = self.option.get()+"_"+self.to_ip.get()+"_"+self.from_ip.get() + options = self.option.get()+"_"+self.to_ip.get().replace(".","-")+"_"+self.from_ip.get().replace(".", "-") self.image_file = os.path.join(self.destination_report.get(), "Report", self.filename+"_"+options+".png") if not os.path.exists(self.image_file): t1 = threading.Thread(target=plot_lan_network.plotLan, args=(self.filename, self.destination_report.get(), self.option.get(), self.to_ip.get(), self.from_ip.get())) @@ -276,15 +289,24 @@ def generate_graph(self): else: self.label.grid_forget() self.load_image() + self.ibutton['state'] = 'normal' + + def gimmick(self): + import interactive_gui + interactive_gui.gimmick_initialize(self.base, "file://"+self.image_file.replace(".png",".html")) def load_image(self): - self.canvas = Canvas(self.ThirdFrame, width=700,height=600, bd=0, bg="navy", xscrollcommand=self.xscrollbar.set, yscrollcommand=self.yscrollbar.set) - self.canvas.grid(row=0, column=0, sticky=N + S + E + W) + self.canvas = Canvas(self.ThirdFrame, width=900,height=500, bd=0, bg="navy", xscrollcommand=self.xscrollbar.set, yscrollcommand=self.yscrollbar.set) + #self.canvas.grid(row=0, column=0, sticky=N + S + E + W) + self.canvas.grid(column=0, row=0, sticky=(N, W, E, S)) + #self.canvas.pack(side = RIGHT, fill = BOTH, expand = True) self.img = ImageTk.PhotoImage(Image.open(self.image_file).resize(tuple(self.zoom),Image.ANTIALIAS))#.convert('RGB')) self.canvas.create_image(0,0, image=self.img) self.canvas.config(scrollregion=self.canvas.bbox(ALL)) self.xscrollbar.config(command=self.canvas.xview) self.yscrollbar.config(command=self.canvas.yview) + #self.canvas.rowconfigure(0, weight=1) + #self.canvas.columnconfigure(0, weight=1) def map_select(self, *args): print(self.option.get()) @@ -308,6 +330,13 @@ def zoom_out(self): if self.img: self.load_image() +class OtherFrame(Toplevel): + + def __init__(self, x, y): + """Constructor""" + Toplevel.__init__(self) + self.geometry("+%d+%d" % (x + 100, y + 200)) + self.title("otherFrame") def main(): base = Tk() diff --git a/Source/main.py b/Source/main.py index bce680f..5a6e8b0 100644 --- a/Source/main.py +++ b/Source/main.py @@ -5,6 +5,12 @@ import sys #-- default lib import datetime #-- default lib +if sys.platform == 'darwin': + import matplotlib + matplotlib.use('TkAgg') + +from cefpython3 import cefpython as cef + try: # for Python2 from Tkinter import * @@ -31,7 +37,9 @@ def main(): icon = PhotoImage(file=logo_file) base.tk.call('wm','iconphoto',base._w,icon) user_interface.pcapXrayGui(base) + cef.Initialize() base.mainloop() + cef.Shutdown() main() diff --git a/requirements.txt b/requirements.txt index ffb03d3..1f12c72 100644 --- a/requirements.txt +++ b/requirements.txt @@ -25,3 +25,7 @@ networkx graphviz matplotlib +# Interactive Maps +cefpython3 +pyvis +