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 get_name(plugin): """ Gets the information and pois from the selected plugin :param plugin: current selected plugin :return: Mongo cursor with the info from the plugin """ project_db = DBConnection.get_collection("plugin") x = DBConnection.list_collections("plugin") for i in x: if plugin == i: project_info = project_db[i] cursor = project_info.find() return cursor
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 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 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 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 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_()
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 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 get_installed_plugins(): """ Get plugins installed in the database collection 'plugin' :return: list of installed plugins """ plugin_list = [] x = DBConnection.list_collections("plugin") for i in x: plugin_list.append(i) return plugin_list
def get_file(current): """ Get the output file of the selected plugin :param current: string current selected plugin :return: string path of output file of plugin """ plugin_db = DBConnection.get_collection("plugin") coll = plugin_db[current] cursor = coll.find() for y in cursor: out = y["output"] return out
def detailed_poi(self, item): """ This method gets the information of an existing poi in the database and displays it top the detail point of interest edit box. :param item: current selected poi :return: none """ value = DBConnection.search_by_item(item) if value is not None: del value["_id"] y = value self.analysis_tab.poi_content_area_textEdit.setText(format_poi(y))
def update_poi(poi_list, current): """ Updates pois list in the selected plugin :param poi_list: list new pois to add :param current: string current selected plugin :return: None """ plugin_db = DBConnection.get_collection("plugin") my_col = plugin_db[current] query = {"name": current} new_values = {"$set": {"poi": poi_list}} my_col.update_one(query, new_values)
def change_font(self, item): """ This method checks if any poi has a comment then bolds the name of the poi. :param item: item list widget to bold the name :return: item list widget """ new_font = QtGui.QFont() if DBConnection.search_comment_by_item(item): new_font.setBold(True) else: new_font.setBold(False) item.setFont(new_font) return item
def get_output(item, current): """ Get the output of the poi in the current plugin :param item: string name of poi :param current: string selected plugin :return: string output of poi """ plugin_db = DBConnection.get_collection("plugin") current_coll = plugin_db[current] cursor = current_coll.find() for y in cursor: poi = y["poi"]["item"] for ash in poi: if ash["name"] in item: return ash["pythonOutput"]
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 plugin_types(plugin_types, current): """ Filters the pois installed in the current plugin with the string passed :param plugin_types: string with the type of poi :param current: Current selected plugin :return: list of pois that matches the type """ plugin_list = [] plugin_db = DBConnection.get_collection("plugin") current_coll = plugin_db[current] cursor = current_coll.find() for y in cursor: poi = y["poi"]["item"] for ash in poi: if plugin_types == ash["type"]: plugin_list.append(ash["name"]) return plugin_list
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