def item_activated(self): """ This method listens for selecting a plugin to display the plugin formation. :return: none """ if self.plugin_tab.listWidget.count() != 0: plugin_s = self.plugin_tab.listWidget.selectedItems() plugin_name = [item.text().encode("ascii") for item in plugin_s] if plugin_name: try: self.plugin = plugin_name[0].decode() cursor = Plugin.get_name(self.plugin) if cursor: for pl in cursor: self.plugin_tab.DPVPluginName.setText(pl["name"]) self.plugin_tab.DPVPluginDescription.setText( pl["desc"]) self.plugin_tab.DPVDefaultOutputField.setText( pl["output"]) for i in pl["poi"]["item"]: last_text = self.plugin_tab.DVPPointOfInterest.toPlainText( ) new = last_text + i["type"] + " " + i[ "name"] + "\n" self.plugin_tab.DVPPointOfInterest.setText(new) except Exception as e: x = ErrorDialog(self.plugin_tab, str(e), "Error") x.exec_()
def project_selected_changed(self): """ This method listens for a change in the current project and updates the singleton and updates the view. :return: none """ if self.project_tab.listWidget.count() != 0: project = self.project_tab.listWidget.selectedItems() project_name = [item.text().encode("ascii") for item in project] if project_name: self.project_name = str(project_name[0], 'utf-8') try: Singleton.set_project(self.project_name) project_db = DBConnection.get_collection(self.project_name) project_info = project_db["projectInfo"] bin_info = project_db["binaryInfo"] cursor = project_info.find() for db in cursor: self.project_tab.textEdit_2.setPlainText(db['ProjectDescription']) self.project_tab.lineEdit_2.setText(db['ProjectName']) self.project_tab.lineEdit_3.setText(db['BnyFilePath']) Singleton.set_path(db['BnyFilePath']) cursor_bin = bin_info.find() for db in cursor_bin: self.set_binary_prop() self.fill_binary_prop(db) self.selected_project_changed.emit() except Exception as e: msg = ErrorDialog(self.project_tab, str(e), "Error") msg.exec()
def save_project(self): """ This method saves the newly created project into the database. :return: none """ if self.project_tab.lineEdit_3.text() != "": saved = False project_db = DBConnection.get_collection(self.project_name) project_info = project_db["projectInfo"] info = {"ProjectName": self.project_tab.lineEdit_2.text(), "ProjectDescription": self.project_tab.textEdit_2.toPlainText(), "BnyFilePath": self.project_tab.lineEdit_3.text()} insert_info = project_info.insert(info, check_keys=False) bin_info = project_db["binaryInfo"] insert_obj = bin_info.insert(r2_bin_info, check_keys=False) msg = QtWidgets.QMessageBox() msg.setIcon(QtWidgets.QMessageBox.Information) msg.setWindowTitle("Save Project") msg.setText("Project Saved") msg.setStandardButtons(QtWidgets.QMessageBox.Ok) retval = msg.exec_() Singleton.set_path(self.project_tab.lineEdit_3.text()) Singleton.set_project(self.project_name) self.project_tab.textEdit_2.setReadOnly(True) self.delete_save_operations(self.project_creation_finished, [self.project_tab.pushButton_7], [self.project_tab.pushButton_8, self.project_tab.pushButton_10], self.project_tab.listWidget) else: msg = ErrorDialog(self.project_tab, "Please select a binary file", "Error Saving Project") msg.exec_()
def delete_project(self): """ This method gets the selected project and deletes it form the database. :return: none """ if self.project_name != "": button_reply = QtWidgets.QMessageBox.question(self.project_tab, 'PyQt5 message', "Do you like to erase Project %s ?" % self.project_name, QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No) if button_reply == QtWidgets.QMessageBox.Yes: DBConnection.drop_db(self.project_name) self.project_tab.lineEdit_2.setText("") self.project_tab.textEdit_2.setText("") self.project_tab.lineEdit_3.setText("") self.set_binary_prop() self.delete_save_operations(self.project_creation_finished, [self.project_tab.pushButton_7], [self.project_tab.pushButton_8, self.project_tab.pushButton_10], self.project_tab.listWidget) list_items = self.project_tab.listWidget.selectedItems() if not list_items: return for item in list_items: self.project_tab.listWidget.takeItem(self.project_tab.listWidget.row(item)) Singleton.set_project("BEAT") Singleton.set_path("") self.delete_project_signal.emit() self.project_selected_changed() else: msg = ErrorDialog(self.project_tab, "Please select a project", "Error Deleting Project") msg.exec_()
def browse_binary_files(self): """ This method allows the user to add a binary file using a browse window. :return: return """ options = QtWidgets.QFileDialog.Options() options |= QtWidgets.QFileDialog.DontUseNativeDialog file_name, _ = QtWidgets.QFileDialog.getOpenFileName(self.project_tab, "Browse Binary File", "", "Binary Files (*.elf | *.exe | *.out)", options=options) if file_name: QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) try: global r2_bin_info self.project_tab.lineEdit_3.setText(file_name) rlocal = r2Connection.Open(file_name) r2_bin_info = rlocal.cmdj("ij") if r2_bin_info["core"]["format"] == "any": msg = QtWidgets.QMessageBox() msg.setText("Error") return self.fill_binary_prop(r2_bin_info) except Exception as e: x = ErrorDialog(self.project_tab, str(e), "Error") x.exec_() QtWidgets.QApplication.restoreOverrideCursor()
def create_project(self): """ This method creates a project if it does not exit in the database. :return: none """ text, ok_pressed = QtWidgets.QInputDialog.getText(self.project_tab, "Create New Project", "Name of Project:", QtWidgets.QLineEdit.Normal, "") if ok_pressed and text != '': db_names = DBConnection.get_db() if text in db_names: msg = ErrorDialog(self.project_tab,"Project with that name already exists", "Error Creating Project") msg.exec_() return self.project_tab.lineEdit_2.setText(text) self.project_tab.textEdit_2.setText("") self.project_tab.lineEdit_3.setText("") self.project_tab.textEdit_2.setReadOnly(False) self.set_binary_prop() self.project_name = text self.project_tab.listWidget.addItem(text) item = self.project_tab.listWidget.findItems(text, QtCore.Qt.MatchExactly) self.project_tab.listWidget.setCurrentItem(item[0]) self.project_tab.setWindowTitle('Create Project') saved = True self.create_operations(self.project_creation_started, [self.project_tab.pushButton_7], [self.project_tab.pushButton_8, self.project_tab.pushButton_10], self.project_tab.listWidget)
def accept_single(self): if self.lineEdit_2.text() != "": if self.comboBox.currentText() == "String": doc = { "item": [{ "name": self.lineEdit_2.text(), "type": self.comboBox.currentText(), "attributes": {}, "pythonOutput": "" }] } elif self.comboBox.currentText() == "Function": doc = { "item": [{ "name": self.lineEdit_2.text(), "type": self.comboBox.currentText(), "attributes": { "parameters": self.lineEdit_3.text(), "retur": self.lineEdit_4.text() }, "pythonOutput": self.lineEdit_5.text() }] } self.pois = doc self.accept() else: e = ErrorDialog(self, "Name must be filled", "Error") e.exec_()
def delete_plugin(self): """ This method deletes the selected plugin from the database. :return: none """ if self.plugin != "": button_reply = QtWidgets.QMessageBox.question( self.plugin_tab, 'PyQt5 message', "Do you like to erase Plugin %s ?" % self.plugin, QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, QtWidgets.QMessageBox.No) if button_reply == QtWidgets.QMessageBox.Yes: project_db = DBConnection.get_collection("plugin") project_db.drop_collection(self.plugin) self.plugin = "" self.plugin_tab.DPVPluginDescription.setText("") self.plugin_tab.DPVPluginName.setText("") self.plugin_tab.DVPPointOfInterest.setText("") self.plugin_tab.DPVDefaultOutputField.setText("") self.delete_save_operations(self.plugin_creation_finished, [self.plugin_tab.pushButton_7], [self.plugin_tab.ButtonSavePlugin], self.plugin_tab.listWidget) list_items = self.plugin_tab.listWidget.selectedItems() if not list_items: return for item in list_items: self.plugin_tab.listWidget.takeItem( self.plugin_tab.listWidget.row(item)) self.plugin_delete_signal.emit() else: x = ErrorDialog(self.plugin_tab, "Please select a plugin", "Error") x.exec_()
def create_plugin(self): """ This method communicates with the view for creating a new plugin and check if the created plugin already exists. :return: none """ text, ok_pressed = QtWidgets.QInputDialog.getText( self.plugin_tab, "Create New Plugin", "Name of Plugin:", QtWidgets.QLineEdit.Normal, "") if ok_pressed and text != '': db_names = DBConnection.get_collection("plugin") coll = db_names.list_collections() for i in coll: if text in i: x = ErrorDialog(self.plugin_tab, "Plugin with that name already exists", "Error Creating Plugin") x.exec_() return self.plugin_tab.DPVPluginDescription.setText("") self.plugin_tab.DPVPluginName.setText(text) self.plugin_tab.DVPPointOfInterest.setText("") self.plugin_tab.DPVDefaultOutputField.setText("") self.plugin_tab.listWidget.addItem(text) item = self.plugin_tab.listWidget.findItems( text, QtCore.Qt.MatchExactly) self.plugin_tab.listWidget.setCurrentItem(item[0]) self.create_operations(self.plugin_creation_started, [self.plugin_tab.pushButton_7], [self.plugin_tab.ButtonSavePlugin], self.plugin_tab.listWidget)
def stop(self): """ This method kills the running dynamic thread. :return: none """ try: thread.terminate() self.run = 0 self.dynamic_stopped.emit() except: x = ErrorDialog(self.analysis_tab, "Run a dynamic analysis first", "Dynamic analysis Error") x.exec_()
def save_plugin(self): """ This method after creating a new plugin this method communicates with the model to save the changes to the database. :return: none """ plugin_db = DBConnection.get_collection("plugin") plg_cllc = plugin_db[self.plugin_tab.DPVPluginName.text()] info = { "name": self.plugin_tab.DPVPluginName.text(), "desc": self.plugin_tab.DPVPluginDescription.toPlainText(), "poi": { "item": [] }, "output": self.plugin_tab.DPVDefaultOutputField.text() } plg = Plugin.get_name(self.plugin_tab.DPVPluginName.text()) self.delete_save_operations(self.plugin_creation_finished, [self.plugin_tab.pushButton_7], [self.plugin_tab.ButtonSavePlugin], self.plugin_tab.listWidget) if not plg: plg_cllc.insert(info, check_keys=False) x = ErrorDialog(self.plugin_tab, "Plugin Saved", "Save Plugin") x.exec_() self.plugin_signal.emit() else: x = ErrorDialog(self, "Plugin already exists", "Error Plugin") x.exec_() return
def check_schema(self): options = QtWidgets.QFileDialog.Options() options |= QtWidgets.QFileDialog.DontUseNativeDialog file_name, _ = QtWidgets.QFileDialog.getOpenFileName( self, "Browse XML", "", "XML Files (*.xml)", options=options) if file_name: try: schema = xmlschema.XMLSchema('./model/plugin/schema.xsd') schema.validate(file_name) self.lineEdit.setText(file_name) with open(file_name) as fd: doc = xmltodict.parse(fd.read()) self.pois = doc["point_of_interest"] except Exception as e: x = ErrorDialog(self, str(e), "Error") x.exec_()
def poi_comboBox_change(self, text): """ This function listens for a change in the poi window to change the current filter and updates the filtered pois which are stored in the database in the list view :param text: poi's type :return: none """ s = Singleton.get_project() if s == "BEAT": msg = ErrorDialog(self.analysis_tab, "Please select a project first", "Static analysis Error") msg.exec_() return self.analysis_tab.poi_listWidget.clear() project_db = DBConnection.get_collection(s) if text == "Functions": project_info = project_db["functions"] cursor = project_info.find() for db in cursor: item = self.set_item(db["name"], "Functions") item = self.change_font(item) self.analysis_tab.poi_listWidget.addItem(item) elif text == "Strings": project_info = project_db["string"] cursor = project_info.find() for db in cursor: text = db["string"] item = self.set_item(text, "Strings") item = self.change_font(item) self.analysis_tab.poi_listWidget.addItem(item) elif text == "All": project_info = project_db["functions"] cursor = project_info.find() for db in cursor: item = self.set_item(db["name"], "Functions") item = self.change_font(item) self.analysis_tab.poi_listWidget.addItem(item) project_info = project_db["string"] cursor = project_info.find() for db in cursor: text = db["string"] item = self.set_item(text, "Strings") item = self.change_font(item) self.analysis_tab.poi_listWidget.addItem(item)
def dynamic(self): """ This method asks the user for parameters, creates a list with the selected pois and stats dynamic analysis thread with the list of pois and parameters as arguments. :return: """ if self.analysis_tab.poi_listWidget.count() == 0: x = ErrorDialog(self.analysis_tab, "Please run Static analysis first", "Error in DYnamic analysis") x.exec_() return global input input, ok_pressed = QtWidgets.QInputDialog.getText(self.analysis_tab, "Dynamic analysis", "Args to pass:"******"") if ok_pressed: self.run += 1 pois_checked = [] r2 = model.analysis.StaticAnalysis.static_all(Singleton.get_path()) self.terminal('r2 > \n') self.terminal(r2.cmd("doo %s" % input)) for i in range(self.analysis_tab.poi_listWidget.count()): item = self.analysis_tab.poi_listWidget.item(i) if item.checkState() == QtCore.Qt.Checked: if item.toolTip() == "Functions": value = DBConnection.search_by_item(item) poi = {"name": item.text(), "from": value["from"], "type": item.toolTip(), "rtnPara": [], "rtnFnc": ""} pois_checked.append(poi) sort = sorted(pois_checked, key=lambda i: i["from"]) global thread try: self.run = 1 self.dynamic_started.emit() thread = model.analysis.DynamicThread.DynamicThread(rlocal=r2, pois=sort) thread.textSignal.connect(lambda x: self.terminal(x)) thread.listSignal.connect(lambda x: self.return_funcitions(x)) thread.errorSignal.connect(lambda x: self.error_thread(x)) thread.start() except Exception as e: print(e)
def input_terminal(self, text): """ This method checks if the dynamic analysis thread is running if it's being run it passes the text as an input pipe.Otherwise passes the text as a command for Radare. :param text: text for argument :return: none """ if self.run == 0: if Singleton.get_project() != "BEAT": try: r2 = model.analysis.StaticAnalysis.static_all(Singleton.get_path()) self.terminal(text + ' >\n') self.terminal(r2.cmd(text)) except Exception as e: x = ErrorDialog(self.analysis_tab, str(e), "Error") x.exec_() self.analysis_tab.terminal_window_lineEdit.setText("") else: x = ErrorDialog(self.analysis_tab, "First select a project", "Error") x.exec_() elif self.run == 1: thread.input(text) self.analysis_tab.terminal_window_lineEdit.clear()
def static(self): """ This method listens to the click of the static analysis button and connects with the model to preform static analysis.This method also saves into the database depending on the type. :return: none """ s = Singleton.get_project() if s == "BEAT": x = ErrorDialog(self.analysis_tab, "Please select a project", "Static analysis Error") x.exec_() return if self.analysis_tab.plugin_comboBox.count() == 0: x = ErrorDialog(self.analysis_tab, "Please install a plugin", "Static analysis Error") x.exec_() return QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) self.analysis_tab.poi_listWidget.clear() print(Singleton.get_path()) rlocal = model.analysis.StaticAnalysis.static_all(Singleton.get_path()) try: if self.analysis_tab.poi_comboBox.currentText() == "All": strings = model.analysis.StaticAnalysis.static_strings(rlocal, self.analysis_tab.plugin_comboBox.currentText()) for st in strings: item = self.set_item(st, "Strings") item = self.change_font(item) self.analysis_tab.poi_listWidget.addItem(item) functions = model.analysis.StaticAnalysis.static_functions(rlocal, self.analysis_tab.plugin_comboBox.currentText()) for fc in functions: item = self.set_item(fc, "Functions") item = self.change_font(item) self.analysis_tab.poi_listWidget.addItem(item) elif self.analysis_tab.poi_comboBox.currentText() == "Functions": functions = model.analysis.StaticAnalysis.static_functions(rlocal, self.analysis_tab.plugin_comboBox.currentText()) for fc in functions: item = self.set_item(fc, "Functions") item = self.change_font(item) self.analysis_tab.poi_listWidget.addItem(item) elif self.analysis_tab.poi_comboBox.currentText() == "Strings": strings = model.analysis.StaticAnalysis.static_strings(rlocal, self.analysis_tab.plugin_comboBox.currentText()) for st in strings: item = self.set_item(st, "Strings") item = self.change_font(item) self.analysis_tab.poi_listWidget.addItem(item) except Exception as e: x = ErrorDialog(self.analysis_tab, str(e), "Static analysis Error") x.exec_() rlocal.quit() QtWidgets.QApplication.restoreOverrideCursor()
def error_thread(self, text): msg = ErrorDialog(self.analysis_tab,text,"Error in Dynamic analysis") msg.exec_()
def open_output(self): """ Grabs the output file from the plugin and gets the selcted pois and runs the file with the pois as arguments. :return: none """ try: plugin = Plugin.get_file(self.analysis_tab.plugin_comboBox.currentText()) cmd = ["python3", plugin] pois = [] for i in range(self.analysis_tab.poi_listWidget.count()): item = self.analysis_tab.poi_listWidget.item(i) if item.checkState() == QtCore.Qt.Checked: value = DBConnection.search_by_item(item) out = Plugin.get_output(item.text(), self.analysis_tab.plugin_comboBox.currentText()) poi = {"name": item.text(), "from": value["from"], "out": out} pois.append(poi) sort = sorted(pois, key=lambda i: i["from"]) for s in sort: cmd.append(str(s)) subprocess.check_call(cmd) x = ErrorDialog(self.analysis_tab, "Finished creating output", "Output") x.exec_() except subprocess.CalledProcessError as e: text = "" if e.returncode == 1: text = f"Error executing {plugin} file" elif e.returncode == 2: text = f"{plugin} file not found" x = ErrorDialog(self.analysis_tab, text, "Error in Output") x.exec_() except Exception as e: x = ErrorDialog(self.analysis_tab, str(e), "Error in Output") x.exec_()