Skip to content

Commit

Permalink
Merge pull request #41 from Srinivas11789/develop
Browse files Browse the repository at this point in the history
PcapXray Release 2.5
  • Loading branch information
Srinivas11789 authored May 15, 2019
2 parents acea4d2 + ba5cd40 commit e668abb
Show file tree
Hide file tree
Showing 7 changed files with 503 additions and 300 deletions.
33 changes: 29 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
A Network Forensics Tool - To visualize a Packet Capture offline as a Network Diagram including device identification, highlight important communication and file extraction
![Alt text](https://srinivas11789.github.io/PcapXray/logo.png?width=20px "PcapXray")
## PcapXray Design Specification
Wiki has more help too.

### Goal:
Given a Pcap File, plot a network diagram displaying hosts in the network, network traffic, highlight important traffic and Tor traffic as well as potential malicious traffic including data involved in the communication.
Expand All @@ -24,9 +25,9 @@ Tool Highlights:
* Device Details

### Tool Image:
![Alt text](https://srinivas11789.github.io/PcapXray/Samples/screen2_2_4.png?raw=true)
![Alt text](https://srinivas11789.github.io/PcapXray/Samples/screen2_5_1.png?raw=true)

![Alt text](https://srinivas11789.github.io/PcapXray/Samples/screen1_2_4.png?raw=true)
![Alt text](https://srinivas11789.github.io/PcapXray/Samples/screen2_5_2.png?raw=true)

### Components:
* Network Diagram
Expand All @@ -35,6 +36,30 @@ Tool Highlights:
* Tor Traffic
* GUI – a gui with options to upload pcap file and display the network diagram

### Setup

* Python 3

```bash
apt install python3-pip
apt install python3-tk
apt install graphviz
apt install python3-pil python3-pil.imagetk
pip3 install -r requirements.txt
python3 Source/main.py
```
( Make sure to escalate privilege to allow file creations - Run with `sudo` )

* Python 2

```bash
apt install python-tk
apt install graphviz
pip install -r requirements.txt
python Source/main.py
```
( Make sure to escalate privilege to allow file creations - Run with `sudo` )

### Python Libraries Used: - All these libraries are required for functionality
* Tkinter and TTK – Install from pip or apt-get – Ensure Tkinter and graphviz is installed (Most Linux contain by default)
* apt install python-tk
Expand All @@ -52,7 +77,7 @@ Tool Highlights:
* Matplotlib – plot graph (not used as of now)

### Demo
![Alt text](https://srinivas11789.github.io/PcapXray/Samples/demo2_4.gif?raw=true)
![Alt text](https://srinivas11789.github.io/PcapXray/Samples/demo2_5.gif?raw=true)

### Getting started:
* Clone the repository
Expand Down Expand Up @@ -120,4 +145,4 @@ Tool Highlights:

[![Analytics](https://ga-beacon.appspot.com/UA-114681129-1/PcapXray/readme)](https://github.com/igrigorik/ga-beacon)

Just for Security Fun!
## ***Just for Security Fun!***
Binary file added Samples/demo2_5.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Samples/screen2_5_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Samples/screen2_5_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
596 changes: 328 additions & 268 deletions Source/Module/plot_lan_network.py

Large diffs are not rendered by default.

33 changes: 23 additions & 10 deletions Source/Module/report_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,30 @@ def packetDetails(self):
try:
packet_file = os.path.join(self.directory, self.filename + "_packet_details.txt")
text_handle = open(packet_file, "w")
text_handle.write("%s\n" % json.dumps(memory.packet_db, indent=2, sort_keys=True))
text_handle.write("%s\n" % json.dumps(memory.packet_db, indent=2, sort_keys=True))
text_handle.close()
except Exception as e:
print("Could not create the report text file, trying backup mode !!!!! %s" % (str(e)))
self.backupReport()

def backupReport(self):
try:
packet_file = os.path.join(self.directory, self.filename + "_packet_details.txt")
text_handle = open(packet_file, "w")
# <TODO>: Do we need to format payload?
#for session in memory.packet_db:
#text_handle.write("\nSession: %s\n" % session)
#text_handle.write("\nEthernet: %s\n" % memory.packet_db[session]["Ethernet"])
#text_handle.write("\nPayload:\n")
#payloads = "\n".join(memory.packet_db[session]["Payload"])
#if payloads:
# text_handle.write("%s\n" % payloads)

for session in memory.packet_db:
text_handle.write("\nSession: %s\n" % session)
text_handle.write("\nEthernet: %s\n" % memory.packet_db[session]["Ethernet"])
text_handle.write("\nPayload:\n")
fpayloads = "\n".join(memory.packet_db[session]["Payload"]["forward"])
text_handle.write("\nForward:\n")
if fpayloads:
text_handle.write("%s\n" % fpayloads)
rpayloads = "\n".join(memory.packet_db[session]["Payload"]["reverse"])
text_handle.write("\nReverse:\n")
if rpayloads:
text_handle.write("%s\n" % rpayloads)
text_handle.write("="*80+"\n")
text_handle.close()
except Exception as e:
print("Could not create the report text file !!!!! Please debug error %s" % (str(e)))
print("Could not create the report text file by backup method !!!!! Please debug error %s" % (str(e)))
141 changes: 123 additions & 18 deletions Source/Module/user_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
import pcap_reader
import plot_lan_network
import communication_details_fetch
import device_details_fetch
import report_generator
import time
import threading
import memory
from PIL import Image,ImageTk
import os, sys

Expand Down Expand Up @@ -63,23 +65,47 @@ def __init__(self, base):
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")

# Browse button
ttk.Button(FirstFrame, text="Browse", command=lambda: self.browse_directory("report")).grid(column=2, row=0, padx=10, pady=10,sticky="E")
ttk.Button(FirstFrame, text="Browse", command=lambda: self.browse_directory("report")).grid(column=2, row=0, padx=10, pady=10,sticky="E")

# Zoom
self.zoom = [900,900]
ttk.Button(FirstFrame, text="zoomIn", command=self.zoom_in).grid(row=0,column=10, padx=5, sticky="E")
ttk.Button(FirstFrame, text="zoomOut", command=self.zoom_out).grid(row=0,column=19,padx=10, sticky="E")

# Second Frame with Options
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)
ttk.Label(SecondFrame, text="Options: ", style="BW.TLabel").grid(row=10,column=0,sticky="W")
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,sticky="W")
self.zoom = [900,900]
ttk.OptionMenu(SecondFrame,self.option,"Select",*self.options).grid(row=10,column=1, padx=10, sticky="W")
self.trigger = ttk.Button(SecondFrame, text="Visualize!", command=self.map_select)
self.trigger.grid(row=10,column=11,sticky="E")

self.img = ""
ttk.Button(SecondFrame, text="zoomIn", command=self.zoom_in).grid(row=10,column=10,padx=5,sticky="E")
ttk.Button(SecondFrame, text="zoomOut", command=self.zoom_out).grid(row=10,column=11,sticky="E")

## Filters
self.from_ip = StringVar()
self.from_hosts = ["All"]
self.to_ip = StringVar()
self.to_hosts = ["All"]
ttk.Label(SecondFrame, text="From: ", style="BW.TLabel").grid(row=10, column=2, sticky="W")
self.from_menu = ttk.Combobox(SecondFrame, width=15, textvariable=self.from_ip, values=self.from_hosts)
self.from_menu.grid(row=10, column=3, padx=10, sticky="E")
ttk.Label(SecondFrame, text="To: ", style="BW.TLabel").grid(row=10, column=4, sticky="W")
self.to_menu = ttk.Combobox(SecondFrame, width=15, textvariable=self.to_ip, values=self.to_hosts)
self.to_menu.grid(row=10, column=5, padx=10, sticky="E")

# Default filter values
self.from_menu.set("All")
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)
Expand All @@ -95,7 +121,7 @@ def __init__(self, base):
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.name_servers = ""
#self.details_fetch = 0
#self.destination_report = ""

def browse_directory(self, option):
Expand All @@ -117,49 +143,129 @@ def browse_directory(self, option):
mb.showerror("Error","Permission denied to create report! Run with higher privilege.")
else:
mb.showerror("Error", "Enter a output directory!")

"""
def update_ips(self, direction):
if direction == "to":
self.to_hosts += list(memory.destination_hosts.keys())
self.to_menu['values'] = self.to_hosts
else:
for mac in memory.lan_hosts:
self.to_hosts += memory.lan_hosts[mac]["ip"]
self.from_hosts += memory.lan_hosts[mac]["ip"]
self.from_menu['values'] = self.from_hosts
"""

def pcap_analyse(self):
if not os.access(self.destination_report.get(), os.W_OK):
mb.showerror("Error","Permission denied to create report! Run with higher privilege.")
return

if os.path.exists(self.pcap_file.get()):

# Disable controls when performing analysis
self.trigger['state'] = 'disabled'
self.to_menu['state'] = 'disabled'
self.from_menu['state'] = 'disabled'

self.progressbar.start()
result = q.Queue()

# PcapRead - First of All!
#result = q.Queue()
packet_read = threading.Thread(target=pcap_reader.PcapEngine,args=(self.pcap_file.get(),"scapy"))
packet_read.start()
while packet_read.is_alive():
self.progressbar.update()
packet_read.join()
self.progressbar.stop()

# Report Generation of the PcapData


#packet_read.join()
#self.capture_read = result.get()
reportThreadpcap = threading.Thread(target=report_generator.reportGen(self.destination_report.get(), self.filename).packetDetails,args=())
reportThreadpcap.start()
#self.option.set("Tor")
self.option.trace("w",self.map_select)
#self.option.trace("w",self.map_select)
#self.option.set("Tor")
self.name_servers = ""

# Reset
self.details_fetch = 0
self.to_hosts = ["All"]
self.from_hosts = ["All"]


# Default filter values
self.to_menu['values'] = self.to_hosts
self.from_menu['values'] = self.from_hosts
self.from_menu.set("All")
self.to_menu.set("All")
self.option.set("All")

"""
# Filters update
# Reset Option Menu with the values fetched from the pcap
menu1 = self.to_menu["menu"]
menu1.delete(0, "end")
for ip in memory.destination_hosts:
menu1.add_command(label=ip, command=lambda value=ip: self.to_ip.set(value))
menu1.add_command(label="All", command=lambda value="All": self.to_ip.set(value))
menu = self.from_menu["menu"]
menu.delete(0, "end")
for mac in memory.lan_hosts:
menu.add_command(label=memory.lan_hosts[mac]["ip"], command=lambda value=memory.lan_hosts[mac]["ip"]: self.from_ip.set(value))
menu1.add_command(label=memory.lan_hosts[mac]["ip"], command=lambda value=memory.lan_hosts[mac]["ip"]: self.to_ip.set(value))
menu.add_command(label="All", command=lambda value="All": self.from_ip.set(value))
"""
self.progressbar.start()
self.to_hosts += list(memory.destination_hosts.keys())
for mac in list(memory.lan_hosts.keys()):
self.progressbar.update()
self.from_hosts.append(memory.lan_hosts[mac]["ip"])
self.to_hosts = list(set(self.to_hosts + self.from_hosts))
self.to_menu['values'] = self.to_hosts
self.from_menu['values'] = self.from_hosts
self.progressbar.stop()

# Enable controls
self.trigger['state'] = 'normal'
self.to_menu['state'] = 'normal'
self.from_menu['state'] = 'normal'
else:
mb.showerror("Error","File Not Found !")

def generate_graph(self):
if self.name_servers == "":
result = q.Queue()
if self.details_fetch == 0:

# Threads to fetch communication and device details
#result = q.Queue()
t = threading.Thread(target=communication_details_fetch.trafficDetailsFetch,args=("sock",))
t1 = threading.Thread(target=device_details_fetch.fetchDeviceDetails("ieee").fetch_info, args=())
t.start()
t1.start()
self.progressbar.start()
while t.is_alive():
self.progressbar.update()
t.join()
self.progressbar.stop()
#self.name_servers = result.get()
t1.join()

# Report Generation Control and Filters update (Here?)
self.details_fetch = 1

# Report Creation Threads
reportThread = threading.Thread(target=report_generator.reportGen(self.destination_report.get(), self.filename).communicationDetailsReport,args=())
reportThread.start()
reportThread = threading.Thread(target=report_generator.reportGen(self.destination_report.get(), self.filename).deviceDetailsReport,args=())
reportThread.start()

self.progressbar.stop()

self.image_file = os.path.join(self.destination_report.get(), "Report", self.filename+"_"+self.option.get()+".png")
# Loding the generated map
options = self.option.get()+"_"+self.to_ip.get()+"_"+self.from_ip.get()
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(),))
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()))
t1.start()
self.progressbar.start()
while t1.is_alive():
Expand All @@ -171,8 +277,6 @@ def generate_graph(self):
else:
self.label.grid_forget()
self.load_image()
reportThread = threading.Thread(target=report_generator.reportGen(self.destination_report.get(), self.filename).deviceDetailsReport,args=())
reportThread.start()

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)
Expand All @@ -185,6 +289,7 @@ def load_image(self):

def map_select(self, *args):
print(self.option.get())
print(self.to_ip.get(), self.from_ip.get())
self.generate_graph()

def zoom_in(self):
Expand Down

0 comments on commit e668abb

Please sign in to comment.