def __init__(self, netzob): super(NetworkCapturer, self).__init__("NETWORK CAPTURER", netzob) # create logger with the given configuration self.bpfFilter = None self.importLayer = 4 self._payloadDict = {} self.envDeps = EnvironmentalDependencies()
def __init__(self, netzob): AbstractImporter.__init__(self, "THIRD PARTY IMPORT") self.netzob = netzob # create the environmental dependancy object self.envDeps = EnvironmentalDependencies() # create logger with the given configuration self.log = logging.getLogger('netzob.Import.ThirdPartyImporter.py') self.messages = [] ospyImporter = OSpy() # Creates the list of third parties self.thirdParties = [ospyImporter] self.plugins = [] # Load plugins for plugin in self.thirdParties: self.plugins.append(plugin) self.init() self.dialog = Gtk.Dialog(title=_("Import data from third parties"), flags=0, buttons=None) self.dialog.show() self.dialog.vbox.pack_start(self.getPanel(), True, True, 0) self.dialog.set_size_request(1000, 600)
def __init__(self, netzob): super(IpcCapturer, self).__init__("IPC CAPTURER", netzob) self.netzob = netzob self.pid = None self.sniffOption = None self.stracePid = None self.aSniffThread = None self.doSniff = False self._payloadDict = {} self.envDeps = EnvironmentalDependencies() self.selected_fds = set()
def __init__(self, netzob): AbstractImporter.__init__(self, "THIRD PARTY IMPORT") self.netzob = netzob # create the environmental dependancy object self.envDeps = EnvironmentalDependencies() # create logger with the given configuration self.log = logging.getLogger('netzob.Import.ThirdPartyImporter.py') self.messages = [] ospyImporter = OSpy() # Creates the list of third parties self.thirdParties = [ospyImporter] self.plugins = [] # Load plugins for plugin in self.thirdParties: self.plugins.append(plugin) self.init() self.dialog = gtk.Dialog(title=_("Import data from third parties"), flags=0, buttons=None) self.dialog.show() self.dialog.vbox.pack_start(self.getPanel(), True, True, 0) self.dialog.set_size_request(1000, 600)
def __init__(self, netzob): AbstractImporter.__init__(self, "FILE IMPORT") self.netzob = netzob self.log = logging.getLogger('netzob.Import.FileImport.py') # create the environmental dependancy object self.envDeps = EnvironmentalDependencies() self.filesToBeImported = []
def __init__(self, netzob): super(DelimiterSeparatedImporter, self).__init__("FILE IMPORT", netzob) self.log = logging.getLogger('netzob.Import.FileImporter.py') # create the environmental dependancy object self.envDeps = EnvironmentalDependencies() self.importedFiles = [] self.messageSeparator = "" self.messageSeparatorStrategy = None
class IpcCapturer(AbstractCapturer): def kill(self): if self.stracePid is not None and self.stracePid.poll() is not None: self.stracePid.kill() if self.aSniffThread is not None and self.aSniffThread.isAlive(): self.aSniffThread._Thread__stop() #+---------------------------------------------- #| Constructor: #+---------------------------------------------- def __init__(self, netzob): super(IpcCapturer, self).__init__("IPC CAPTURER", netzob) self.netzob = netzob self.pid = None self.sniffOption = None self.stracePid = None self.aSniffThread = None self.doSniff = False self._payloadDict = {} self.envDeps = EnvironmentalDependencies() self.selected_fds = set() @property def payloadDict(self): return self._payloadDict.copy() def getProcessList(self): """getProcessList: Return the process list """ processList = [] uidUser = self.getUidOfCurrentUser() for pid in readProcesses(): if (uidUser == "0") or (uidUser == self.getUidOfProcess(pid)): processList.append(str(pid) + "\t" + str(readProcessCmdline(pid)[0])) return processList def getUidOfProcess(self, pid): cmd = "ps -p " + str(pid) + " -o uid= |tr -d \" \"" uid = os.popen(cmd).read().strip() return uid def getUidOfCurrentUser(self): cmd = "id" idResult = os.popen(cmd).read() m = re.search("uid=(\d+)\(.*", idResult) uid = m.group(1) return uid #+---------------------------------------------- #| Retrieve the filtered FD #+---------------------------------------------- def retrieveFDs(self, f_fs=True, f_net=True, f_proc=True): if self.pid is None: return [] if False: # f_net and (not f_fs) and (not f_proc): # -i for optimization cmd = "/usr/bin/lsof -i -a -d 0-1024 -a -p " + str(self.pid) + " | grep -v \"SIZE/OFF\" |awk -F \" \" {' print $5 \" \" $8 \" \" $9 \" \" $7'}" else: grep = "." if f_fs: grep += "DIR\|REG\|" if f_net: grep += "IPv4\|IPv6\|" if f_proc: grep += "CHR\|unix\|FIFO\|" grep = grep[:-2] cmd = "/usr/bin/lsof -d 0-1024 -a -p " + str(self.pid) + " | grep -v \"SIZE/OFF\" |awk -F \" \" {' print $4 \"##\" $5 \"##\" $9'} | grep \"" + grep + "\"" lines = os.popen(cmd).readlines() fdescrs = [] for fd in lines: elts = fd[:-1].split("##") fdescrs.append(elts) return fdescrs #+---------------------------------------------- #| Called when launching sniffing process #+---------------------------------------------- def startSniff(self, callback_readMessage): self.callback_readMessage = callback_readMessage self.selected_fds.clear() self.doSniff = True self.envDeps.captureEnvData() # Retrieve the environmental data (os specific, system specific, etc.) self.messages = [] if self.sniffOption == "filtered": (model, paths) = self.fdTreeview.get_selection().get_selected_rows() for path in paths: iter = model.get_iter(path) if(model.iter_is_valid(iter)): # Extract the fd number self.selected_fds.add(int(re.match("(\d+)", model.get_value(iter, 0)).group(1))) self.packets = [] self.aSniffThread = threading.Thread(None, self.sniffThread, None, (), {}) self.aSniffThread.start() #+---------------------------------------------- #| Called when stopping sniffing process #+---------------------------------------------- def stopSniff(self): self.doSniff = False if self.stracePid is not None: self.stracePid.kill() self.stracePid = None if self.aSniffThread is not None and self.aSniffThread.isAlive(): self.aSniffThread._Thread__stop() self.aSniffThread = None #+---------------------------------------------- #| Thread for sniffing a process #+---------------------------------------------- def sniffThread(self): logging.info("Launching sniff process") self.stracePid = subprocess.Popen(["/usr/bin/strace", "-xx", "-s", "65536", "-e", "read,write", "-p", str(self.pid)], stdout=subprocess.PIPE, stderr=subprocess.PIPE) GObject.io_add_watch(self.stracePid.stderr, GObject.IO_IN | GObject.IO_HUP, self.handle_new_pkt) #+---------------------------------------------- #| Handle new packet received by strace #+---------------------------------------------- def handle_new_pkt(self, src, event): # Retrieve details from the captured paket data = src.readline() compiledRegex = re.compile("(read|write)\((\d+), \"(.*)\", \d+\)[ \t]*=[ \t]*(\d+)") m = compiledRegex.match(data) if m is None: return self.doSniff direction = data[m.start(1): m.end(1)] fd = int(data[m.start(2): m.end(2)]) pkt = data[m.start(3): m.end(3)] pkt = pkt.replace("\\x", "") returnCode = int(data[m.start(4): m.end(4)]) # Apply filter if self.sniffOption == "fs": if not self.getTypeFromFD(int(fd)) == "fs": return self.doSniff elif self.sniffOption == "network": if not self.getTypeFromFD(int(fd)) == "network": return self.doSniff elif self.sniffOption == "ipc": if not self.getTypeFromFD(int(fd)) == "ipc": return self.doSniff elif self.sniffOption == "filtered": if not fd in self.selected_fds: return self.doSniff mUuid = str(uuid.uuid4()) mTimestamp = int(time.time()) message = IPCMessage(mUuid, mTimestamp, pkt, self.getTypeFromFD(int(fd)), fd, direction) self._payloadDict[mUuid] = pkt self.messages.append(message) self.callback_readMessage(message) return self.doSniff #+---------------------------------------------- #| GETTERS #+---------------------------------------------- def getTypeFromFD(self, fd): path = "/proc/" + str(self.pid) + "/fd/" + str(fd) if os.path.realpath(path).find("socket:[", 0) != -1: return "network" elif os.path.isfile(os.path.realpath(path)) or os.path.isdir(os.path.realpath(path)): return "fs" else: return "ipc" def getMessageDetails(self, messageID): if not messageID in self._payloadDict: errorMessage = _("Message ID: {0} not found in importer " + "message list").format(messageID) logging.error(errorMessage) raise NetzobImportException("IPC", errorMessage, ERROR) payload = self._payloadDict[messageID] return TypeConvertor.hexdump(TypeConvertor.netzobRawToPythonRaw(payload))
class ThirdPartyImport(AbstractImporter): def new(self): pass def update(self): pass def clear(self): pass def kill(self): pass #+---------------------------------------------- #| Constructor: #+---------------------------------------------- def __init__(self, netzob): AbstractImporter.__init__(self, "THIRD PARTY IMPORT") self.netzob = netzob # create the environmental dependancy object self.envDeps = EnvironmentalDependencies() # create logger with the given configuration self.log = logging.getLogger('netzob.Import.ThirdPartyImporter.py') self.messages = [] ospyImporter = OSpy() # Creates the list of third parties self.thirdParties = [ospyImporter] self.plugins = [] # Load plugins for plugin in self.thirdParties: self.plugins.append(plugin) self.init() self.dialog = gtk.Dialog(title=_("Import data from third parties"), flags=0, buttons=None) self.dialog.show() self.dialog.vbox.pack_start(self.getPanel(), True, True, 0) self.dialog.set_size_request(1000, 600) def init(self): self.fileName = "" self.thirdParty = "" # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Main panel # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ self.panel = gtk.Table(rows=10, columns=8, homogeneous=True) self.panel.show() # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Select a file # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ label_selectSource = gtk.Label(_("Select data source")) label_selectSource.show() entry_filepath = gtk.Entry() entry_filepath.set_text("") entry_filepath.show() but_source = gtk.Button("...") but_source.show() but_source.connect("clicked", self.selectFiles, entry_filepath) self.panel.attach(label_selectSource, 0, 1, 0, 1, xoptions=gtk.FILL | gtk.EXPAND, yoptions=gtk.FILL | gtk.EXPAND, xpadding=5, ypadding=5) self.panel.attach(entry_filepath, 1, 5, 0, 1, xoptions=gtk.FILL | gtk.EXPAND, yoptions=gtk.FILL | gtk.EXPAND, xpadding=5, ypadding=5) self.panel.attach(but_source, 5, 6, 0, 1, xoptions=gtk.FILL | gtk.EXPAND, yoptions=gtk.FILL | gtk.EXPAND, xpadding=5, ypadding=5) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Select a third party # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ label_thirdParty = gtk.Label(_("Select a third party")) label_thirdParty.show() self.thirdPartyStore = gtk.combo_box_entry_new_text() self.thirdPartyStore.show() self.thirdPartyStore.set_size_request(500, -1) self.thirdPartyStore.set_model(gtk.ListStore(str)) # register all the available plugins for plugin in self.plugins: self.thirdPartyStore.append_text(plugin.getName()) but_import = gtk.Button(_("Load")) but_import.show() but_import.connect("clicked", self.load_file, entry_filepath) self.panel.attach(label_thirdParty, 0, 1, 1, 2, xoptions=gtk.FILL | gtk.EXPAND, yoptions=gtk.FILL | gtk.EXPAND, xpadding=5, ypadding=5) self.panel.attach(self.thirdPartyStore, 1, 5, 1, 2, xoptions=gtk.FILL | gtk.EXPAND, yoptions=gtk.FILL | gtk.EXPAND, xpadding=5, ypadding=5) self.panel.attach(but_import, 5, 6, 1, 2, xoptions=gtk.FILL | gtk.EXPAND, yoptions=gtk.FILL | gtk.EXPAND, xpadding=5, ypadding=5) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # File details # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ scroll = gtk.ScrolledWindow() self.textview = gtk.TextView() self.textview.show() self.textview.get_buffer().create_tag("normalTag", family="Courier") scroll.add(self.textview) scroll.show() scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.panel.attach(scroll, 0, 6, 2, 10, xoptions=gtk.FILL | gtk.EXPAND, yoptions=gtk.FILL | gtk.EXPAND, xpadding=5, ypadding=5) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Extracted data # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ scroll2 = gtk.ScrolledWindow() self.lineView = gtk.TreeView(gtk.TreeStore(str, str)) # line number, content self.lineView.get_selection().set_mode(gtk.SELECTION_SINGLE) self.lineView.connect('button-press-event', self.button_press_on_message) cell = gtk.CellRendererText() # Col file descriptor column = gtk.TreeViewColumn(_("Message ID")) column.pack_start(cell, True) column.set_attributes(cell, text=0) self.lineView.append_column(column) self.lineView.show() scroll2.add(self.lineView) scroll2.show() scroll2.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.panel.attach(scroll2, 6, 8, 0, 10, xoptions=gtk.FILL, yoptions=gtk.FILL | gtk.EXPAND, xpadding=5, ypadding=5) # Button select packets for further analysis but = gtk.Button(label=_("Import")) but.show() but.connect("clicked", self.import_file) self.panel.attach(but, 2, 3, 10, 11, xoptions=0, yoptions=0, xpadding=5, ypadding=5) def button_press_on_message(self, treeview, event): x = int(event.x) y = int(event.y) info = treeview.get_path_at_pos(x, y) idMessage = None if info is not None: path = info[0] iter = treeview.get_model().get_iter(path) idMessage = str(treeview.get_model().get_value(iter, 0)) if idMessage == None: return # Search for the selected message selectedMessage = None for message in self.messages: if str(message.getID()) == idMessage: selectedMessage = message if selectedMessage == None: self.log.warn(_("Impossible to retrieve the message the user clicked on. Hum ?")) return self.displayMessage(selectedMessage) def load_file(self, button, entryPath): # First we retrieve the provided files filesToBeImported = [] # Computes the selected file(s) strPaths = entryPath.get_text().split(";") for strPath in strPaths: filename = unicode(strPath, "utf-8") if filename != None and filename != "" and os.path.isfile(filename): filesToBeImported.append(filename) else: logging.warning( _("Cannot load file {0}, its not a file.").format(filename)) # Start to load parsedMessages = self.loadMessagesFromPlugin(self.thirdPartyStore.get_active_text(), filesToBeImported) if parsedMessages == None: logging.warning(_("Impossible to find a plugin to import data from.")) else: logging.debug(_("A number of {0} messages were extracted.").format(len(parsedMessages))) for message in parsedMessages: self.messages.append(message) self.lineView.get_model().append(None, [message.getID(), message.getData()]) # We clean the display self.textview.get_buffer().insert_with_tags_by_name(self.textview.get_buffer().get_start_iter(), "", "normalTag") def loadMessagesFromPlugin(self, pluginName, files): for plugin in self.plugins: if plugin.getName() == pluginName: return plugin.parse(files) return None #+---------------------------------------------- #| Called when user select a list of packet #+---------------------------------------------- def import_file(self, button): currentProject = self.netzob.getCurrentProject() # We ask the confirmation dialog = gtk.MessageDialog(None, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, _("Are you sure to import the {0} computed messages in project {1}?").format(str(len(self.messages)), currentProject.getName())) # Checkbox for session vbox = gtk.VBox() vbox.show() hbox = gtk.HBox() hbox.show() vbox.pack_start(hbox) isSession = gtk.CheckButton(_("Check if this trace is a session")) isSession.set_active(False) isSession.show() # hbox.pack_start(isSession) dialog.vbox.pack_end(vbox, True, True, 0) resp = dialog.run() dialog.destroy() if resp == gtk.RESPONSE_OK: self.saveMessagesInProject(self.netzob.getCurrentWorkspace(), currentProject, self.messages) self.dialog.destroy() # We update the gui self.netzob.update() #+---------------------------------------------- #| Called when user import files #+---------------------------------------------- def selectFiles(self, button, label): aFile = "" chooser = gtk.FileChooserDialog(title=_("Select one or multiple file"), action=gtk.FILE_CHOOSER_ACTION_OPEN, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) chooser.set_select_multiple(True) filesToBeImported = [] # Computes the selected file(s) res = chooser.run() if res == gtk.RESPONSE_OK: for filename in chooser.get_filenames(): filename = unicode(filename, "utf-8") if filename != None and filename != "" and os.path.isfile(filename): filesToBeImported.append(filename) chooser.destroy() # We update the label with the list of the selected files label.set_text(";".join(filesToBeImported)) #+---------------------------------------------- #| Retrieve messages from files #+---------------------------------------------- def retrieveMessagesFromFiles(self): # We capture the current environment self.envDeps.captureEnvData() # We read each file and create one message for each file fileNumber = 0 self.messages = [] self.lineView.get_model().clear() for file in self.filesToBeImported: # Extraction of the metadata fileName = file.strip() size = os.path.getsize(file) creationDate = datetime.datetime.fromtimestamp(os.path.getctime(file)) modificationDate = datetime.datetime.fromtimestamp(os.path.getmtime(file)) owner = "none" # Retrieve the binary content of the file content = self.getNetzobRawContentOfFile(file) if not len(content) > 0: continue # Create a message message = FileMessage(uuid.uuid4(), 0, content, fileName, creationDate, modificationDate, owner, size, 0) self.messages.append(message) self.lineView.get_model().append(None, [message.getID(), content]) fileNumber += 1 # We clean the display self.textview.get_buffer().insert_with_tags_by_name(self.textview.get_buffer().get_start_iter(), "", "normalTag") def getNetzobRawContentOfFile(self, filename): file = open(filename, "rb") content = file.read() file.close() return TypeConvertor.stringToNetzobRaw(content) def entry_separator_callback(self, widget, entry): entry_text = widget.get_text() self.lineSeparator = entry_text self.updateMessageList() def updateMessageList(self): # We read each file and create one message for each file fileNumber = 0 # We split the content of each message and retrieve new messages self.retrieveMessagesFromFiles() new_messages = [] for message in self.messages: lineNumber = 0 if len(self.lineSeparator) > 0: splittedStrHexData = message.getData().split(self.lineSeparator) else: splittedStrHexData = [message.getData()] for s in splittedStrHexData: if len(s) > 0: message = FileMessage(uuid.uuid4(), 0, s, message.getFilename(), message.getCreationDate(), message.getModificationDate(), message.getOwner(), message.getSize(), lineNumber) new_messages.append(message) lineNumber += 1 # We save the new messages self.messages = [] self.messages.extend(new_messages) self.lineView.get_model().clear() for message in self.messages: self.lineView.get_model().append(None, [message.getID(), message.getData()]) # We clean the display self.textview.get_buffer().delete(self.textview.get_buffer().get_start_iter(), self.textview.get_buffer().get_end_iter()) def displayMessage(self, message): # Clean the hexdump view self.textview.get_buffer().delete(self.textview.get_buffer().get_start_iter(), self.textview.get_buffer().get_end_iter()) # Fecth the content of the message to display hexContent = TypeConvertor.hexdump(TypeConvertor.netzobRawToPythonRaw(message.getData())) # Update the hexdump self.textview.get_buffer().insert_with_tags_by_name(self.textview.get_buffer().get_start_iter(), hexContent, "normalTag") #+---------------------------------------------- #| GETTERS #+---------------------------------------------- def getPanel(self): return self.panel
class IpcCapturer(AbstractCapturer): def kill(self): if self.stracePid is not None and self.stracePid.poll() is not None: self.stracePid.kill() if self.aSniffThread is not None and self.aSniffThread.isAlive(): self.aSniffThread._Thread__stop() #+---------------------------------------------- #| Constructor: #+---------------------------------------------- def __init__(self, netzob): super(IpcCapturer, self).__init__("IPC CAPTURER", netzob) self.netzob = netzob self.pid = None self.sniffOption = None self.stracePid = None self.aSniffThread = None self.doSniff = False self._payloadDict = {} self.envDeps = EnvironmentalDependencies() self.selected_fds = set() @property def payloadDict(self): return self._payloadDict.copy() def getProcessList(self): """getProcessList: Return the process list """ processList = [] uidUser = self.getUidOfCurrentUser() for pid in readProcesses(): if (uidUser == "0") or (uidUser == self.getUidOfProcess(pid)): processList.append( str(pid) + "\t" + str(readProcessCmdline(pid)[0])) return processList def getUidOfProcess(self, pid): cmd = "ps -p " + str(pid) + " -o uid= |tr -d \" \"" uid = os.popen(cmd).read().strip() return uid def getUidOfCurrentUser(self): cmd = "id" idResult = os.popen(cmd).read() m = re.search("uid=(\d+)\(.*", idResult) uid = m.group(1) return uid #+---------------------------------------------- #| Retrieve the filtered FD #+---------------------------------------------- def retrieveFDs(self, f_fs=True, f_net=True, f_proc=True): if self.pid is None: return [] if False: # f_net and (not f_fs) and (not f_proc): # -i for optimization cmd = "/usr/bin/lsof -i -a -d 0-1024 -a -p " + str( self.pid ) + " | grep -v \"SIZE/OFF\" |awk -F \" \" {' print $5 \" \" $8 \" \" $9 \" \" $7'}" else: grep = "." if f_fs: grep += "DIR\|REG\|" if f_net: grep += "IPv4\|IPv6\|" if f_proc: grep += "CHR\|unix\|FIFO\|" grep = grep[:-2] cmd = "/usr/bin/lsof -d 0-1024 -a -p " + str( self.pid ) + " | grep -v \"SIZE/OFF\" |awk -F \" \" {' print $4 \"##\" $5 \"##\" $9'} | grep \"" + grep + "\"" lines = os.popen(cmd).readlines() fdescrs = [] for fd in lines: elts = fd[:-1].split("##") fdescrs.append(elts) return fdescrs #+---------------------------------------------- #| Called when launching sniffing process #+---------------------------------------------- def startSniff(self, callback_readMessage): self.callback_readMessage = callback_readMessage self.selected_fds.clear() self.doSniff = True self.envDeps.captureEnvData( ) # Retrieve the environmental data (os specific, system specific, etc.) self.messages = [] if self.sniffOption == "filtered": (model, paths) = self.fdTreeview.get_selection().get_selected_rows() for path in paths: iter = model.get_iter(path) if (model.iter_is_valid(iter)): # Extract the fd number self.selected_fds.add( int( re.match("(\d+)", model.get_value(iter, 0)).group(1))) self.packets = [] self.aSniffThread = threading.Thread(None, self.sniffThread, None, (), {}) self.aSniffThread.start() #+---------------------------------------------- #| Called when stopping sniffing process #+---------------------------------------------- def stopSniff(self): self.doSniff = False if self.stracePid is not None: self.stracePid.kill() self.stracePid = None if self.aSniffThread is not None and self.aSniffThread.isAlive(): self.aSniffThread._Thread__stop() self.aSniffThread = None #+---------------------------------------------- #| Thread for sniffing a process #+---------------------------------------------- def sniffThread(self): logging.info("Launching sniff process") self.stracePid = subprocess.Popen([ "/usr/bin/strace", "-xx", "-s", "65536", "-e", "read,write", "-p", str(self.pid) ], stdout=subprocess.PIPE, stderr=subprocess.PIPE) GObject.io_add_watch(self.stracePid.stderr, GObject.IO_IN | GObject.IO_HUP, self.handle_new_pkt) #+---------------------------------------------- #| Handle new packet received by strace #+---------------------------------------------- def handle_new_pkt(self, src, event): # Retrieve details from the captured paket data = src.readline() compiledRegex = re.compile( "(read|write)\((\d+), \"(.*)\", \d+\)[ \t]*=[ \t]*(\d+)") m = compiledRegex.match(data) if m is None: return self.doSniff direction = data[m.start(1):m.end(1)] fd = int(data[m.start(2):m.end(2)]) pkt = data[m.start(3):m.end(3)] pkt = pkt.replace("\\x", "") returnCode = int(data[m.start(4):m.end(4)]) # Apply filter if self.sniffOption == "fs": if not self.getTypeFromFD(int(fd)) == "fs": return self.doSniff elif self.sniffOption == "network": if not self.getTypeFromFD(int(fd)) == "network": return self.doSniff elif self.sniffOption == "ipc": if not self.getTypeFromFD(int(fd)) == "ipc": return self.doSniff elif self.sniffOption == "filtered": if not fd in self.selected_fds: return self.doSniff mUuid = str(uuid.uuid4()) mTimestamp = int(time.time()) message = IPCMessage(mUuid, mTimestamp, pkt, self.getTypeFromFD(int(fd)), fd, direction) self._payloadDict[mUuid] = pkt self.messages.append(message) self.callback_readMessage(message) return self.doSniff #+---------------------------------------------- #| GETTERS #+---------------------------------------------- def getTypeFromFD(self, fd): path = "/proc/" + str(self.pid) + "/fd/" + str(fd) if os.path.realpath(path).find("socket:[", 0) != -1: return "network" elif os.path.isfile(os.path.realpath(path)) or os.path.isdir( os.path.realpath(path)): return "fs" else: return "ipc" def getMessageDetails(self, messageID): if not messageID in self._payloadDict: errorMessage = _("Message ID: {0} not found in importer " + "message list").format(messageID) logging.error(errorMessage) raise NetzobImportException("IPC", errorMessage, ERROR) payload = self._payloadDict[messageID] return TypeConvertor.hexdump( TypeConvertor.netzobRawToPythonRaw(payload))
class ThirdPartyImport(AbstractImporter): def new(self): pass def update(self): pass def clear(self): pass def kill(self): pass #+---------------------------------------------- #| Constructor: #+---------------------------------------------- def __init__(self, netzob): AbstractImporter.__init__(self, "THIRD PARTY IMPORT") self.netzob = netzob # create the environmental dependancy object self.envDeps = EnvironmentalDependencies() # create logger with the given configuration self.log = logging.getLogger('netzob.Import.ThirdPartyImporter.py') self.messages = [] ospyImporter = OSpy() # Creates the list of third parties self.thirdParties = [ospyImporter] self.plugins = [] # Load plugins for plugin in self.thirdParties: self.plugins.append(plugin) self.init() self.dialog = Gtk.Dialog(title=_("Import data from third parties"), flags=0, buttons=None) self.dialog.show() self.dialog.vbox.pack_start(self.getPanel(), True, True, 0) self.dialog.set_size_request(1000, 600) def init(self): self.fileName = "" self.thirdParty = "" # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Main panel # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ self.panel = Gtk.Table(rows=10, columns=8, homogeneous=True) self.panel.show() # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Select a file # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ label_selectSource = Gtk.Label(label=_("Select data source")) label_selectSource.show() entry_filepath = Gtk.Entry() entry_filepath.set_text("") entry_filepath.show() but_source = Gtk.Button("...") but_source.show() but_source.connect("clicked", self.selectFiles, entry_filepath) self.panel.attach(label_selectSource, 0, 1, 0, 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, yoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, xpadding=5, ypadding=5) self.panel.attach(entry_filepath, 1, 5, 0, 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, yoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, xpadding=5, ypadding=5) self.panel.attach(but_source, 5, 6, 0, 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, yoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, xpadding=5, ypadding=5) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Select a third party # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ label_thirdParty = Gtk.Label(label=_("Select a third party")) label_thirdParty.show() self.thirdPartyStore = Gtk.ComboBoxText.new_with_entry() self.thirdPartyStore.show() self.thirdPartyStore.set_size_request(500, -1) self.thirdPartyStore.set_model(Gtk.ListStore(str)) # register all the available plugins for plugin in self.plugins: self.thirdPartyStore.append_text(plugin.getName()) but_import = Gtk.Button(_("Load")) but_import.show() but_import.connect("clicked", self.load_file, entry_filepath) self.panel.attach(label_thirdParty, 0, 1, 1, 2, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, yoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, xpadding=5, ypadding=5) self.panel.attach(self.thirdPartyStore, 1, 5, 1, 2, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, yoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, xpadding=5, ypadding=5) self.panel.attach(but_import, 5, 6, 1, 2, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, yoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, xpadding=5, ypadding=5) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # File details # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ scroll = Gtk.ScrolledWindow() self.textview = Gtk.TextView() self.textview.show() self.textview.get_buffer().create_tag("normalTag", family="Courier") scroll.add(self.textview) scroll.show() scroll.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.panel.attach(scroll, 0, 6, 2, 10, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, yoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, xpadding=5, ypadding=5) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Extracted data # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ scroll2 = Gtk.ScrolledWindow() self.lineView = Gtk.TreeView(Gtk.TreeStore(str, str)) # line number, content self.lineView.get_selection().set_mode(Gtk.SelectionMode.SINGLE) self.lineView.connect('button-press-event', self.button_press_on_message) cell = Gtk.CellRendererText() # Col file descriptor column = Gtk.TreeViewColumn(_("Message ID")) column.pack_start(cell, True) column.add_attribute(cell, "text", 0) self.lineView.append_column(column) self.lineView.show() scroll2.add(self.lineView) scroll2.show() scroll2.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.panel.attach(scroll2, 6, 8, 0, 10, xoptions=Gtk.AttachOptions.FILL, yoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, xpadding=5, ypadding=5) # Button select packets for further analysis but = Gtk.Button(label=_("Import")) but.show() but.connect("clicked", self.import_file) self.panel.attach(but, 2, 3, 10, 11, xoptions=0, yoptions=0, xpadding=5, ypadding=5) def button_press_on_message(self, treeview, event): x = int(event.x) y = int(event.y) info = treeview.get_path_at_pos(x, y) idMessage = None if info is not None: path = info[0] iter = treeview.get_model().get_iter(path) idMessage = str(treeview.get_model().get_value(iter, 0)) if idMessage is None: return # Search for the selected message selectedMessage = None for message in self.messages: if str(message.getID()) == idMessage: selectedMessage = message if selectedMessage is None: self.log.warn("Impossible to retrieve the message the user clicked on. Hum?") return self.displayMessage(selectedMessage) def load_file(self, button, entryPath): # First we retrieve the provided files filesToBeImported = [] # Computes the selected file(s) strPaths = entryPath.get_text().split(";") for strPath in strPaths: filename = unicode(strPath, "utf-8") if filename is not None and filename != "" and os.path.isfile(filename): filesToBeImported.append(filename) else: logging.warning("Cannot load file {0}, its not a file.".format(filename)) # Start to load parsedMessages = self.loadMessagesFromPlugin(self.thirdPartyStore.get_active_text(), filesToBeImported) if parsedMessages is None: logging.warning("Impossible to find a plugin to import data from.") else: logging.debug("A number of {0} messages were extracted.".format(len(parsedMessages))) for message in parsedMessages: self.messages.append(message) self.lineView.get_model().append(None, [message.getID(), message.getData()]) # We clean the display self.textview.get_buffer().insert_with_tags_by_name(self.textview.get_buffer().get_start_iter(), "", "normalTag") def loadMessagesFromPlugin(self, pluginName, files): for plugin in self.plugins: if plugin.getName() == pluginName: return plugin.parse(files) return None #+---------------------------------------------- #| Called when user select a list of packet #+---------------------------------------------- def import_file(self, button): currentProject = self.netzob.getCurrentProject() # We ask the confirmation dialog = Gtk.MessageDialog(None, Gtk.DialogFlags.DESTROY_WITH_PARENT, Gtk.MessageType.QUESTION, Gtk.ButtonsType.OK_CANCEL, "Are you sure to import the " + str(len(self.messages)) + " computed messages in project " + currentProject.getName() + ".") # Checkbox for session vbox = Gtk.VBox() vbox.show() hbox = Gtk.HBox() hbox.show() vbox.pack_start(hbox, True, True, 0) isSession = Gtk.CheckButton(_("Check if this trace is a session")) isSession.set_active(False) isSession.show() # hbox.pack_start(isSession, True, True, 0) dialog.vbox.pack_end(vbox, True, True, 0) resp = dialog.run() dialog.destroy() if resp == Gtk.ResponseType.OK: self.saveMessagesInProject(self.netzob.getCurrentWorkspace(), currentProject, self.messages) self.dialog.destroy() # We update the gui self.netzob.update() #+---------------------------------------------- #| Called when user import files #+---------------------------------------------- def selectFiles(self, button, label): aFile = "" chooser = Gtk.FileChooserDialog(title=_("Select one or multiple file"), action=Gtk.FileChooserAction.OPEN, buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK)) chooser.set_select_multiple(True) filesToBeImported = [] # Computes the selected file(s) res = chooser.run() if res == Gtk.ResponseType.OK: for filename in chooser.get_filenames(): filename = unicode(filename, "utf-8") if filename is not None and filename != "" and os.path.isfile(filename): filesToBeImported.append(filename) chooser.destroy() # We update the label with the list of the selected files label.set_text(";".join(filesToBeImported)) #+---------------------------------------------- #| Retrieve messages from files #+---------------------------------------------- def retrieveMessagesFromFiles(self): # We capture the current environment self.envDeps.captureEnvData() # We read each file and create one message for each file fileNumber = 0 self.messages = [] self.lineView.get_model().clear() for file in self.filesToBeImported: # Extraction of the metadata fileName = file.strip() size = os.path.getsize(file) creationDate = datetime.datetime.fromtimestamp(os.path.getctime(file)) modificationDate = datetime.datetime.fromtimestamp(os.path.getmtime(file)) owner = "none" # Retrieve the binary content of the file content = self.getNetzobRawContentOfFile(file) if not len(content) > 0: continue # Create a message message = FileMessage(str(uuid.uuid4()), 0, content, fileName, creationDate, modificationDate, owner, size, 0) self.messages.append(message) self.lineView.get_model().append(None, [message.getID(), content]) fileNumber += 1 # We clean the display self.textview.get_buffer().insert_with_tags_by_name(self.textview.get_buffer().get_start_iter(), "", "normalTag") def getNetzobRawContentOfFile(self, filename): file = open(filename, "rb") content = file.read() file.close() return TypeConvertor.stringToNetzobRaw(content) def entry_separator_callback(self, widget, entry): entry_text = widget.get_text() self.lineSeparator = entry_text self.updateMessageList() def updateMessageList(self): # We read each file and create one message for each file fileNumber = 0 # We split the content of each message and retrieve new messages self.retrieveMessagesFromFiles() new_messages = [] for message in self.messages: lineNumber = 0 if len(self.lineSeparator) > 0: splittedStrHexData = message.getData().split(self.lineSeparator) else: splittedStrHexData = [message.getData()] for s in splittedStrHexData: if len(s) > 0: message = FileMessage(str(uuid.uuid4()), 0, s, message.getFilename(), message.getCreationDate(), message.getModificationDate(), message.getOwner(), message.getSize(), lineNumber) new_messages.append(message) lineNumber += 1 # We save the new messages self.messages = [] self.messages.extend(new_messages) self.lineView.get_model().clear() for message in self.messages: self.lineView.get_model().append(None, [message.getID(), message.getData()]) # We clean the display self.textview.get_buffer().delete(self.textview.get_buffer().get_start_iter(), self.textview.get_buffer().get_end_iter()) def displayMessage(self, message): # Clean the hexdump view self.textview.get_buffer().delete(self.textview.get_buffer().get_start_iter(), self.textview.get_buffer().get_end_iter()) # Fecth the content of the message to display hexContent = TypeConvertor.hexdump(TypeConvertor.netzobRawToPythonRaw(message.getData())) # Update the hexdump self.textview.get_buffer().insert_with_tags_by_name(self.textview.get_buffer().get_start_iter(), hexContent, "normalTag") #+---------------------------------------------- #| GETTERS #+---------------------------------------------- def getPanel(self): return self.panel
class FileImport(AbstractImporter): #+---------------------------------------------- #| Constructor: #+---------------------------------------------- def __init__(self, netzob): AbstractImporter.__init__(self, "FILE IMPORT") self.netzob = netzob self.log = logging.getLogger('netzob.Import.FileImport.py') # create the environmental dependancy object self.envDeps = EnvironmentalDependencies() self.filesToBeImported = [] #+---------------------------------------------- #| Retrieve messages from files #+---------------------------------------------- def retrieveMessagesFromFiles(self): # We capture the current environment self.envDeps.captureEnvData() # We read each file and create one message for each file fileNumber = 0 self.messages = [] for file in self.filesToBeImported: # Extraction of the metadata fileName = file.strip() size = os.path.getsize(file) creationDate = datetime.datetime.fromtimestamp(os.path.getctime(file)) modificationDate = datetime.datetime.fromtimestamp(os.path.getmtime(file)) owner = "none" # Retrieve the binary content of the file content = self.getNetzobRawContentOfFile(file) if not len(content) > 0: continue # Create a message message = FileMessage(uuid.uuid4(), 0, content, fileName, creationDate, modificationDate, owner, size, 0) self.messages.append(message) fileNumber += 1 def getNetzobRawContentOfFile(self, filename): file = open(filename, "rb") content = file.read() file.close() return TypeConvertor.stringToNetzobRaw(content) def applySeparatorOnFiles(self, lineSeparator): # We read each file and create one message for each file fileNumber = 0 # We split the content of each message and retrieve new messages self.retrieveMessagesFromFiles() new_messages = [] for message in self.messages: lineNumber = 0 if len(lineSeparator) > 0: splittedStrHexData = message.getData().split(lineSeparator) else: splittedStrHexData = [message.getData()] for s in splittedStrHexData: if len(s) > 0: message = FileMessage(uuid.uuid4(), 0, s, message.getFilename(), message.getCreationDate(), message.getModificationDate(), message.getOwner(), message.getSize(), lineNumber) new_messages.append(message) lineNumber += 1 # We save the new messages self.messages = [] self.messages.extend(new_messages)
class NetworkCapturer(AbstractCapturer): """NetworkCapturer: This class offers the capability to capture traffic from live network. """ INVALID_BPF_FILTER = 0 INVALID_LAYER2 = 1 INVALID_LAYER3 = 2 INVALID_LAYER4 = 3 def __init__(self, netzob): super(NetworkCapturer, self).__init__("NETWORK CAPTURER", netzob) # create logger with the given configuration self.bpfFilter = None self.importLayer = 4 self._payloadDict = {} self.envDeps = EnvironmentalDependencies() @property def payloadDict(self): return self._payloadDict.copy() def setBPFFilter(self, bpfFilter): self.bpfFilter = bpfFilter def setImportLayer(self, importLayer): if not importLayer in [1, 2, 3, 4]: raise self.importLayer = importLayer def getNetworkDevices(self): interfaces = [] # list of interfaces try: interfaces = pcapy.findalldevs() except: logging.warn("You don't have enough permissions to open any network interface on this system. Please look at the README.rst file for more information.") return interfaces def readMessages(self, callback_readMessage, device, count, time): """Read all messages from all opened PCAP files""" self.callback_readMessage = callback_readMessage self.envDeps.captureEnvData() # Retrieve the environmental data (os specific, system specific, etc.) self.messages = [] aSniffThread = threading.Thread(None, self.sniffingThread, None, (device, count, time), {}) aSniffThread.start() #+---------------------------------------------- #| Thread for sniffing work #+---------------------------------------------- def sniffingThread(self, device, count, time): logging.info("Launching sniff process on dev {0} with: count={1}, timeout={2}, filter=\"{3}\"".format(device, count, time, self.bpfFilter)) sniffer = pcapy.open_live(device, 1024, False, int(time)) try: sniffer.setfilter(self.bpfFilter) except: logging.warn("The provided filter is not valid (it should respects the BPF format") return self.datalink = sniffer.datalink() if self.datalink != pcapy.DLT_EN10MB and self.datalink != pcapy.DLT_LINUX_SLL: errorMessage = _("This device cannot be sniffed since the " + "layer 2 is not supported ({0})").format(str(self.datalink)) self.log.warn(errorMessage) raise NetzobImportException("PCAP", errorMessage, ERROR, self.INVALID_LAYER2) else: sniffer.loop(int(count), self._packetHandler) def _packetHandler(self, header, payload): """Decode a packet""" mUuid = str(uuid.uuid4()) mTimestamp = int(time.time()) message = None if self.importLayer == 1: if len(payload) == 0: return message = RawMessage( mUuid, mTimestamp, payload.encode("hex")) self._payloadDict[mUuid] = payload elif self.importLayer == 2: (l2Proto, l2SrcAddr, l2DstAddr, l2Payload, etherType) = \ self.decodeLayer2(header, payload) if len(l2Payload) == 0: return message = L2NetworkMessage( mUuid, mTimestamp, l2Payload.encode("hex"), l2Proto, l2SrcAddr, l2DstAddr) self._payloadDict[mUuid] = payload elif self.importLayer == 3: (l2Proto, l2SrcAddr, l2DstAddr, l2Payload, etherType) = \ self.decodeLayer2(header, payload) try: (l3Proto, l3SrcAddr, l3DstAddr, l3Payload, ipProtocolNum) = \ self.decodeLayer3(etherType, l2Payload) except TypeError: return if len(l3Payload) == 0: return message = L3NetworkMessage( mUuid, mTimestamp, l3Payload.encode("hex"), l2Proto, l2SrcAddr, l2DstAddr, l3Proto, l3SrcAddr, l3DstAddr) self._payloadDict[mUuid] = payload else: (l2Proto, l2SrcAddr, l2DstAddr, l2Payload, etherType) = \ self.decodeLayer2(header, payload) try: (l3Proto, l3SrcAddr, l3DstAddr, l3Payload, ipProtocolNum) = \ self.decodeLayer3(etherType, l2Payload) (l4Proto, l4SrcPort, l4DstPort, l4Payload) = \ self.decodeLayer4(ipProtocolNum, l3Payload) except TypeError: return if l4Payload.encode("hex") == "": return if len(l4Payload) == 0: return message = L4NetworkMessage( mUuid, mTimestamp, l4Payload.encode("hex"), l2Proto, l2SrcAddr, l2DstAddr, l3Proto, l3SrcAddr, l3DstAddr, l4Proto, l4SrcPort, l4DstPort) self._payloadDict[mUuid] = payload self.messages.append(message) self.callback_readMessage(message) def decodeLayer2(self, header, payload): def formatMacAddress(arrayMac): return ":".join("{0:0>2}".format( hex(b)[2:]) for b in arrayMac.tolist()) if self.datalink == pcapy.DLT_EN10MB: l2Decoder = Decoders.EthDecoder() l2Proto = "Ethernet" layer2 = l2Decoder.decode(payload) l2SrcAddr = formatMacAddress(layer2.get_ether_shost()) l2DstAddr = formatMacAddress(layer2.get_ether_dhost()) elif self.datalink == pcapy.DLT_LINUX_SLL: l2Decoder = Decoders.LinuxSLLDecoder() l2Proto = "Linux SLL" layer2 = l2Decoder.decode(payload) l2SrcAddr = layer2.get_addr() l2DstAddr = None l2Payload = payload[layer2.get_header_size():] etherType = layer2.get_ether_type() return (l2Proto, l2SrcAddr, l2DstAddr, l2Payload, etherType) def decodeLayer3(self, etherType, l2Payload): if etherType == Packets.IP.ethertype: l3Proto = "IP" l3Decoder = Decoders.IPDecoder() layer3 = l3Decoder.decode(l2Payload) l3SrcAddr = layer3.get_ip_src() l3DstAddr = layer3.get_ip_dst() l3Payload = l2Payload[layer3.get_header_size():] ipProtocolNum = layer3.get_ip_p() return (l3Proto, l3SrcAddr, l3DstAddr, l3Payload, ipProtocolNum) else: warnMessage = _("Cannot import one of the provided packets since " + "its layer 3 is unsupported (Only IP is " + "currently supported, packet ethernet " + "type = {0})").format(etherType) logging.warn(warnMessage) def decodeLayer4(self, ipProtocolNum, l3Payload): if ipProtocolNum == Packets.UDP.protocol: l4Proto = "UDP" l4Decoder = Decoders.UDPDecoder() layer4 = l4Decoder.decode(l3Payload) l4SrcPort = layer4.get_uh_sport() l4DstPort = layer4.get_uh_dport() l4Payload = layer4.get_data_as_string() return (l4Proto, l4SrcPort, l4DstPort, l4Payload) elif ipProtocolNum == Packets.TCP.protocol: l4Proto = "TCP" l4Decoder = Decoders.TCPDecoder() layer4 = l4Decoder.decode(l3Payload) l4SrcPort = layer4.get_th_sport() l4DstPort = layer4.get_th_dport() l4Payload = layer4.get_data_as_string() return (l4Proto, l4SrcPort, l4DstPort, l4Payload) else: warnMessage = "Cannot import one of the provided packets since its layer 4 is unsupported (Only UDP and TCP are currently supported, packet IP protocol number = {0})".format(ipProtocolNum) logging.warn(warnMessage) def getMessageDetails(self, messageID): if not messageID in self._payloadDict: errorMessage = "Message ID: {0} not found in importer message list".format(messageID) logging.error(errorMessage) raise NetzobImportException("PCAP", errorMessage, ERROR) decoder = Decoders.EthDecoder() payload = self._payloadDict[messageID] return decoder.decode(payload)
def init(self): # create the environmental dependancy object self.envDeps = EnvironmentalDependencies() # Default line separator is <CR> self.fileName = "" # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Main panel # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ self.panel = Gtk.Table(rows=10, columns=8, homogeneous=True) self.panel.show() # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Select a file # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ but = Gtk.Button(_("Select file(s)")) but.show() entry_filepath = Gtk.Entry() # entry_filepath.set_width_chars(50) entry_filepath.set_text("") entry_filepath.show() but.connect("clicked", self.selectFiles, entry_filepath) self.panel.attach( but, 0, 2, 0, 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, yoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, xpadding=5, ypadding=5) self.panel.attach( entry_filepath, 2, 6, 0, 1, xoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, yoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, xpadding=5, ypadding=5) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Extracted data # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ scroll2 = Gtk.ScrolledWindow() self.lineView = Gtk.TreeView(Gtk.TreeStore( str, str, str)) # id message, type, content self.lineView.get_selection().set_mode(Gtk.SelectionMode.SINGLE) #self.lineView.connect('button-press-event', self.button_press_on_message) cell = Gtk.CellRendererText() # Col file descriptor column = Gtk.TreeViewColumn(_("Message ID")) column.pack_start(cell, True) column.add_attribute(cell, "text", 0) self.lineView.append_column(column) column = Gtk.TreeViewColumn(_("Type")) column.pack_start(cell, True) column.add_attribute(cell, "text", 1) self.lineView.append_column(column) column = Gtk.TreeViewColumn(_("Content")) column.pack_start(cell, True) column.add_attribute(cell, "text", 2) self.lineView.append_column(column) self.lineView.show() scroll2.add(self.lineView) scroll2.show() scroll2.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC) self.panel.attach(scroll2, 0, 6, 1, 10, xoptions=Gtk.AttachOptions.FILL, yoptions=Gtk.AttachOptions.FILL | Gtk.AttachOptions.EXPAND, xpadding=5, ypadding=5) # Button select packets for further analysis but = Gtk.Button(label=_("Import")) but.show() but.connect("clicked", self.import_file) self.panel.attach(but, 2, 3, 10, 11, xoptions=0, yoptions=0, xpadding=5, ypadding=5)
def init(self): # create the environmental dependancy object self.envDeps = EnvironmentalDependencies() # Network Capturing Panel self.panel = gtk.Table(rows=7, columns=4, homogeneous=False) self.panel.show() # Network devices label = gtk.Label(_("Network devices")) label.show() listNetworkDevice = gtk.combo_box_entry_new_text() listNetworkDevice.show() listNetworkDevice.set_size_request(300, -1) listNetworkDevice.set_model(gtk.ListStore(str)) listNetworkDevice.get_model().clear() # list of interfaces try: interfaces = pcapy.findalldevs() except: self.log.warn(_("You don't have enough permissions to open any network interface on this system.")) interfaces = [] for interface in interfaces: listNetworkDevice.append_text(str(interface)) self.panel.attach(label, 0, 1, 0, 1, xoptions=gtk.FILL, yoptions=0, xpadding=5, ypadding=5) self.panel.attach(listNetworkDevice, 1, 2, 0, 1, xoptions=gtk.FILL, yoptions=0, xpadding=5, ypadding=5) # BPF filter label = gtk.Label(_("BPF filter")) label.show() entry_filter = gtk.Entry() entry_filter.set_width_chars(50) entry_filter.show() entry_filter.set_text("tcp port 80") self.panel.attach(label, 0, 1, 1, 2, xoptions=gtk.FILL, yoptions=0, xpadding=5, ypadding=5) self.panel.attach(entry_filter, 1, 2, 1, 2, xoptions=gtk.FILL, yoptions=0, xpadding=5, ypadding=5) # Count capturing limit label = gtk.Label(_("Count limit")) label.show() entry_count = gtk.Entry() entry_count.show() entry_count.set_text("10") self.panel.attach(label, 0, 1, 2, 3, xoptions=0, yoptions=0, xpadding=5, ypadding=5) self.panel.attach(entry_count, 1, 2, 2, 3, xoptions=0, yoptions=0, xpadding=5, ypadding=5) # Time capturing limit label = gtk.Label(_("Timeout")) label.show() entry_time = gtk.Entry() entry_time.show() entry_time.set_text("10") self.panel.attach(label, 0, 1, 3, 4, xoptions=0, yoptions=0, xpadding=5, ypadding=5) self.panel.attach(entry_time, 1, 2, 3, 4, xoptions=0, yoptions=0, xpadding=5, ypadding=5) # Sniff launching button but = gtk.Button(label=_("Sniff traffic")) but.show() but.connect("clicked", self.launch_sniff, listNetworkDevice, entry_filter, entry_count, entry_time) self.panel.attach(but, 1, 2, 5, 6, xoptions=0, yoptions=0, xpadding=5, ypadding=5) # Packet list scroll = gtk.ScrolledWindow() self.treestore = gtk.TreeStore(int, str, str, str, str, str, int) # pktID, proto (udp/tcp), IP.src, IP.dst, sport, dport, timestamp treeview = gtk.TreeView(self.treestore) treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE) treeview.connect("cursor-changed", self.packet_details) cell = gtk.CellRendererText() # Col proto column = gtk.TreeViewColumn(_("Proto")) column.pack_start(cell, True) column.set_attributes(cell, text=1) treeview.append_column(column) # Col IP.src column = gtk.TreeViewColumn(_("IP source")) column.pack_start(cell, True) column.set_attributes(cell, text=2) treeview.append_column(column) # Col IP.dst column = gtk.TreeViewColumn(_("IP dest")) column.pack_start(cell, True) column.set_attributes(cell, text=3) treeview.append_column(column) # Col {TCP,UDP}.sport column = gtk.TreeViewColumn(_("sport")) column.pack_start(cell, True) column.set_attributes(cell, text=4) treeview.append_column(column) # Col {TCP,UDP}.dport column = gtk.TreeViewColumn(_("dport")) column.pack_start(cell, True) column.set_attributes(cell, text=5) treeview.append_column(column) treeview.show() scroll.add(treeview) scroll.show() scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.panel.attach(scroll, 0, 2, 4, 5, xoptions=gtk.FILL, yoptions=gtk.FILL | gtk.EXPAND, xpadding=5, ypadding=5) # Button select packets for further analysis but = gtk.Button(label=_("Save selected packets")) but.show() but.connect("clicked", self.save_packets, treeview) self.panel.attach(but, 1, 2, 6, 7, xoptions=0, yoptions=0, xpadding=5, ypadding=5) # Packet detail scroll = gtk.ScrolledWindow() self.textview = gtk.TextView() self.textview.show() self.textview.get_buffer().create_tag("normalTag", family="Courier") scroll.add(self.textview) scroll.show() scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.panel.attach(scroll, 2, 4, 0, 7, xoptions=gtk.FILL | gtk.EXPAND, yoptions=gtk.FILL | gtk.EXPAND, xpadding=5, ypadding=5)
class NetworkImport(AbstractImporter): def new(self): pass def update(self): pass def clear(self): pass def kill(self): pass #+-----------------------------------------------------------------------+ #| Constructor: #| @param zob: a reference to the main netzob.py #+-----------------------------------------------------------------------+ def __init__(self, zob): AbstractImporter.__init__(self, "NETWORK IMPORT") self.zob = zob # create logger with the given configuration self.log = logging.getLogger('netzob.Import.Network.py') self.packets = [] self.init() self.dialog = gtk.Dialog(title=_("Capture network trafic"), flags=0, buttons=None) self.dialog.show() self.dialog.vbox.pack_start(self.getPanel(), True, True, 0) self.dialog.set_size_request(900, 700) def init(self): # create the environmental dependancy object self.envDeps = EnvironmentalDependencies() # Network Capturing Panel self.panel = gtk.Table(rows=7, columns=4, homogeneous=False) self.panel.show() # Network devices label = gtk.Label(_("Network devices")) label.show() listNetworkDevice = gtk.combo_box_entry_new_text() listNetworkDevice.show() listNetworkDevice.set_size_request(300, -1) listNetworkDevice.set_model(gtk.ListStore(str)) listNetworkDevice.get_model().clear() # list of interfaces try: interfaces = pcapy.findalldevs() except: self.log.warn(_("You don't have enough permissions to open any network interface on this system.")) interfaces = [] for interface in interfaces: listNetworkDevice.append_text(str(interface)) self.panel.attach(label, 0, 1, 0, 1, xoptions=gtk.FILL, yoptions=0, xpadding=5, ypadding=5) self.panel.attach(listNetworkDevice, 1, 2, 0, 1, xoptions=gtk.FILL, yoptions=0, xpadding=5, ypadding=5) # BPF filter label = gtk.Label(_("BPF filter")) label.show() entry_filter = gtk.Entry() entry_filter.set_width_chars(50) entry_filter.show() entry_filter.set_text("tcp port 80") self.panel.attach(label, 0, 1, 1, 2, xoptions=gtk.FILL, yoptions=0, xpadding=5, ypadding=5) self.panel.attach(entry_filter, 1, 2, 1, 2, xoptions=gtk.FILL, yoptions=0, xpadding=5, ypadding=5) # Count capturing limit label = gtk.Label(_("Count limit")) label.show() entry_count = gtk.Entry() entry_count.show() entry_count.set_text("10") self.panel.attach(label, 0, 1, 2, 3, xoptions=0, yoptions=0, xpadding=5, ypadding=5) self.panel.attach(entry_count, 1, 2, 2, 3, xoptions=0, yoptions=0, xpadding=5, ypadding=5) # Time capturing limit label = gtk.Label(_("Timeout")) label.show() entry_time = gtk.Entry() entry_time.show() entry_time.set_text("10") self.panel.attach(label, 0, 1, 3, 4, xoptions=0, yoptions=0, xpadding=5, ypadding=5) self.panel.attach(entry_time, 1, 2, 3, 4, xoptions=0, yoptions=0, xpadding=5, ypadding=5) # Sniff launching button but = gtk.Button(label=_("Sniff traffic")) but.show() but.connect("clicked", self.launch_sniff, listNetworkDevice, entry_filter, entry_count, entry_time) self.panel.attach(but, 1, 2, 5, 6, xoptions=0, yoptions=0, xpadding=5, ypadding=5) # Packet list scroll = gtk.ScrolledWindow() self.treestore = gtk.TreeStore(int, str, str, str, str, str, int) # pktID, proto (udp/tcp), IP.src, IP.dst, sport, dport, timestamp treeview = gtk.TreeView(self.treestore) treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE) treeview.connect("cursor-changed", self.packet_details) cell = gtk.CellRendererText() # Col proto column = gtk.TreeViewColumn(_("Proto")) column.pack_start(cell, True) column.set_attributes(cell, text=1) treeview.append_column(column) # Col IP.src column = gtk.TreeViewColumn(_("IP source")) column.pack_start(cell, True) column.set_attributes(cell, text=2) treeview.append_column(column) # Col IP.dst column = gtk.TreeViewColumn(_("IP dest")) column.pack_start(cell, True) column.set_attributes(cell, text=3) treeview.append_column(column) # Col {TCP,UDP}.sport column = gtk.TreeViewColumn(_("sport")) column.pack_start(cell, True) column.set_attributes(cell, text=4) treeview.append_column(column) # Col {TCP,UDP}.dport column = gtk.TreeViewColumn(_("dport")) column.pack_start(cell, True) column.set_attributes(cell, text=5) treeview.append_column(column) treeview.show() scroll.add(treeview) scroll.show() scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.panel.attach(scroll, 0, 2, 4, 5, xoptions=gtk.FILL, yoptions=gtk.FILL | gtk.EXPAND, xpadding=5, ypadding=5) # Button select packets for further analysis but = gtk.Button(label=_("Save selected packets")) but.show() but.connect("clicked", self.save_packets, treeview) self.panel.attach(but, 1, 2, 6, 7, xoptions=0, yoptions=0, xpadding=5, ypadding=5) # Packet detail scroll = gtk.ScrolledWindow() self.textview = gtk.TextView() self.textview.show() self.textview.get_buffer().create_tag("normalTag", family="Courier") scroll.add(self.textview) scroll.show() scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.panel.attach(scroll, 2, 4, 0, 7, xoptions=gtk.FILL | gtk.EXPAND, yoptions=gtk.FILL | gtk.EXPAND, xpadding=5, ypadding=5) #+---------------------------------------------- #| Called when user select a list of packet #+---------------------------------------------- def save_packets(self, button, treeview): currentProject = self.zob.getCurrentProject() # We compute the selected messages # Create the new XML structure messages = [] selection = treeview.get_selection() (model, paths) = selection.get_selected_rows() for path in paths: iter = model.get_iter(path) if(model.iter_is_valid(iter)): packetID = model.get_value(iter, 0) proto = model.get_value(iter, 1) timestamp = str(model.get_value(iter, 6)) packetPayload = self.packets[packetID] eth_decoder = Decoders.EthDecoder() ip_decoder = Decoders.IPDecoder() udp_decoder = Decoders.UDPDecoder() tcp_decoder = Decoders.TCPDecoder() IPsrc = None IPdst = None Sport = None Dport = None Data = None ethernet = eth_decoder.decode(packetPayload) if ethernet.get_ether_type() == Packets.IP.ethertype: ip = ip_decoder.decode(packetPayload[ethernet.get_header_size():]) IPsrc = ip.get_ip_src() IPdst = ip.get_ip_dst() if ip.get_ip_p() == Packets.UDP.protocol: udp = udp_decoder.decode(packetPayload[ethernet.get_header_size() + ip.get_header_size():]) Sport = udp.get_uh_sport() Dport = udp.get_uh_dport() Data = udp.get_data_as_string() if ip.get_ip_p() == Packets.TCP.protocol: tcp = tcp_decoder.decode(packetPayload[ethernet.get_header_size() + ip.get_header_size():]) Sport = tcp.get_th_sport() Dport = tcp.get_th_dport() Data = tcp.get_data_as_string() # Compute the messages message = NetworkMessage(uuid.uuid4(), timestamp, Data.encode("hex"), IPsrc, IPdst, proto, Sport, Dport) messages.append(message) # We ask the confirmation md = gtk.MessageDialog(None, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_QUESTION, gtk.BUTTONS_OK_CANCEL, (_("Are you sure to import the %s selected packets in project %s?") % (str(len(messages)), currentProject.getName()))) # md.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) resp = md.run() md.destroy() if resp == gtk.RESPONSE_OK: self.saveMessagesInProject(self.zob.getCurrentWorkspace(), currentProject, messages) self.dialog.destroy() # We update the gui self.zob.update() #+---------------------------------------------- #| Called when user select a packet for details #+---------------------------------------------- def packet_details(self, treeview): (model, paths) = treeview.get_selection().get_selected_rows() decoder = Decoders.EthDecoder() for path in paths[:1]: iter = model.get_iter(path) if(model.iter_is_valid(iter)): packetID = model.get_value(iter, 0) payload = self.packets[packetID] self.textview.get_buffer().set_text("") self.textview.get_buffer().insert_with_tags_by_name(self.textview.get_buffer().get_start_iter(), str(decoder.decode(payload)), "normalTag") #+---------------------------------------------- #| Called when launching sniffing process #+---------------------------------------------- def launch_sniff(self, button, dev, filter, count, time): button.set_sensitive(False) self.envDeps.captureEnvData() # Retrieve the environmental data (os specific, system specific, etc.) self.packets = [] self.treestore.clear() self.textview.get_buffer().set_text("") aSniffThread = threading.Thread(None, self.sniffingThread, None, (button, dev, filter, count, time), {}) aSniffThread.start() #+---------------------------------------------- #| Thread for sniffing work #+---------------------------------------------- def sniffingThread(self, button, devstore, filter, count, time): modele = devstore.get_model() est_actif = devstore.get_active() dev = "" if est_actif < 0: dev = "" dev = modele[est_actif][0] self.log.info(_("Launching sniff process on dev {0} with : count={1}, timeout={2}, filter=\"{3}\"").format(dev, count.get_text(), time.get_text(), filter.get_text())) sniffer = pcapy.open_live(dev, 1024, False, int(time.get_text())) try: sniffer.setfilter(filter.get_text()) except: self.log.warn(_("The provided filter is not valid (it should respects the BPF format")) button.set_sensitive(True) return sniffer.loop(int(count.get_text()), self.packetHandler) button.set_sensitive(True) def packetHandler(self, header, payload): # Definition of the protocol decoders (impacket) eth_decoder = Decoders.EthDecoder() ip_decoder = Decoders.IPDecoder() udp_decoder = Decoders.UDPDecoder() tcp_decoder = Decoders.TCPDecoder() ethernet = eth_decoder.decode(payload) if ethernet.get_ether_type() == Packets.IP.ethertype: ip = ip_decoder.decode(payload[ethernet.get_header_size():]) if ip.get_ip_p() == Packets.UDP.protocol: udp = udp_decoder.decode(payload[ethernet.get_header_size() + ip.get_header_size():]) if len(udp.get_data_as_string()) > 0: self.treestore.append(None, [len(self.packets), "UDP", ip.get_ip_src(), ip.get_ip_dst(), udp.get_uh_sport(), udp.get_uh_dport(), int(time.time())]) self.packets.append(payload) if ip.get_ip_p() == Packets.TCP.protocol: tcp = tcp_decoder.decode(payload[ethernet.get_header_size() + ip.get_header_size():]) if len(tcp.get_data_as_string()) > 0: self.treestore.append(None, [len(self.packets), "TCP", ip.get_ip_src(), ip.get_ip_dst(), tcp.get_th_sport(), tcp.get_th_dport(), int(time.time())]) self.packets.append(payload) #+---------------------------------------------- #| GETTERS #+---------------------------------------------- def getPanel(self): return self.panel