def Show(self): """ Creates the form and brings it to the front. """ try: input_md5 = idc.retrieve_input_file_md5() except: input_md5 = idc.GetInputMD5() if input_md5 is None: return else: name = "{}".format(config['name']) try: options = PluginForm.WCLS_CLOSE_LATER |\ PluginForm.WCLS_SAVE |\ PluginForm.WOPN_RESTORE except: options = PluginForm.FORM_CLOSE_LATER |\ PluginForm.FORM_SAVE |\ PluginForm.FORM_RESTORE return PluginForm.Show(self, name, options=options)
def __init__(self, **kwargs): super(AddFileDialog, self).__init__(title="Add File", **kwargs) name = idc.GetInputFile() md5hash = idc.GetInputMD5() layout = QtWidgets.QGridLayout() layout.addWidget(QtWidgets.QLabel("Project:"), 0, 0) layout.addWidget(QtWidgets.QLabel("File name:"), 1, 0) layout.addWidget(QtWidgets.QLabel("Description:"), 2, 0) layout.addWidget(QtWidgets.QLabel("MD5 hash:"), 3, 0) self.project_cbb = widgets.QItemSelect('projects') layout.addWidget(self.project_cbb, 0, 1) self.name_txt = QtWidgets.QLineEdit() self.name_txt.setText(name) layout.addWidget(self.name_txt, 1, 1) self.description_txt = QtWidgets.QTextEdit() layout.addWidget(self.description_txt, 2, 1) layout.addWidget(QtWidgets.QLabel(md5hash), 3, 1) self.base_layout.addLayout(layout) self.shareidbCkb = QtWidgets.QCheckBox("Share IDB (let others without " "the idb to participate)") self.base_layout.addWidget(self.shareidbCkb) self.bottom_layout(ok_text="&Add")
def GetInputFileMD5(): """ Return the MD5 hash of the input binary file @return: MD5 string or None on error """ return idc.GetInputMD5()
def req_modcheck(self, hash): md5, pdb = hash.get('md5'), hash.get('pdb') remote = None if md5: print("[*] modcheck idb (md5)") local = idc.GetInputMD5() remote = (''.join(str(md5).encode("ascii").split())).upper() elif pdb: print("[*] modcheck idb (pdb guid)") msg = base64.b64decode(pdb) local = DbgDirHlpr.read_rsds_codeview() remote = DbgDirHlpr.parse_itoldyouso_output(msg) print(" -> remote: <%s>" % remote) print(" -> local : <%s>" % local) if remote == "0": res = "[!] warning, no Debug Directory" elif local == remote: res = "[+] module successfully matched" else: res = "[!] warning, modules mismatch" print res self.notice_broker("cmd", "\"cmd\":\"%s\"" % res) return
def data(self): return { 'project': self.project_cbb.currentData(), 'name': self.name_txt.text(), 'md5hash': idc.GetInputMD5(), 'description': self.description_txt.toPlainText(), 'shareidb': self.shareidbCkb.isChecked() }
def init(self): self.hook = None if idc.GetInputMD5() != input_md5 or idaapi.ph_get_id( ) != idaapi.PLFM_386: return idaapi.PLUGIN_SKIP self.hook = deobX86Hook() self.hook.hook() return idaapi.PLUGIN_KEEP
def Show(self): if idc.GetInputMD5() == None: return else: return PluginForm.Show( self, NAME, options=(PluginForm.FORM_CLOSE_LATER | PluginForm.FORM_RESTORE | PluginForm.FORM_SAVE))
def get_connection_filename(self): binkit_profile = os.path.join(os.environ['USERPROFILE'], '.binkit') if not os.path.isdir(binkit_profile): try: os.makedirs(binkit_profile) except: traceback.print_exc() md5 = idc.GetInputMD5().lower() self.connection_filename = os.path.join( binkit_profile, "%s-%d.port" % (md5, os.getpid()))
def upload(self, ctx): start = time.time() func_count = 0 bb_count = 0 call_count = 0 target = idaapi.get_root_filename() hash = idc.GetInputMD5() tx = self.neo.cypher.begin() insert_binary = "MERGE (n:Binary {name:{N},hash:{H}}) RETURN n" insert_func = "MERGE (n:Function {name:{N},start:{S},flags:{F}}) RETURN n" insert_bb = "MERGE (n:BasicBlock {start:{S}, end:{E}}) RETURN n" create_relationship = "MATCH (u:Function {name:{N}}), (r:Function {start:{S}}) CREATE (u)-[:CALLS]->(r)" create_contains = "MATCH (u:BasicBlock {start:{S}}), (f:Function {name:{N}}) CREATE (f)-[:CONTAINS]->(u)" create_inside = "MATCH (u:Function {start:{S}}), (b:Binary {hash:{H}}) CREATE (f)-[:INSIDE]->(b)" self.neo.cypher.execute(insert_binary, {"N": target, "H": hash}) self.neo.cypher.execute("CREATE INDEX ON :Function(start)") #self.neo.cypher.execute("CREATE INDEX ON :Function(name)") self.neo.cypher.execute("CREATE INDEX ON :BasicBlock(start)") for f in Functions(): tx.append(create_inside, {"S": f, "H": hash}) callee_name = GetFunctionName(f) flags = get_flags(f) type = GetType(f) if type: return_type = type.split()[0] print type end_return = type.find(' ') start_args = type.find('(') print type[end_return + 1:start_args] print type[start_args + 1:].split(',') else: print GuessType(f) tx.append(insert_func, {"N": callee_name, "S": f, "F": flags}) func_count += 1 fc = idaapi.FlowChart(idaapi.get_func(f)) for block in fc: tx.append(insert_bb, {"S": block.startEA, "E": block.endEA}) tx.append(create_contains, {"S": block.startEA, "N": f}) bb_count += 1 tx.process() tx.commit() tx = self.neo.cypher.begin() for f in Functions(): for xref in CodeRefsTo(f, 0): caller_name = GetFunctionName(xref) if caller_name != '': tx.append(create_relationship, {"N": caller_name, "S": f}) call_count += 1 tx.process() tx.commit() print "Upload ran in: " + str(time.time() - start) print "Uploaded " + str(func_count) + " functions, " + str( call_count) + " function calls and " + str( bb_count) + " basic blocks."
def PopulateForm(self): layout = QVBoxLayout() label = QtWidgets.QLabel() label.setText("Proposed function names for sample %s" % idc.GetInputMD5()) self.funcinfos = SkelFunctionInfosList(self.settings_filename) layout.addWidget(label) layout.addWidget(self.funcinfos) self.setLayout(layout)
def __init__(self, real_dir): super(Plugin, self).__init__() self.tools = include.helper.Tools(self) self.config_main = ConfigParser.ConfigParser() self.config_theme = ConfigParser.ConfigParser() self._bin_md5 = idc.GetInputMD5() self._bin_name = re.sub(r'\.[^.]*$', '', idc.GetInputFile()) self._read_config(real_dir) self.gui = None self.parser = None
def Show(self): """ Called when the plugin form is visible """ if idc.GetInputMD5() == None: return else: return PluginForm.Show( self, NAME, options=(PluginForm.FORM_CLOSE_LATER | PluginForm.FORM_RESTORE | PluginForm.FORM_SAVE))
def from_json(json_message): message = json.loads(json_message) if message is None or len(message) == 0 or type(message) != dict: return message = psida_common.convert_struct_to_utf8(message) if 'user' not in message or message['user'] == CONFIGURATION[USER]: # don't receive your own updates return if 'project' not in message or message['project'] != idc.GetInputMD5(): # don't receive updates for other projects return return TYPE_TO_CLASS[message['update_type']](**message)
def __init__(self, filename): self.match_results = [] if os.path.isfile(filename): self.functions_matcher = functions.Matcher(filename=filename) md5 = idc.GetInputMD5().lower() if md5 == self.functions_matcher.get_md5('source'): self.self_name = 'source' self.peer_name = 'target' elif md5 == self.functions_matcher.get_md5('target'): self.self_name = 'target' self.peer_name = 'source' else: self.self_name = 'source' self.peer_name = 'target'
def get_sample_id(self): """ Query the server for the sample ID """ endpoint = "/api/1.0/samples/" endpoint += lower(idc.GetInputMD5()) endpoint += "/" try: data = self.poli_get(endpoint) if data["sample_id"] is not None: return data["sample_id"] else: return False except BaseException: # 404? return False
def __init__(self, **kwargs): super(AddFileDialog, self).__init__(title="Add File", **kwargs) name = idc.GetInputFile() md5hash = idc.GetInputMD5() gridLyt = QtWidgets.QGridLayout() layout = QtWidgets.QVBoxLayout() gridLyt.addWidget(QtWidgets.QLabel("File name:"), 0, 0) gridLyt.addWidget(QtWidgets.QLabel("Description:"), 1, 0) gridLyt.addWidget(QtWidgets.QLabel("MD5 hash:"), 2, 0) self.nameTxt = QtWidgets.QLineEdit() self.nameTxt.setText(name) gridLyt.addWidget(self.nameTxt, 0, 1) self.descriptionTxt = QtWidgets.QTextEdit() gridLyt.addWidget(self.descriptionTxt, 1, 1) gridLyt.addWidget(QtWidgets.QLabel(md5hash), 2, 1) layout.addLayout(gridLyt) self.shareidbCkb = QtWidgets.QCheckBox("Share IDB (let others without " "the idb to participate)") layout.addWidget(self.shareidbCkb) self.statusLbl = QtWidgets.QLabel() layout.addWidget(self.statusLbl) addBtn = QtWidgets.QPushButton("&Add") addBtn.setDefault(True) cancelBtn = QtWidgets.QPushButton("&Cancel") SizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) addBtn.setSizePolicy(SizePolicy) cancelBtn.setSizePolicy(SizePolicy) buttonLyt = QtWidgets.QHBoxLayout() buttonLyt.addWidget(addBtn) buttonLyt.addWidget(cancelBtn) layout.addLayout(buttonLyt) self.setLayout(layout) addBtn.clicked.connect(self.submit) cancelBtn.clicked.connect(self.reject)
def __init__(self, real_dir): super(Plugin, self).__init__() self.tools = include.helper.Tools(self) self.config_main = ConfigParser.ConfigParser() self.config_theme = ConfigParser.ConfigParser() self._bin_md5 = idc.GetInputMD5() self._bin_name = re.sub(r'\.[^.]*$', '', idc.GetInputFile()) self.imports = self._get_imported_names() self.tmp_items = [] self._read_config(real_dir) self.banned_functions = \ self.config_main.get('etc', 'banned_functions').split(',') self.gui = None self.parser = None
def PopulateForm(self): layout = QVBoxLayout() label = QtWidgets.QLabel() label.setText("Notes about sample %s" % idc.GetInputMD5()) self.editor = QtWidgets.QTextEdit() self.editor.setFontFamily(self.skel_settings.notepad_font_name) self.editor.setFontPointSize(self.skel_settings.notepad_font_size) text = self.skel_conn.get_abstract() self.editor.setPlainText(text) # editor.setAutoFormatting(QtWidgets.QTextEdit.AutoAll) self.editor.textChanged.connect(self._onTextChange) layout.addWidget(label) layout.addWidget(self.editor) self.setLayout(layout)
def __init__(self, **kwargs): self.address = None self.data = None self.update_type = None self.user = None self.project = None self.data_at_address = None if 'user' not in kwargs: self.user = CONFIGURATION[USER] if 'project' not in kwargs: self.project = idc.GetInputMD5() for attribute_name in self.ATTRIBUTES: if self.__getattribute__(attribute_name) is None: if attribute_name not in kwargs: raise Exception( "ERROR - Ops - Required attribute name %s does not appear in arguments" % attribute_name) self.__setattr__(attribute_name, kwargs[attribute_name])
def start_binkit_server(connection_filename): port = 18861 while 1: try: t = ThreadedServer(BinKitService(), port = port, protocol_config = { 'allow_public_attrs': True, }) print('Listening on %d\n' % port) md5 = idc.GetInputMD5().lower() try: with open(connection_filename, "w") as fd: json.dump({'port': port, 'md5': md5, 'root_fileanem': idaapi.get_root_filename(), 'input_filename': idaapi.get_input_file_path()}, fd) except: traceback.print_exc() t.start() break except: port += 1 traceback.print_exc()
def __init__(self): super(Plugin, self).__init__() self.tools = hrdev_plugin.include.helper.Tools(self) self.config_main = ConfigParser.ConfigParser() self.config_theme = ConfigParser.ConfigParser() self._bin_md5 = idc.GetInputMD5() self._bin_name = re.sub(r'\.[^.]*$', '', idc.GetInputFile()) self.imports = self._get_imported_names() self.tmp_items = [] real_dir = os.path.realpath(__file__).split('\\') real_dir.pop() real_dir = os.path.sep.join(real_dir) self._read_config(real_dir) self.banned_functions = \ self.config_main.get('etc', 'banned_functions').split(',') self.gui = None self.parser = None
def pickle(destination_file=None, functions_only=False): """ Stores some of the information in the IDB in the given file in pickle format - a dictionary of: - MD5 of binary input file - segment names and ranges - function and address names - comments """ if destination_file is None: destination_file = QtWidgets.QFileDialog.getSaveFileName()[0] if destination_file is None: print "User canceled pickling" return False destination_file = os.path.abspath(destination_file) print "Saving pickle file to: {}".format(destination_file) print "Started pickling at %s" % (time.ctime()) idb_data = { INPUT_FILE_MD5_FIELD: idc.GetInputMD5(), SEGMENTS: psida_common.get_segments(), } if functions_only: idb_data[NAMES_FIELD] = get_function_names() idb_data[COMMENTS_FIELD] = get_function_comments() else: idb_data[NAMES_FIELD] = get_names() idb_data[COMMENTS_FIELD] = get_all_comments() idb_data[STRUCTURES_FIELD] = get_all_structures() # pickle the data with open(destination_file, 'wb') as f: cPickle.dump(idb_data, f, 2) print "Pickling complete at %s" % (time.ctime()) print "Pickle File: {}".format(destination_file)
def submit(self): name = self.nameTxt.text() md5hash = idc.GetInputMD5() description = self.descriptionTxt.toPlainText() shareidb = self.shareidbCkb.isChecked() data = { 'name': name, 'md5hash': md5hash, 'description': description, 'instances': [] } if shareidb: # TODO: uploadfile pass self.response = network.query("POST", "collab/files/", params=data, json=True) self.accept()
def find_input_file(): """ Description: Check whether or not IDA knows where the original file used to create the IDB is. If IDA doesn't know, check the IDA's directory for the file. Output: Returns True if the input file was located, False if it was not. """ global INPUT_FILE_PATH ida_path = INPUT_FILE_PATH if not os.path.exists(ida_path): # If IDA does not know, check if the (correct) file is sitting next to the IDB. local_path = os.path.join(idautils.GetIdbDir(), idc.GetInputFile()) if os.path.exists(local_path) and \ hashlib.md5(open(local_path, 'rb').read()).hexdigest().upper() == idc.GetInputMD5(): INPUT_FILE_PATH = local_path append_debug('Guessed the input file path: ' + INPUT_FILE_PATH) append_debug('IDA thought it was: ' + ida_path) return True else: return False else: return True
def get_input_file_hash(): return idc.GetInputMD5()
def unpickle(source_file=None, overwrite=False, ignore_segment_change=False, ignore_md5_mismatch=False, visual_merge=True): """ Loads information from the given pickled file. """ if source_file is None: source_file = QtWidgets.QFileDialog.getOpenFileName()[0] hooks_enabled = idb_push.g_hooks_enabled try: print "Started unpickling at %s" % (time.ctime()) idb_push.g_hooks_enabled = False with open(source_file, 'rb') as f: idb_data = cPickle.load(f) # verify MD5 if idb_data[INPUT_FILE_MD5_FIELD] != idc.GetInputMD5( ) and not ignore_md5_mismatch: print "MD5 mismatch - unpickled file for %s but working on %s" % ( idb_data[INPUT_FILE_MD5_FIELD], idc.GetInputMD5()) return # check for segment change if not ignore_segment_change: # using iteritems since iterating on a dictionary returns only the dictionary keys if psida_common.get_segments() != idb_data[SEGMENTS]: if 1 != idc.AskYN( 0, SEGMENT_WARNING % (format_segments(idb_data[SEGMENTS]), format_segments(psida_common.get_segments()))): # user replied No or Cancel return # apply idb_data (unless overwrite==True, in which case # you just overwrite everything) if visual_merge and not overwrite: # apply non-conflicting updates name_conflicts = {} comment_conflicts = {} structure_conflicts = {} set_names(idb_data[NAMES_FIELD], overwrite, name_conflicts) set_all_comments(idb_data[COMMENTS_FIELD], overwrite, comment_conflicts) set_all_structures(idb_data[STRUCTURES_FIELD], overwrite, structure_conflicts) conflicts = { NAMES_FIELD: name_conflicts, COMMENTS_FIELD: comment_conflicts, STRUCTURES_FIELD: structure_conflicts } if len(name_conflicts) + len(comment_conflicts) + len( structure_conflicts) == 0: # no conflicts need solving print "Unpickling complete at %s" % (time.ctime()) return global g_form if g_form is not None: g_form.Close(idaapi.PluginForm.FORM_SAVE) g_form = IDBMergeForm() g_form.Show("IDB MERGE") populate_form_with_items(make_items(conflicts)) else: set_names(idb_data[NAMES_FIELD], overwrite) set_all_comments(idb_data[COMMENTS_FIELD], overwrite) idc.Refresh() idc.RefreshLists() print "Unpickling complete at %s" % (time.ctime()) except: traceback.print_exc() raise finally: idb_push.g_hooks_enabled = hooks_enabled
def get_md5(self): return idc.GetInputMD5().lower()
def getMD5OfInputFile(self): """Returns the MD5 of the file currently being analyzed.""" return idc.GetInputMD5()