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 static_functions(rlocal, cplugin): """ analysis all the functions in the binary and filters with the selected plugin and adds them to the database :param rlocal: R2Connection of the binary file :param cplugin: string current selected plugin :return: List of dict with filtered functions """ items = [] s = Singleton.get_project() project_db = DBConnection.get_collection(s) #if project_db["functions"]: # project_db.drop_collection("functions") func_db = project_db["functions"] func_all = rlocal.cmdj("aflj") func_plg = Plugin.plugin_types("Function", cplugin) for fc in func_all: if fc["name"] in func_plg: function = rlocal.cmdj("axtj %s" % fc["name"]) tmp = fc["name"] for f in function: fc["name"] = tmp + " " + hex(f["from"]) items.append(fc["name"]) fc["comment"] = "" fc["runs"] = [] fc["from"] = hex(f["from"]) if "_id" in fc: del fc["_id"] if func_db.find({"name": fc["name"]}).count() == 0: func_db.insert_one(fc) return items
def open_comment(self): """ This method opens the comment pop-up to add a comment/ or edit an exiting comment.Afterwards it updates the information to the detailed point of interest in the database. :return: none """ item = self.analysis_tab.poi_listWidget.currentItem() value = DBConnection.search_by_item(item) project_db = DBConnection.get_collection(Singleton.get_project()) if item.toolTip() == "Functions": db_info = project_db["functions"] elif item.toolTip() == "Strings": db_info = project_db["string"] if value is not None: id = value["_id"] cmt = value["comment"] if cmt is None: cmt = "" pop_up = CommentDialog(self.analysis_tab, cmt) comm = pop_up.exec_() index = {"_id": id} new_value = {"$set": {"comment": comm}} db_info.update_one(index, new_value) self.detailed_poi(item) new_font = QtGui.QFont() new_font.setBold(True) item.setFont(new_font)
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 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 return_funcitions(self, text): """ This method receives the information from the breakpoint and stores the information into the database. :param text: information received :return: none """ value = DBConnection.search_by_name(text["name"], "Functions") project_db = DBConnection.get_collection(Singleton.get_project()) db_info = project_db["functions"] if value is not None: id = value["_id"] index = {"_id": id} runs = value["runs"] run = {"name":input,"rtnPara": text["rtnPara"], "rtnFnc": text["rtnFnc"]} runs.append(run) new_value = {"$set": {"runs": runs}} db_info.update_one(index, new_value)
def search_by_name(name, type): """ Gets all the information of poi from the database :param name: String name of poi :param type: String type of the poi :return: Dict with all poi info """ s = Singleton.get_project() project_db = get_collection(s) value = None if type == "Functions": project_info = project_db["functions"] cursor = project_info.find_one({"name": name}) if cursor is not None: value = {"_id": cursor["_id"], 'name': cursor["name"], 'signature': cursor["signature"], 'varaddress': hex(cursor["offset"]), 'from': cursor["from"], 'comment': cursor["comment"], 'runs':cursor["runs"]} return value
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 static_strings(rlocal, cplugin): """ analysis all the strings in the binary and filters with nthe selected plugin and adds them to the database :param rlocal: R2Connection of the binary file :param cplugin: string current selected plugin :return: List of dict with filtered strings """ items = [] s = Singleton.get_project() project_db = DBConnection.get_collection(s) # Strings strings = rlocal.cmdj("izj") str_plg = Plugin.plugin_types("String", cplugin) #if project_db["string"]: # project_db.drop_collection("string") str_db = project_db["string"] for string in strings: text = string["string"] text_decoded = base64.b64decode(text) for i in str_plg: if i.upper() in text_decoded.decode().upper(): x = rlocal.cmdj("axtj %s" % string["vaddr"]) tmp = text_decoded.decode() for str in x: string["string"] = tmp + " " + hex(str["from"]) items.append(string["string"]) string["from"] = hex(str["from"]) string["comment"] = "" if "_id" in string: del string["_id"] if str_db.find({"string": string["string"]}).count() == 0: str_db.insert_one(string) break return items
def search_by_item(item): """ Gets all the information of a poi from a listwidget item :param item: ListwidgetItem selected poi :return: dict with pois info """ if item is not None: s = Singleton.get_project() project_db = get_collection(s) value = None if item.toolTip() == "Functions": project_info = project_db["functions"] cursor = project_info.find_one({"name": item.text()}) if cursor is not None: value = {"_id":cursor["_id"],'name': cursor["name"], 'signature': cursor["signature"], 'varaddress': hex(cursor["offset"]), 'from': cursor["from"], 'comment': cursor["comment"],"runs": cursor["runs"]} elif item.toolTip() == "Strings": project_info = project_db["string"] cursor = project_info.find_one({"string": item.text()}) if cursor is not None: value = {"_id":cursor["_id"],'string': cursor["string"], 'varaddress': hex(cursor["vaddr"]), 'from': cursor["from"], 'comment': cursor["comment"]} return value return None
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 set_running(self): self.main_window.setWindowTitle("BEAT | Running " + Singleton.get_project())
def set_project_name(self): self.main_window.setWindowTitle("BEAT | " + Singleton.get_project())
def setup_ui(self, main_window): """Sets up the ui for the main window and establishes the ui_implementation and their connections for each tab""" self.main_window = main_window self.main_window.setObjectName("BEAT") self.main_window.resize(804, 615) self.main_window.setFixedSize(self.main_window.width(), self.main_window.height()) self.setWindowIcon(QtGui.QIcon('./resources/beat.png')) self.main_window.setWindowTitle("BEAT") s = Singleton() s.set_project("BEAT") self.centralwidget = QtWidgets.QWidget(self.main_window) self.centralwidget.setObjectName("centralwidget") self.tabWidget = QtWidgets.QTabWidget(self.centralwidget) self.tabWidget.setGeometry(QtCore.QRect(5, 5, 794, 605)) self.tabWidget.setObjectName("tabWidget") self.ProjectTab = Tab1.Tab1(self) self.tabWidget.addTab(self.ProjectTab, "") self.analysisTab = Tab2.Tab2(self) self.tabWidget.addTab(self.analysisTab, "") self.pluginTab = Tab3.Tab3(self) self.tabWidget.addTab(self.pluginTab, "") self.pointsOfInterestTab = Tab4.Tab4(self) self.tabWidget.addTab(self.pointsOfInterestTab, "") self.documentationTab = Tab5.Tab5(self) self.tabWidget.addTab(self.documentationTab, "") self.project_implementation = ProjectTabImplementation.ProjectTabImplementation(self.ProjectTab) self.project_implementation.establish_connections() self.project_implementation.establish_calls() self.analysis_implementation = AnalysisTabImplementation.AnalysisTabImplementation(self.analysisTab) self.analysis_implementation.establish_connections() self.analysis_implementation.establish_calls() self.plugin_implementation = PluginTabImplementation.PluginTabImplementation(self.pluginTab) self.plugin_implementation.establish_connections() self.plugin_implementation.establish_calls() self.poi_implementation = POITabImplementation.POITabImplementation(self.pointsOfInterestTab) self.poi_implementation.establish_connections() self.poi_implementation.establish_calls() self.doc_implementation = DocumentationTabImplementation.DocumentationTabImplementation(self.documentationTab) self.doc_implementation.establish_connections() self.doc_implementation.establish_calls() self.project_implementation.selected_project_changed.connect( lambda: self.analysis_implementation.poi_comboBox_change("All")) self.project_implementation.selected_project_changed.connect(lambda: self.set_project_name()) self.project_implementation.selected_project_changed.connect( lambda: self.analysisTab.terminal_output_textEdit.clear()) self.project_implementation.project_creation_started.connect(lambda: self.disable_tabs()) self.project_implementation.project_creation_finished.connect(lambda: self.enable_tabs()) self.project_implementation.delete_project_signal.connect(lambda: self.analysisTab.poi_listWidget.clear()) self.project_implementation.delete_project_signal.connect(lambda: self.set_clear_name()) self.project_implementation.delete_project_signal.connect( lambda: self.analysisTab.poi_content_area_textEdit.clear()) self.analysis_implementation.dynamic_started.connect(lambda: self.set_running()) self.analysis_implementation.dynamic_stopped.connect(lambda: self.set_project_name()) self.analysis_implementation.dynamic_started.connect(lambda: self.disable_tabs()) self.analysis_implementation.dynamic_stopped.connect(lambda: self.enable_tabs()) self.plugin_implementation.plugin_signal.connect(self.analysis_implementation.set_plugins) self.plugin_implementation.plugin_signal.connect(self.poi_implementation.set_plugins) self.plugin_implementation.plugin_creation_started.connect(lambda: self.disable_tabs()) self.plugin_implementation.plugin_creation_finished.connect(lambda: self.enable_tabs()) self.plugin_implementation.plugin_delete_signal.connect(self.poi_implementation.set_plugins) self.plugin_implementation.plugin_delete_signal.connect( lambda: self.poi_implementation.fill_poi(self.pointsOfInterestTab.comboBox_2.currentText())) self.plugin_implementation.plugin_delete_signal.connect(self.pointsOfInterestTab.textEdit.clear) self.plugin_implementation.plugin_delete_signal.connect(self.analysis_implementation.set_plugins) self.poi_implementation.add_poi_signal.connect(self.plugin_implementation.item_activated) self.main_window.setCentralWidget(self.centralwidget) self.retranslate_ui() self.tabWidget.setCurrentIndex(0) QtCore.QMetaObject.connectSlotsByName(main_window)