def jump(custom_viewer, line): (pl, x, y) = idaapi.get_custom_viewer_place(custom_viewer, False) pl2 = idaapi.place_t_as_simpleline_place_t(pl.clone()) oldline = pl2.n pl2.n = line idaapi.jumpto(custom_viewer, pl2, x, y) return oldline
def get_ea_from_highlight(): view = idaapi.get_current_viewer() thing = ida_kernwin.get_highlight(view) if thing and thing[1]: # we have a highligh, is it a valid name ? ea = idc.get_name_ea_simple(thing[0]) if ea != idaapi.BADADDR: return ea # get name at screen ea ea = idc.get_screen_ea() name = idc.get_name(ea, idaapi.GN_DEMANGLED) if name and thing[0] in name: return ea # Try to get full highlight name place = idaapi.get_custom_viewer_place(view, False) if place and len(place) == 3: # (plate_t, x, y) ea = place[0].toea() far_code_refs = [xref.to for xref in idautils.XrefsFrom(ea, ida_xref.XREF_FAR)] if far_code_refs: return far_code_refs[0] # First xref # Reach now, we do not have any valid name, return current screen ea return idc.get_screen_ea()
def get_custom_viewer_hint(self, view, place): curline = idaapi.get_custom_viewer_curline(view, True) _, x, y = idaapi.get_custom_viewer_place(view, True) ea = place.toea() return ('0x%08X: %s' % (place.toea(), datetime.datetime.now().isoformat(' ')), 1)
def jump_to_line(ea, line, col): idc.Jump(ea) viewer = idaapi.get_current_viewer() (pl, x, y) = idaapi.get_custom_viewer_place(viewer, False) pl2 = idaapi.place_t_as_simpleline_place_t(pl.clone()) pl2.n = line x = col y = 10 idaapi.jumpto(viewer, pl2, x, y)
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 jump(self, data): j = data['address'].split(" : ") ea = idaapi.get_name_ea(idc.BADADDR, j[0]) ln = int(j[1]) print "JUMPTO", j, ea, ln ui = idaapi.open_pseudocode(ea, False) (pl, x, y) = idaapi.get_custom_viewer_place(ui.ct, False) pl2 = idaapi.place_t_as_simpleline_place_t(pl.clone()) pl2.n = ln idaapi.jumpto(ui.ct, pl2, 0, y)
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 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