def auto_map_lvars(self, vdui=None, start_ea=None): func = None if start_ea is None: func = idaapi.get_func(idaapi.get_screen_ea()) start_ea = func.startEA if vdui is None: vdui = idaapi.get_tform_vdui(idaapi.get_current_tform()) if vdui is None: idaapi.jumpto(start_ea) vdui = idaapi.get_tform_vdui(idaapi.get_current_tform()) if func is None: func = idaapi.get_func(start_ea) self.de = idaapi.decompile(func) mapped_vars = False did_stuff = False self.assignments, overall_refs = self.analyze_fn() if self.map_vars_used_only_once(vdui, overall_refs): did_stuff = True mapped_vars = True elif self.map_lvars(vdui): did_stuff = True mapped_vars = True if mapped_vars: vdui.refresh_view(True) elif did_stuff: vdui.refresh_ctext() return did_stuff
def test_choose2(modal=False): global c c = MyChoose2("Choose2 - sample 1", nb=10, modal=modal) r = c.show() form = idaapi.get_current_tform() for thing in ["A", "B"]: idaapi.attach_action_to_popup(form, None, "choose2:act%s" % thing)
def create_ioctl_tab(tracker, modal=False): global ioctl_tracker ioctl_tracker = tracker items = get_all_defines() idaapi.register_action( idaapi.action_desc_t("choose2:remove_ioctl", "Invalid IOCTL", remove_ioctl(items))) action = "send_ioctl" actname = "choose2:act%s" % action idaapi.register_action( idaapi.action_desc_t(actname, "Send IOCTL", send_ioctl_handler_t(items))) idaapi.register_action( idaapi.action_desc_t("choose2:actcopy_defines", "Copy All Defines", copy_defines_handler_t(items))) idaapi.register_action( idaapi.action_desc_t("choose2:actstop_unload", "Stop & Unload Driver", stop_unload_handler_t())) idaapi.register_action( idaapi.action_desc_t("choose2:actstart_load", "Load & Start Driver", start_load_handler_t())) global c c = MyChoose2("IOCTL Code Viewer", items, modal=modal) c.show() form = idaapi.get_current_tform() idaapi.attach_action_to_popup(form, None, "choose2:act%s" % action) idaapi.attach_action_to_popup(form, None, "choose2:actcopy_defines") idaapi.attach_action_to_popup(form, None, "choose2:actstop_unload") idaapi.attach_action_to_popup(form, None, "choose2:actstart_load") idaapi.attach_action_to_popup(form, None, "choose2:remove_ioctl")
def run(): try: current_function = sark.Function() except sark.exceptions.SarkNoFunction: log("Cannot xref registers outside of functions.") return #register_name = idaapi.get_highlighted_identifier() # TypeError: in method 'get_highlight', argument 1 of type 'TWidget *' register_name = idaapi.get_highlighted_identifier(idaapi.get_current_tform()) # ida7.0 must give TWidget* try: register_id = get_register_identifier(register_name) except sark.exceptions.SarkInvalidRegisterName: log("Highlight a register to xref") return choose = RegisterReferencesView(current_function.name, register_name) for line in current_function.lines: if has_register_reference(line.insn, register_id): choose.add_xref(line.ea) choose.show()
def init(self): try: self._install_plugin() except Exception as e: form = idaapi.get_current_tform() pass return idaapi.PLUGIN_KEEP
def register(self): add_bookmark_action = idaapi.action_desc_t( 'add_bookmark:action', 'Add bookmark', self.AddBookmarkHandler(self), None) idaapi.register_action(add_bookmark_action) form = idaapi.get_current_tform() idaapi.attach_action_to_popup(form, None, 'add_bookmark:action') self.Show()
def get_init_menu(self): try: self.widget = form_to_widget(idaapi.get_current_tform()) if self.widget is None: raise Exception() except: self.widget = form_to_widget(idaapi.find_tform('Output window')) self.window = self.widget.window() self.menu = self.window.findChild(QtWidgets.QMenuBar)
def get_custom_viewer_hint(self, view, place): try: tform = idaapi.get_current_tform() if idaapi.get_tform_type(tform) != idaapi.BWN_DISASM: return None curline = idaapi.get_custom_viewer_curline(view, True) _, x, y = idaapi.get_custom_viewer_place(view, True) ea = place.toea() # "color" is a bit of misnomer: its the type of the symbol currently hinted color = get_color_at_char(curline, x) if color != idaapi.COLOR_ADDR: return None # for COLOR_ADDR tokens, we get something like: # 401000sub_401000 # so we will need to prune the address from the start before we can use it :-( token = get_token_at_char(curline, x) # enumerate the operands of the instruction at this address # and search the token for the operand text func_name = None for i in range(3): o = idc.GetOpnd(ea, i) if not o: break # if we have `offset sub_401000`, we want: `sub_401000` if ' ' in o: o = o.partition(' ')[2] if o in token: func_name = o break if not func_name: return None # get the address given the function name fva = idc.LocByName(func_name) if not fva: return None # ensure its actually a function if not idaapi.get_func(fva): return None # this magic constant "1" is the number of "important lines" to display by default. # the remaining lines get shown if you scroll down while the hint is displayed, revealing more lines. return render_function_hint(fva), 1 except Exception as e: print( 'CallsHintsPlugin: error: %s. Get in touch with @williballenthin.' % (str(e))) return None
def create_view(self, bap): "creates a new view" pid = bap.proc.pid name = 'BAP-{0}'.format(pid) view = View(name, bap, on_close=lambda: self.delete_view(pid)) view.instance = bap curr = idaapi.get_current_tform() self.views[pid] = view view.Show() # pylint: disable=no-member idaapi.switchto_tform(curr, True)
def get_window(): """Get IDA's top level window.""" tform = idaapi.get_current_tform() # Required sometimes when closing IDBs and not IDA. if not tform: tform = idaapi.find_tform("Output window") widget = form_to_widget(tform) window = widget.window() return window
def init(self): try: self._install_plugin() idaapi.msg("RECLASSIFY load complete.\n") # failed to initialize or integrate the plugin, log and skip loading except Exception as e: form = idaapi.get_current_tform() print e return idaapi.PLUGIN_KEEP
def refresh_views(): """ Refresh the IDA views. """ # refresh IDA views idaapi.refresh_idaview_anyway() # refresh hexrays view, if active current_tform = idaapi.get_current_tform() vu = idaapi.get_tform_vdui(current_tform) if vu: vu.refresh_ctext()
def get_cursor_func_ref(): """ Get the function reference under the user cursor. Returns BADADDR or a valid function address. """ current_tform = idaapi.get_current_tform() tform_type = idaapi.get_tform_type(current_tform) # get the hexrays vdui (if available) vu = idaapi.get_tform_vdui(current_tform) # # hexrays view is active # if vu: cursor_addr = vu.item.get_ea() # # disassembly view is active # elif tform_type == idaapi.BWN_DISASM: cursor_addr = idaapi.get_screen_ea() # # if the cursor is over an operand value that has a function ref, # use that as a valid rename target # op_addr = idc.GetOperandValue(cursor_addr, idaapi.get_opnum()) op_func = idaapi.get_func(op_addr) if op_func and op_func.startEA == op_addr: return op_addr # unsupported/unknown view is active else: return idaapi.BADADDR # # if the cursor is over a function definition or other reference, use that # as a valid rename target # cursor_func = idaapi.get_func(cursor_addr) if cursor_func and cursor_func.startEA == cursor_addr: return cursor_addr # fail return idaapi.BADADDR
def init(self): """ This is called by IDA when it is loading the plugin. """ # attempt plugin initialization try: self._install_plugin() # failed to initialize or integrate the plugin, log and skip loading except Exception as e: form = idaapi.get_current_tform() pass return idaapi.PLUGIN_KEEP
def register(self): form = idaapi.get_current_tform() the_name = "reverse to" idaapi.register_action( idaapi.action_desc_t(the_name, "reverse to", self.stacktrace_handler(self.revTo))) idaapi.attach_action_to_popup(form, None, the_name) the_name = "refresh_stack" idaapi.register_action( idaapi.action_desc_t( the_name, "refresh stack", self.stacktrace_handler(self.updateStackTrace))) idaapi.attach_action_to_popup(form, None, the_name)
def touch_window(target): """ Touch a window/widget/form to ensure it gets drawn by IDA. XXX/HACK: We need to ensure that widget we will analyze actually gets drawn so that there are colors for us to steal. To do this, we switch to it, and switch back. I tried a few different ways to trigger this from Qt, but could only trigger the full painting by going through the IDA routines. """ # get the currently active widget/form title (the form itself seems transient...) if using_ida7api: twidget = idaapi.get_current_widget() title = idaapi.get_widget_title(twidget) else: form = idaapi.get_current_tform() title = idaapi.get_tform_title(form) # touch/draw the widget by playing musical chairs if using_ida7api: # touch the target window by switching to it idaapi.activate_widget(target, True) flush_ida_sync_requests() # locate our previous selection previous_twidget = idaapi.find_widget(title) # return us to our previous selection idaapi.activate_widget(previous_twidget, True) flush_ida_sync_requests() else: # touch the target window by switching to it idaapi.switchto_tform(target, True) flush_ida_sync_requests() # locate our previous selection previous_form = idaapi.find_tform(title) # lookup our original form and switch back to it idaapi.switchto_tform(previous_form, True) flush_ida_sync_requests()
def __init__(self, *args, **kwargs): # Main entry for the plugin # When plugin is hooked every function here will be initialized print("[SPIRIT] SpiritMS IDA Plugin succesfully loaded") idaapi.plugin_t.__init__(self) icon_data = str(open(PIC_DIR, "rb").read()) self.icon_id = idaapi.load_custom_icon(data=icon_data) self.load_folders() self.load_actions() self.hooks = Hooks() self.hooks.hook() form = idaapi.get_current_tform() idaapi.attach_action_to_popup(form, None, "my:InHeader", None)
def load_actions(self): # Loading all icons and functions in right click context menu action_desc = idaapi.action_desc_t( 'my:InHeader', # The action name. This acts like an ID and must be unique '[Spirit] Analyze InHeader Ops', # The action text. InHeaderHandler(), # The action handler. 'Ctrl+H', # Optional: the action shortcut 'Analyzes InHeader Opcodes', # Optional: the action tooltip (available in menus/toolbar) self.icon_id) packet_analysis = idaapi.action_desc_t( 'my:PacketStruct', '[Spirit] Analyze Packet Structure', PacketAnalysis(), 'Ctrl+Shift+E', 'Analyzes Packet Structure.', self.icon_id) out_packet_analysis = idaapi.action_desc_t( 'my:OutPacket', '[Spirit] Grab OutPacket Info', OutPacketAnalysis(), 'Ctrl+Shift+F', 'Provides some information on a given OutPacket function.', self.icon_id) open_file = idaapi.action_desc_t( 'my:OpenFile', '[Spirit] Open function in notepad', FileOpener(), 'Ctrl+Shift+W', 'Lets you open the pseudocode in notepad environment.', self.icon_id) idaapi.register_action(packet_analysis) idaapi.register_action(action_desc) idaapi.register_action(out_packet_analysis) idaapi.register_action(open_file) form = idaapi.get_current_tform() idaapi.attach_action_to_popup(form, None, "my:InHeader", None) idaapi.attach_action_to_popup(form, None, "my:PacketStruct", None) idaapi.attach_action_to_popup(form, None, "my:OutPacket", None) idaapi.attach_action_to_popup(form, None, "my:OpenFile", None)
def get_custom_viewer_hint(self, view, place): try: tform = idaapi.get_current_tform() if idaapi.get_tform_type(tform) != idaapi.BWN_DISASM: return None curline = idaapi.get_custom_viewer_curline(view, True) # sometimes get_custom_viewer_place() returns [x, y] and sometimes [place_t, x, y]. # we want the place_t. viewer_place = idaapi.get_custom_viewer_place(view, True) if len(viewer_place) != 3: return None _, x, y = viewer_place ea = place.toea() # "color" is a bit of misnomer: its the type of the symbol currently hinted color = get_color_at_char(curline, x) if color != idaapi.COLOR_ADDR: return None # grab the FAR references to code (not necessarilty a branch/call/jump by itself) far_code_references = [ xref.to for xref in idautils.XrefsFrom(ea, ida_xref.XREF_FAR) if idc.isCode(idc.GetFlags(xref.to)) ] if len(far_code_references) != 1: return None fva = far_code_references[0] # ensure its actually a function if not idaapi.get_func(fva): return None # this magic constant is the number of "important lines" to display by default. # the remaining lines get shown if you scroll down while the hint is displayed, revealing more lines. return render_function_hint(fva), DEFAULT_IMPORTANT_LINES_NUM except Exception as e: logger.warning( 'unexpected exception: %s. Get in touch with @williballenthin.', e, exc_info=True) return None
def refresh_views(): """ Refresh the IDA views. """ # refresh IDA views idaapi.refresh_idaview_anyway() # NOTE/COMPAT: refresh hexrays view, if active if using_ida7api: current_widget = idaapi.get_current_widget() vu = idaapi.get_widget_vdui(current_widget) else: current_tform = idaapi.get_current_tform() vu = idaapi.get_tform_vdui(current_tform) if vu: vu.refresh_ctext()
def run(self, arg): global tainted_pcs # this is called when select the plugin from the Edit>Plugins menu curwidget = idaapi.get_current_tform() if (idaapi.BWN_PSEUDOCODE == idaapi.get_widget_type(curwidget)): reuse = HIT2_ReuseDialog.GET_NEW_PROCESS clear_old = False if (len(tainted_pcs) > 0): reuse = HIT2_ReuseDialog.askToReuse() if (HIT2_ReuseDialog.GET_NEW_PROCESS == reuse): tainted_pcs.clear() # need to clear old colors in case changing process on the # same decompiled function that colored before clear_old = True if (HIT2_ReuseDialog.CANCEL_REQUEST != reuse): self.color_pseudocode(curwidget, clear_old) else: idaapi.msg("Current window is not a pseudocode window\n")
def init(self): self.plugin = MyScriptLaunch() # Involve class from included script # Check the version of IDA if idaapi.IDA_SDK_VERSION < 700: print("Plugin doesn't support this version of IDA.") return idaapi.PLUGIN_HIDE # Try install plugin in IDA try: self._install_plugin() except Exception as e: form = idaapi.get_current_tform() pass # Toolbar menu # Describe the action menus for Plugin idaapi.action_desc_t( 'My Plugin', # The action name. This acts like an ID and must be unique 'Main menu of Plugin', # The action text. EditorHandler(self.run), # The action handler. 'Ctrl+Alt+W', # Optional: the action shortcut 'Plugin for runing other scripts' # Optional: the action tooltip (available in menus/toolbar) ) # Registration of this action to menu idaapi.attach_action_to_menu( 'Edit/Plugins', # Relative path of where to add the action 'My Plugin', # The action ID (see above) idaapi.SETMENU_APP # We want to append the action after ^ ) # Launch the Taint script # Describe the action menus (Your script) action_desc = idaapi.action_desc_t( 'Script', # The action name. This acts like an ID and must be unique 'My Script', # The action text. EditorHandler(self.myScript), # The action handler. 'Ctrl+Alt+A', # Optional: the action shortcut 'Run my script' # Optional: the action tooltip (available in menus/toolbar) ) # Registration this action idaapi.register_action(action_desc) return PLUGIN_OK
def editor_menuaction(self): action_desc = idaapi.action_desc_t( 'my:editoraction', # The action name. This acts like an ID and must be unique 'Python Editor!', # The action text. MyEditorHandler(), # The action handler. 'Ctrl+H', # Optional: the action shortcut DO IT HERE! 'Script editor', # Optional: the action tooltip (available in menus/toolbar) idaapi.load_custom_icon( ":/ico/python.png" ) # hackish load action icon , if no custom icon use number from 1-150 from internal ida ) # 3) Register the action idaapi.register_action(action_desc) idaapi.attach_action_to_menu( 'File/Editor...', # The relative path of where to add the action 'my:editoraction', # The action ID (see above) idaapi.SETMENU_APP ) # We want to append the action after the 'Manual instruction... form = idaapi.get_current_tform() idaapi.attach_action_to_popup(form, None, "my:editoraction", None)
def get_cursor_func_ref(): current_tform = idaapi.get_current_tform() tform_type = idaapi.get_tform_type(current_tform) # get the hexrays vdui (if available) vu = idaapi.get_tform_vdui(current_tform) if vu: cursor_addr = vu.item.get_ea() elif tform_type == idaapi.BWN_DISASM: cursor_addr = idaapi.get_screen_ea() op_addr = idc.GetOperandValue(cursor_addr, idaapi.get_opnum()) op_func = idaapi.get_func(op_addr) if op_func and op_func.startEA == op_addr: return op_addr else: return idaapi.BADADDR cursor_func = idaapi.get_func(cursor_addr) if cursor_func and cursor_func.startEA == cursor_addr: return cursor_addr return idaapi.BADADDR
idaapi.set_switch_info(jmp_loc, s) idaapi.create_switch_table(jmp_loc, s) return 1 def create_table(self): screen_ea = idaapi.get_screen_ea() print("Creating table at: ", hex(screen_ea)) ida_bytes.del_items(screen_ea, 0, 4*6) ret = ida_bytes.create_data(screen_ea, ida_bytes.FF_DWORD, 4, idaapi.BADNODE) print("got return: ", ret) idc.MakeArray(screen_ea, 6) # This action is always available. def update(self, ctx): return idaapi.AST_ENABLE_ALWAYS action_desc = idaapi.action_desc_t( 'rusty:table', # The action name. This acts like an ID and must be unique 'Create Table!', # The action text. MyHandler(), # The action handler. 'Ctrl+Shift+E', # Optional: the action shortcut 'Create Table!', # Optional: the action tooltip (available in menus/toolbar) 199) # Optional: the action icon (shows when in menus/toolbars) idaapi.unregister_action('rusty:table') idaapi.register_action(action_desc) form = idaapi.get_current_tform() idaapi.attach_action_to_popup(form, None, "rusty:table", None) idaapi.attach_action_to_menu( 'Edit/Other/Manual instruction...', # The relative path of where to add the action 'rusty:table', # The action ID (see above) idaapi.SETMENU_APP)
def get_current_widget(): if idaapi.IDA_SDK_VERSION <= 699: form = idaapi.get_current_tform() else: form = ida_kernwin.get_current_widget() return form
def cb(user_data, notification_code, va_list): ''' example hook_cb_t function that handles custom viewer hints. Args: user_data (ctypes.c_void_p): context supplied to callback registration notification_code (int): one of the UI_NOTIFICATIONS enum values va_list (ctypes.c_void_p): varargs that must be manually parsed Returns: int: see notifiication code documentation for interpretation Notes: - This is a closure that expects to have ''' # this function is called *a lot*, so don't do any heavy lifting # until you know its the event you want. # ctypes doesn't support varargs in callback functions. # so, we need to parse the remaining arguments ourselves. # # on windows, varargs are sequential stack locations. # so, lets access the members like an array of ints/pointers. # # WARNING: the following section that manually parses varargs is # probably architecture and platfrom dependent! va_list = ctypes.cast(va_list, c_long_p) if notification_code == UI_NOTIFICATIONS.UI_GET_EA_HINT: # ea is just a number: # # typedef uint32 ea_t # # via: https://www.hex-rays.com/products/ida/support/sdkdoc/pro_8h.html#a7b0aeaed04e477c02cf8ea3452002d1a ea = va_list[0] buf = ctypes.cast(va_list[1], ctypes.c_char_p) bufsize = va_list[2] print('ui_get_ea_hint:') print('>.. notification code: %s' % (notification_code)) print('>.. ea: %s' % (hex(ea))) print('>.. buf: %s' % (buf)) print('>.. bufsize: %s' % (hex(bufsize))) the_hint = datetime.datetime.now().isoformat(' ') self.dll.qstrncpy(buf, ctypes.c_char_p(the_hint), bufsize) print('<.. buf: %s' % (buf)) return 1 elif notification_code == UI_NOTIFICATIONS.UI_GET_CUSTOM_VIEWER_HINT: viewer = ctypes.cast(va_list[0], c_long_p) place = ctypes.cast(va_list[1], c_long_p) important_lines = ctypes.cast(va_list[2], c_long_p) hint = ctypes.cast(va_list[3], c_char_pp) if not place: print('ui_get_custom_viewer_hint: invalid place') return 0 print('ui_get_custom_viewer_hint:') print('>.. notification code: %s' % (notification_code)) print('>.. important lines: %s %s' % (important_lines, important_lines.contents)) print('>.. hint: %s %s' % (hint, hint.contents)) # so, we'd like to fetch the EA of the current view. # ideally, we'd do: # # ea = place.toea() # # but `place` is a raw c++ object pointer, and ctypes isn't that smart. # next best would be to do something like: # # place = self.dll.get_custom_viewer_place(viewer); # # however, this doesn't work because `get_custom_viewer_place` is not an exported routine. # it seems to be part of the IDA SDK static lib to which plugins link. # # next best would be to use `idaapi.get_custom_viewer_place`: # # place = idaapi.get_custom_viewer_place(viewer); # # but, this doesn't work because we're mixing a ctypes pointer with a swig function. # so, we'll fall back to querying the current viewer, and fetching the place from there. # let's only display for disassembly listings # # i only know how to test the view/form type using the `get_tform_type` function. # therefore, we'll first query the current tform, and subsequently the current custom_viewer. tform = idaapi.get_current_tform() if idaapi.get_tform_type(tform) != idaapi.BWN_DISASM: return 0 viewer = idaapi.get_current_viewer() # `place` is a tuple (though techincally, a list), with elements: # - place_t proxy # - x position in characters # - y position in characters from top of screen/form (-1 in graph view) place, x, y = idaapi.get_custom_viewer_place(viewer, True) the_hint = '0x%08X: %s' % ( place.toea(), datetime.datetime.now().isoformat(' ')) important_lines[0] = ctypes.c_long(1) # we don't have access to the qstring c++ class methods, # so we'll use a dummy routine to correctly set our qstring contents. # `replace_tabs` assigns from a char * to a qstring *. # # relevant idasdk documentation: # # idaman THREAD_SAFE bool ida_export # replace_tabs ( # qstring *out, # const char *str, # int tabsize) self.dll.replace_tabs(hint, ctypes.c_char_p(the_hint), 4) print('<.. important lines: %s %s' % (important_lines, important_lines.contents)) print('<.. hint: %s %s' % (hint, hint.contents)) return 1 return 0
def get_window(): """Get IDA's top level window.""" tform = idaapi.get_current_tform() widget = idaapi.PluginForm.FormToPySideWidget(tform) window = widget.window() return window
def get_cursor_func_ref(): """ Get the function reference under the user cursor. Returns BADADDR or a valid function address. """ # NOTE / COMPAT: if using_ida7api: current_widget = idaapi.get_current_widget() form_type = idaapi.get_widget_type(current_widget) vu = idaapi.get_widget_vdui(current_widget) else: current_tform = idaapi.get_current_tform() form_type = idaapi.get_tform_type(current_tform) vu = idaapi.get_tform_vdui(current_tform) # # hexrays view is active # if vu: cursor_addr = vu.item.get_ea() # # disassembly view is active # elif form_type == idaapi.BWN_DISASM: cursor_addr = idaapi.get_screen_ea() opnum = idaapi.get_opnum() if opnum != -1: # # if the cursor is over an operand value that has a function ref, # use that as a valid rename target # # NOTE/COMPAT: if using_ida7api: op_addr = idc.get_operand_value(cursor_addr, opnum) else: op_addr = idc.GetOperandValue(cursor_addr, opnum) op_func = idaapi.get_func(op_addr) # NOTE/COMPAT: if using_ida7api: if op_func and op_func.start_ea == op_addr: return op_addr else: if op_func and op_func.startEA == op_addr: return op_addr # unsupported/unknown view is active else: return idaapi.BADADDR # # if the cursor is over a function definition or other reference, use that # as a valid rename target # cursor_func = idaapi.get_func(cursor_addr) # NOTE/COMPAT: if using_ida7api: if cursor_func and cursor_func.start_ea == cursor_addr: return cursor_addr else: if cursor_func and cursor_func.startEA == cursor_addr: return cursor_addr # fail return idaapi.BADADDR