###################################################### # Author: Andrea Fioraldi <andreafioraldi@gmail.com> # # License: BSD 2-Clause # ###################################################### from idaapi import PluginForm from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtCore import Qt from ui import * from angrdbg import * import angr import claripy import idaapi import idc import idautils import glob import sip import pickle import os import manage class IDAngrCtx(object): def __init__(self): self.find = [] self.avoid = [] self.find_lambda = "def find_cond(state):\n\tsol = state.solver.eval\n\tfor addr in finds:\n\t\tif sol(state.regs.pc) == addr: return True\n\treturn False" self.avoid_lambda = "def avoid_cond(state):\n\tsol = state.solver.eval\n\tfor addr in avoids:\n\t\tif sol(state.regs.pc) == addr: return True\n\treturn False" self.regs = [] self.simregs = [] self.simmem = [] self.constraints = {} #{ item: (code string, lambda) } self.stateman = None self.foundstate = None self.simman = None _idangr_ctx = IDAngrCtx() def save_ctx(filename): global _idangr_ctx with open(filename, "wb") as fh: pickle.dump(_idangr_ctx, fh) def load_ctx(filename): global _idangr_ctx with open(filename, "rb") as fh: _idangr_ctx = pickle.load(fh) class IDAngrTextViewerForm(QtWidgets.QDialog): def __init__(self, text, title): QtWidgets.QDialog.__init__(self) self.text = text self.ui = Ui_IDAngrTextViewer() self.ui.setupUi(self) if title: self.setWindowTitle(title) self.ui.plainTextEdit.setPlainText(str(text)) self.ui.plainBox.toggled.connect(self.plain_toggled) self.ui.hexBox.toggled.connect(self.hex_toggled) self.ui.pyBox.toggled.connect(self.py_toggled) def plain_toggled(self, enabled): if enabled: self.ui.plainTextEdit.setPlainText(str(self.text)) def hex_toggled(self, enabled): if enabled: self.ui.plainTextEdit.setPlainText(str(self.text).encode("hex")) def py_toggled(self, enabled): if self.ui.pyBox.isChecked(): self.ui.plainTextEdit.setPlainText(repr(self.text)) @staticmethod def show_text(text, title=None): frm = IDAngrTextViewerForm(text, title) frm.exec_() class IDAngrAddMemDialog(QtWidgets.QDialog): def __init__(self): QtWidgets.QDialog.__init__(self) self.ui = Ui_IDAngrAddMem() self.ui.setupUi(self) self.ui.lenTextEdit.setText(str(load_project().arch.bits / 8)) def set_addr(self, addr): if type(addr) == int or type(addr) == long: addr = "0x%x" % addr self.ui.addrTextEdit.setText(addr) @staticmethod def get_mem(addr): dialog = IDAngrAddMemDialog() dialog.set_addr(addr) r = dialog.exec_() if r == QtWidgets.QDialog.Accepted: addr = dialog.ui.addrTextEdit.displayText() try: addr = int(addr, 16) except: QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, 'Error', "Address not in hex format").exec_() return None length = dialog.ui.lenTextEdit.displayText() try: length = int(length) except: QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, 'Error', "Length not in dec format").exec_() return None return (addr, length) return None class IDAngrSavedsDialog(QtWidgets.QDialog): def __init__(self, folder, title): QtWidgets.QDialog.__init__(self) self.ui = Ui_IDAngrSavedsDialog() self.ui.setupUi(self) self.setWindowTitle(title) self.h = PythonHighlighter(self.ui.codeView.document()) self.folder = folder self.files_list = [] for path in glob.glob(os.path.join(folder, "*.py")): self.files_list.append(os.path.basename(path)[:-3]) self.ui.selectorList.setModel(QtCore.QStringListModel(self.files_list)) self.model = self.ui.selectorList.selectionModel() self.model.selectionChanged.connect(self.selector_clicked) def selector_clicked(self): item = self.model.selection().indexes()[0] path = os.path.join(self.folder, item.data() + ".py") with open(path, "r") as f: code = f.read() self.ui.codeView.setPlainText(code) @staticmethod def go(folder, title="Saveds"): dialog = IDAngrSavedsDialog(folder, title) r = dialog.exec_() if r == QtWidgets.QDialog.Accepted: return dialog.ui.codeView.toPlainText() class IDAngrConstraintsDialog(QtWidgets.QDialog): def __init__(self, item, text=""): QtWidgets.QDialog.__init__(self) self.ui = Ui_IDAngrConstraintsDialog() self.ui.setupUi(self) if type(item) in (int, long): item = hex(item) self.ui.constrEdit.setPlainText(text) self.setWindowTitle("Edit Constraints - " + str(item)) self.h = PythonHighlighter(self.ui.constrEdit.document()) self.ui.savedsBtn.clicked.connect(self.saveds_clicked) def saveds_clicked(self): code = IDAngrSavedsDialog.go(os.path.join(os.path.dirname(__file__), "saveds", "constraints"), "Predefined Constraints") if code == None: return self.ui.constrEdit.setPlainText(code) @staticmethod def go(item): global _idangr_ctx if item in _idangr_ctx.constraints: dialog = IDAngrConstraintsDialog(item, _idangr_ctx.constraints[item][0]) else: dialog = IDAngrConstraintsDialog(item, "# add your constraints to the var 'sym' using the var 'state'\n") r = dialog.exec_() if r == QtWidgets.QDialog.Accepted: code = dialog.ui.constrEdit.toPlainText() func = "def constr_func(sym, state):\n" for line in code.split("\n"): func += "\t" + line + "\n" try: if manage.is_remote(): manage.remote_exec(func) else: exec(func) in globals() except Exception as ee: QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, 'Constraints Code - Python Error', str(ee)).exec_() return if manage.is_remote(): _idangr_ctx.constraints[item] = (code, manage.remote_eval("constr_func")) else: _idangr_ctx.constraints[item] = (code, constr_func) class IDAngrExecDialog(QtWidgets.QDialog): def __init__(self): global _idangr_ctx QtWidgets.QDialog.__init__(self) self.ui = Ui_IDAngrExecDialog() self.ui.setupUi(self) if _idangr_ctx.find_lambda: self.ui.findCondEdit.setPlainText(_idangr_ctx.find_lambda) if _idangr_ctx.avoid_lambda: self.ui.avoidCondEdit.setPlainText(_idangr_ctx.avoid_lambda) self.ui.simprocsBox.setChecked(get_memory_type() == SIMPROCS_FROM_CLE) self.ui.textloaderBox.setChecked(get_memory_type() == USE_CLE_MEMORY) self.ui.gotloaderBox.setChecked(get_memory_type() == ONLY_GOT_FROM_CLE) self.ui.execallBox.setChecked(get_memory_type() == GET_ALL_DISCARD_CLE) self.fh = PythonHighlighter(self.ui.findCondEdit.document()) self.ah = PythonHighlighter(self.ui.avoidCondEdit.document()) @staticmethod def go(): global _idangr_ctx dialog = IDAngrExecDialog() r = dialog.exec_() if r == QtWidgets.QDialog.Accepted: if dialog.ui.simprocsBox.isChecked(): set_memory_type(SIMPROCS_FROM_CLE) elif dialog.ui.textloaderBox.isChecked(): set_memory_type(USE_CLE_MEMORY) elif dialog.ui.gotloaderBox.isChecked(): set_memory_type(ONLY_GOT_FROM_CLE) elif dialog.ui.execallBox.isChecked(): set_memory_type(GET_ALL_DISCARD_CLE) if dialog.ui.useFindCondBox.isChecked(): code = dialog.ui.findCondEdit.toPlainText() _idangr_ctx.find_lambda = code finds = _idangr_ctx.find avoids = _idangr_ctx.avoid try: if manage.is_remote(): manage.remote_exec("finds = %s" % repr(finds)) manage.remote_exec("avoids = %s" % repr(finds)) manage.remote_exec(code) else: exec(code) in locals() except Exception as ee: QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, 'Find Condition - Python Error', str(ee)).exec_() return None try: if manage.is_remote(): find = manage.remote_eval("find_cond") else: find = find_cond except: QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, 'Error', "find_cond not defined").exec_() return None else: find = _idangr_ctx.find if dialog.ui.useAvoidCondBox.isChecked(): code = dialog.ui.avoidCondEdit.toPlainText() _idangr_ctx.avoid_lambda = code finds = _idangr_ctx.find avoids = _idangr_ctx.avoid try: if manage.is_remote(): manage.remote_exec("finds = %s" % repr(finds)) manage.remote_exec("avoids = %s" % repr(finds)) manage.remote_exec(code) else: exec(code) in locals() except Exception as ee: QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, 'Avoid Condition - Python Error', str(ee)).exec_() return None try: if manage.is_remote(): avoid = manage.remote_eval("avoid_cond") else: avoid = avoid_cond except: QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, 'Error', "avoid_cond not defined").exec_() return None else: avoid = _idangr_ctx.avoid return (find, avoid) return None class IDAngrTableModel(QtCore.QAbstractTableModel): def __init__(self, datain, headerdata, parent=None): QtCore.QAbstractTableModel.__init__(self, parent) self.arraydata = datain self.headerdata = headerdata def rowCount(self, parent): return len(self.arraydata) def columnCount(self, parent): if len(self.arraydata) > 0: return len(self.arraydata[0]) return 0 def data(self, index, role): if not index.isValid(): return None elif role != Qt.DisplayRole: return None return self.arraydata[index.row()][index.column()] def headerData(self, col, orientation, role): if orientation == Qt.Horizontal and role == Qt.DisplayRole: return self.headerdata[col] return None class IDAngrPanelForm(PluginForm): def on_find_menu(self, point): m = QtWidgets.QMenu(self.ui.findView) def delete(): model = self.ui.findView.model() for i in self.ui.findView.selectedIndexes(): model.removeRow(i.row()) def jumpto(): global _idangr_ctx model = self.ui.findView.model() sel = self.ui.findView.selectedIndexes() if len(sel) > 0: idc.jumpto(_idangr_ctx.find[sel[0].row()]) m.addAction('Jump to', jumpto) m.addAction('Delete', delete) m.exec_(self.ui.findView.viewport().mapToGlobal(point)) def on_avoid_menu(self, point): m = QtWidgets.QMenu(self.ui.avoidView) def delete(): model = self.ui.avoidView.model() for i in self.ui.avoidView.selectedIndexes(): model.removeRow(i.row()) def jumpto(): global _idangr_ctx model = self.ui.avoidView.model() sel = self.ui.avoidView.selectedIndexes() if len(sel) > 0: idc.jumpto(_idangr_ctx.avoid[sel[0].row()]) m.addAction('Jump to', jumpto) m.addAction('Delete', delete) m.exec_(self.ui.avoidView.viewport().mapToGlobal(point)) def add_find(self, addr): item = QtWidgets.QListWidgetItem("0x%x" % addr) self.ui.findView.addItem(item) def remove_find(self, addr): model = self.ui.findView.model() for item in self.ui.findView.findItems("0x%x" % addr, Qt.MatchExactly): i = self.ui.findView.indexFromItem(item) model.removeRow(i.row()) def add_avoid(self, addr): item = QtWidgets.QListWidgetItem("0x%x" % addr) self.ui.avoidView.addItem(item) def remove_avoid(self, addr): model = self.ui.avoidView.model() for item in self.ui.avoidView.findItems("0x%x" % addr, Qt.MatchExactly): i = self.ui.avoidView.indexFromItem(item) model.removeRow(i.row()) def reset_clicked(self): global _idangr_ctx while len(_idangr_ctx.simregs) > 0: _idangr_ctx.simregs.pop() while len(_idangr_ctx.simmem) > 0: _idangr_ctx.simmem.pop() _idangr_ctx.find = [] _idangr_ctx.avoid = [] _idangr_ctx.stateman = None _idangr_ctx.simman = None _idangr_ctx.foundstate = None self.ui.regsView.model().layoutChanged.emit() self.ui.memoryView.model().layoutChanged.emit() self.ui.findView.clear() self.ui.avoidView.clear() self.ui.todbgBtn.setEnabled(False) self.ui.viewFileBtn.setEnabled(False) self.ui.nextBtn.setEnabled(False) def run_clicked(self): global _idangr_ctx conds = IDAngrExecDialog.go() if conds == None: return try: _idangr_ctx.stateman = StateManager() except Exception as ee: QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, 'StateManager - Python Error', str(ee)).exec_() return for e in _idangr_ctx.simregs: _idangr_ctx.stateman.sim(e[0]) if e[0] in _idangr_ctx.constraints: try: _idangr_ctx.constraints[e[0]][1](_idangr_ctx.stateman.symbolics[e[0]][0], _idangr_ctx.stateman.state) except Exception as ee: QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, 'Constraints on %s - Python Error' % str(e[0]), str(ee)).exec_() return for e in _idangr_ctx.simmem: addr = int(e[0], 16) _idangr_ctx.stateman.sim(addr, int(e[1])) if addr in _idangr_ctx.constraints: try: _idangr_ctx.constraints[addr][1](_idangr_ctx.stateman.symbolics[int(e[0], 16)][0], _idangr_ctx.stateman.state) except Exception as ee: QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, 'Constraints on %s - Python Error' % str(e[0]), str(ee)).exec_() return sm = _idangr_ctx.stateman.simulation_manager() _idangr_ctx.simman = sm sm.explore(find=conds[0], avoid=conds[1]) if len(sm.found) == 0: QtWidgets.QMessageBox(QtWidgets.QMessageBox.Warning, 'Not Found', "Valid state not found after exploration.\n" + str(_idangr_ctx.stateman) + "\n").exec_() return _idangr_ctx.foundstate = sm.found[0] conc = _idangr_ctx.stateman.concretize(_idangr_ctx.foundstate) for i in xrange(len(_idangr_ctx.simregs)): try: _idangr_ctx.simregs[i][2] = "0x%x" % conc[_idangr_ctx.simregs[i][0]] except: pass for i in xrange(len(_idangr_ctx.simmem)): try: _idangr_ctx.simmem[i][2] = repr(conc[int(_idangr_ctx.simmem[i][0], 16)]) except: pass #print _idangr_ctx.simmem self.ui.filesBox.setRange(0, len(_idangr_ctx.foundstate.posix.fd) -1 +3) self.ui.regsView.model().layoutChanged.emit() self.ui.memoryView.model().layoutChanged.emit() self.ui.todbgBtn.setEnabled(True) self.ui.viewFileBtn.setEnabled(True) self.ui.nextBtn.setEnabled(True) QtWidgets.QMessageBox(QtWidgets.QMessageBox.Information, 'Done', "Valid state found").exec_() def next_clicked(self): global _idangr_ctx conds = IDAngrExecDialog.go() if conds == None: return if _idangr_ctx.stateman == None: _idangr_ctx.stateman = StateManager() for e in _idangr_ctx.simregs: _idangr_ctx.stateman.sim(e[0]) if e[0] in _idangr_ctx.constraints: try: _idangr_ctx.constraints[e[0]][1](_idangr_ctx.stateman.symbolics[e[0]], _idangr_ctx.stateman.state) except Exception as ee: QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, 'Constraints on %s - Python Error' % str(e[0]), str(ee)).exec_() return for e in _idangr_ctx.simmem: addr = int(e[0], 16) _idangr_ctx.stateman.sim(addr, int(e[1])) if addr in _idangr_ctx.constraints: try: _idangr_ctx.constraints[addr][1](_idangr_ctx.stateman.symbolics[int(e[0], 16)], _idangr_ctx.stateman.state) except Exception as ee: QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, 'Constraints on %s - Python Error' % str(e[0]), str(ee)).exec_() return if _idangr_ctx.simman == None: if _idangr_ctx.foundstate == None: sm = _idangr_ctx.stateman.simulation_manager() else: sm = load_project().factory.simulation_manager(_idangr_ctx.foundstate) _idangr_ctx.simman = sm else: sm = _idangr_ctx.simman sm.explore(find=conds[0], avoid=conds[1]) if len(sm.found) == 0: QtWidgets.QMessageBox(QtWidgets.QMessageBox.Warning, 'Not Found', "Valid state not found after exploration.\n" + str(_idangr_ctx.stateman) + "\n").exec_() return _idangr_ctx.foundstate = sm.found[-1] conc = _idangr_ctx.stateman.concretize(_idangr_ctx.foundstate) for i in xrange(len(_idangr_ctx.simregs)): try: _idangr_ctx.simregs[i][2] = "0x%x" % conc[_idangr_ctx.simregs[i][0]] except: pass for i in xrange(len(_idangr_ctx.simmem)): try: _idangr_ctx.simmem[i][2] = repr(conc[int(_idangr_ctx.simmem[i][0], 16)]) except: pass #print _idangr_ctx.simmem self.ui.filesBox.setRange(0, len(_idangr_ctx.foundstate.posix.fd) -1 +3) self.ui.regsView.model().layoutChanged.emit() self.ui.memoryView.model().layoutChanged.emit() QtWidgets.QMessageBox(QtWidgets.QMessageBox.Information, 'Done', "Valid state found").exec_() def todbg_clicked(self): global _idangr_ctx _idangr_ctx.stateman.to_dbg(_idangr_ctx.foundstate) def on_regs_menu(self, point): global _idangr_ctx m = QtWidgets.QMenu(self.ui.regsView) def delete(): model = self.ui.regsView.model() for i in self.ui.regsView.selectedIndexes(): _idangr_ctx.simregs.pop(i.row()) self.ui.regsView.model().layoutChanged.emit() def jumpto(): model = self.ui.regsView.model() sel = self.ui.regsView.selectedIndexes() if len(sel) > 0: try: addr = int(_idangr_ctx.simregs[sel[0].row()][2], 16) idc.jumpto(addr) except: pass def copyval(): model = self.ui.regsView.model() sel = self.ui.regsView.selectedIndexes() if len(sel) > 0: cb = QtWidgets.QApplication.clipboard() cb.clear(mode=cb.Clipboard) cb.setText(_idangr_ctx.simregs[sel[0].row()][2], mode=cb.Clipboard) def set_constr(): model = self.ui.regsView.model() sel = self.ui.regsView.selectedIndexes() if len(sel) > 0: item = _idangr_ctx.simregs[sel[0].row()][0] IDAngrConstraintsDialog.go(item) m.addAction('Jump to', jumpto) m.addAction('Copy value', copyval) m.addAction('Set constraints', set_constr) m.addAction('Delete', delete) m.exec_(self.ui.regsView.viewport().mapToGlobal(point)) def on_mem_menu(self, point): global _idangr_ctx m = QtWidgets.QMenu(self.ui.memoryView) def delete(): model = self.ui.memoryView.model() for i in self.ui.memoryView.selectedIndexes(): _idangr_ctx.simmem.pop(i.row()) self.ui.memoryView.model().layoutChanged.emit() def jumpto(): model = self.ui.memoryView.model() sel = self.ui.memoryView.selectedIndexes() if len(sel) > 0: idc.jumpto(int(_idangr_ctx.simmem[sel[0].row()][0], 16)) def copyval(): model = self.ui.memoryView.model() sel = self.ui.memoryView.selectedIndexes() if len(sel) > 0: cb = QtWidgets.QApplication.clipboard() cb.clear(mode=cb.Clipboard) cb.setText(_idangr_ctx.simmem[sel[0].row()][2], mode=cb.Clipboard) def set_constr(): model = self.ui.memoryView.model() sel = self.ui.memoryView.selectedIndexes() if len(sel) > 0: item = int(_idangr_ctx.simmem[sel[0].row()][0], 16) IDAngrConstraintsDialog.go(item) m.addAction('Jump to', jumpto) m.addAction('Copy value', copyval) m.addAction('Set constraints', set_constr) m.addAction('Delete', delete) m.exec_(self.ui.memoryView.viewport().mapToGlobal(point)) def add_reg(self, idx): global _idangr_ctx reg = _idangr_ctx.regs[idx] for row in _idangr_ctx.simregs: #don't add a reg twice if row[0] == reg: return _idangr_ctx.simregs.append([reg, load_project().arch.registers[reg][1], "?"]) self.ui.regsView.model().layoutChanged.emit() def add_mem(self, addr, size): global _idangr_ctx if type(addr) == int or type(addr) == long: addr = "0x%x" % addr _idangr_ctx.simmem.append([addr, size, "?"]) self.ui.memoryView.model().layoutChanged.emit() def remove_mem(self, addr): pass def view_file_clicked(self): global _idangr_ctx fd = self.ui.filesBox.value() IDAngrTextViewerForm.show_text(_idangr_ctx.foundstate.posix.dumps(fd), "File %d Viewer" % fd) def load_clicked(self): global _idangr_ctx filename = QtWidgets.QFileDialog.getOpenFileName(self.parent, 'Open File')[0] if filename != "": self.reset_clicked() load_ctx(filename) for addr in _idangr_ctx.find: self.add_find(addr) for addr in _idangr_ctx.avoid: self.add_avoid(addr) tablemodel = IDAngrTableModel(_idangr_ctx.simregs, ['Name', 'Size', 'Value'], self.parent) self.ui.regsView.setModel(tablemodel) self.ui.regsView.resizeColumnsToContents() tablemodel = IDAngrTableModel(_idangr_ctx.simmem, ['Address', 'Length', 'Value'], self.parent) self.ui.memoryView.setModel(tablemodel) self.ui.memoryView.resizeColumnsToContents() def save_clicked(self): global _idangr_ctx filename = QtWidgets.QFileDialog.getSaveFileName(self.parent, 'Save File')[0] if filename != "": save_ctx(filename) def OnCreate(self, form): """ Called when the plugin form is created """ global _idangr_ctx _idangr_ctx = IDAngrCtx() # Get parent widget self.parent = self.FormToPyQtWidget(form) self.ui = Ui_IDAngrPanel() self.ui.setupUi(self.parent) project = load_project() self.ui.findView.customContextMenuRequested.connect(self.on_find_menu) self.ui.avoidView.customContextMenuRequested.connect(self.on_avoid_menu) self.ui.resetBtn.clicked.connect(self.reset_clicked) self.ui.runBtn.clicked.connect(self.run_clicked) self.ui.nextBtn.clicked.connect(self.next_clicked) self.ui.todbgBtn.clicked.connect(self.todbg_clicked) self.ui.viewFileBtn.clicked.connect(self.view_file_clicked) self.ui.loadBtn.clicked.connect(self.load_clicked) self.ui.saveBtn.clicked.connect(self.save_clicked) _idangr_ctx.regs = sorted(project.arch.registers, key=lambda x: project.arch.registers.get(x)[0]) for reg in _idangr_ctx.regs: self.ui.registerChooser.addItem(reg) self.ui.registerChooser.setCurrentIndex(-1) self.ui.registerChooser.currentIndexChanged.connect(self.add_reg) tablemodel = IDAngrTableModel(_idangr_ctx.simregs, ['Name', 'Size', 'Value'], self.parent) self.ui.regsView.setModel(tablemodel) self.ui.regsView.resizeColumnsToContents() tablemodel = IDAngrTableModel(_idangr_ctx.simmem, ['Address', 'Length', 'Value'], self.parent) self.ui.memoryView.setModel(tablemodel) self.ui.memoryView.resizeColumnsToContents() self.ui.regsView.customContextMenuRequested.connect(self.on_regs_menu) self.ui.memoryView.customContextMenuRequested.connect(self.on_mem_menu) def OnClose(self, form): """ Called when the plugin form is closed """ #global _idangr_panel #del _idangr_panel def Show(self): """Creates the form is not created or focuses it if it was""" return PluginForm.Show(self, "IDAngr Panel", options = (PluginForm.FORM_TAB | PluginForm.FORM_CLOSE_LATER)) class IDAngrActionHandler(idaapi.action_handler_t): def __init__(self, action): idaapi.action_handler_t.__init__(self) self.action = action def activate(self, ctx): global _idangr_ctx, _idangr_panel if self.action == "Find": addr = idaapi.get_screen_ea() if addr in _idangr_ctx.avoid: _idangr_ctx.avoid.remove(addr) _idangr_panel.remove_avoid(addr) if addr in _idangr_ctx.find: return _idangr_ctx.find.append(addr) _idangr_panel.add_find(addr) elif self.action == "Avoid": addr = idaapi.get_screen_ea() if addr in _idangr_ctx.find: _idangr_ctx.find.remove(addr) _idangr_panel.remove_find(addr) if addr in _idangr_ctx.avoid: return _idangr_ctx.avoid.append(addr) _idangr_panel.add_avoid(addr) elif self.action == "Symbolic": addr = idaapi.get_screen_ea() #if addr in _idangr_ctx.simmem: # return m = IDAngrAddMemDialog.get_mem(addr) if m != None: _idangr_panel.add_mem(m[0], m[1]) #_idangr_ctx.simmem.append(m) def update(self, ctx): return idaapi.AST_ENABLE_ALWAYS class IDAngrHooks(idaapi.UI_Hooks): @staticmethod def finish_populating_tform_popup(form, popup): idaapi.attach_action_to_popup(form, popup, "Find", "IDAngr/") idaapi.attach_action_to_popup(form, popup, "Avoid", "IDAngr/") idaapi.attach_action_to_popup(form, popup, "Symbolic", "IDAngr/") idaapi.register_action(idaapi.action_desc_t('Find', 'Find', IDAngrActionHandler("Find"))) idaapi.register_action(idaapi.action_desc_t('Avoid', 'Avoid', IDAngrActionHandler("Avoid"))) idaapi.register_action(idaapi.action_desc_t('Symbolic', 'Symbolic', IDAngrActionHandler("Symbolic"))) _idangr_hooks = IDAngrHooks() _idangr_hooks.hook() try: _idangr_panel except: _idangr_panel = IDAngrPanelForm() def idangr_panel_show(): global _idangr_panel _idangr_panel.Show()