def apply_cfg(reload=False, filters={}): """loads abyss configuration.""" cfg_file = get_cfg_filename() kw.msg("%s: %sloading %s...\n" % (PLUGIN_NAME, "re" if reload else "", cfg_file)) if not os.path.isfile(cfg_file): kw.msg("%s: default configuration (%s) does not exist!\n" % (PLUGIN_NAME, cfg_file)) kw.msg("Creating default configuration\n") try: with open(cfg_file, "w") as f: f.write("[init]\n") for name, mod in filters.items(): f.write("%s=False\n" % name) except: kw.msg("failed!\n") return False return apply_cfg(reload=True) config = configparser.RawConfigParser() config.readfp(open(cfg_file)) # read all sections for section in config.sections(): if section == "init": for name, value in config.items(section): try: filters[name].set_activated( config[section].getboolean(name)) #print("%s -> %s" % (name, value)) except: pass kw.msg("done!\n") return True
def create_ram_segment(): success = add_segm(0, RAM_START_ADDRESS, RAM_START_ADDRESS + RAM_SIZE, "RAM", None) == 1 msg("creating RAM segment..%s" % ("ok!\n" if success else "failure!\n")) if (not success): return set_segm_addressing(getseg(RAM_START_ADDRESS), 0)
def create_rom_segment(): success = add_segm(0, ROM_START_ADDRESS, ROM_START_ADDRESS + ROM_SIZE, "ROM", "CODE") == 1 msg("creating ROM segment..%s" % ("ok!\n" if success else "failure!\n")) if (not success): return set_segm_addressing(getseg(ROM_START_ADDRESS), 0)
def install_plugin(): """Installs script to IDA userdir as a plugin.""" if is_plugin(): kw.msg("Command not available. Plugin already installed.\n") return False src = SELF if is_installed(): btnid = kw.ask_yn( kw.ASKBTN_NO, "File exists:\n\n%s\n\nReplace?" % get_target_filename()) if btnid is not kw.ASKBTN_YES: return False dst = get_target_filename() usrdir = os.path.dirname(dst) kw.msg("Copying script from \"%s\" to \"%s\" ..." % (src, usrdir)) if not os.path.exists(usrdir): try: os.path.makedirs(usrdir) except OSError as e: if e.errno != errno.EEXIST: kw.msg("failed (mkdir)!\n") return False try: shutil.copy(src, dst) except: kw.msg("failed (copy)!\n") return False kw.msg(("done\n" "Plugin installed - please restart this IDA instance now.\n")) return True
def detect_arch(): #heuristically determine what architecture we're on #only x86-64 and arm64 are supported is_le = False bits = 0 info = get_inf_structure() arch = ARCH_UNKNOWN if info.is_64bit(): bits = 64 elif info.is_32bit(): bits = 32 else: bits = 16 if not info.is_be(): is_le = True procname = info.procName if bits == 64 and is_le: if procname == "ARM": msg("Detected architecture: arm64\n") arch = ARCH_ARM64 elif procname == "metapc": msg("Detected architecture: x86_64\n") arch = ARCH_X86_64 return arch
def on_mb_click(self, event, addr, size, mouse_offs): button = event.button() if button == Qt.MiddleButton: mouse = addr + mouse_offs c = get_byte(mouse) head, name, size = self._get_item_info(mouse) funcname = self._get_func_name(mouse) self.ann = [(mouse, qRgb(c, 0xFF, self.hl_color), "Address: %X" % (mouse), qRgb(c, 0xFF, self.hl_color)), (None, None, " Item: %s" % (name), qRgb(c, 0xFF, self.hl_color)), (None, None, " Head: %X" % (head), qRgb(c, 0xFF, self.hl_color)), (None, None, " Size: %d" % (size), qRgb(c, 0xFF, self.hl_color))] if funcname: self.ann.append((None, None, " Function: %s" % (funcname), qRgb(c, 0xFF, self.hl_color))) self.last_sel = (head, size) elif button == Qt.MiddleButton: pass elif button == Qt.RightButton: self.switch ^= 1 msg('Highlighting %s\n' % self.mode[self.switch])
def init(self): self.xray_hooks = None if not is_compatible(): kw.msg("%s: decompiler not available, skipping." % PLUGIN_NAME) return ida_idaapi.PLUGIN_SKIP load_cfg() kw.register_action( kw.action_desc_t( XRAY_LOADCFG_ACTION_ID, "%s: reload config" % PLUGIN_NAME, loadcfg_action_handler_t(), "Ctrl-R")) kw.register_action( kw.action_desc_t( XRAY_FILTER_ACTION_ID, "%s: toggle" % PLUGIN_NAME, xray_action_handler_t(), "F3")) kw.register_action( kw.action_desc_t( XRAY_QUERY_ACTION_ID, "%s: search" % PLUGIN_NAME, regexfilter_action_handler_t(), "Ctrl-F")) self.xray_hooks = xray_hooks_t() self.xray_hooks.hook() return ida_idaapi.PLUGIN_KEEP
def __init__(self, objc_class_va, segment_map, arch=ARCH_X86_64): """Create a new ObjcClass instance Arguments: objc_class_va {number} -- Virtual address of the Objective-C class to parse segment_map {dictionary} -- A dictionary mapping segment names to a start/end virtual address tuple Keyword Arguments: arch {number} -- CPU architecture. Either ARCH_X86_64 or ARM64 (default: {ARCH_X86_64}) """ self.arch = arch self.segment_map = segment_map class_ro_va = get_qword(objc_class_va + self.OBJC2_CLASS_RO_OFFSET) self.name_pointer = get_qword(class_ro_va + self.OBJC2_CLASS_RO_NAME_OFFSET) self.method_list = [] if class_ro_va == BADADDR or class_ro_va == 0: self.class_ro_va = None return self.class_ro_va = class_ro_va class_methods_va = get_qword(class_ro_va + self.OBJC2_CLASS_RO_BASE_METHODS_OFFSET) if class_methods_va == BADADDR or class_methods_va == 0: self.class_methods_va = None return self.class_methods_va = class_methods_va msg("Class found at virtual address: 0x%x\n" % objc_class_va) msg("Class name: %s\n" % get_strlit_contents(self.name_pointer)) #Parse the method_list_t struct and build a list of methods self.method_list = ObjcMethodList(class_methods_va, segment_map, arch=arch)
def run(self, arg=0): #we need the calls again if we wanna load it via File/Plugins/editor ida_kernwin.msg( "StyleSheet Paster Loaded to menu \n use Alt+P hot key to quick load " ) hackish = MyEditorHandlerPaste( ) #must be the same as line (53) change also hackish = must be unique also line (100) hackish.activate(self) #hackish must the same as line hackish = (99)
def OnViewKeydown(self, key, state): c = chr(key & 0xFF) if c == 'C': self.center_node = not self.center_node ida_kernwin.msg("%s: centering graph %sabled\n" % (PLUGIN_NAME, "en" if self.center_node else "dis")) return True
def FindInstructions(instr, asm_where=None): """ Finds instructions/opcodes @return: Returns a tuple(True, [ ea, ... ]) or a tuple(False, "error message") """ if not asm_where: # get first segment seg = ida_segment.get_first_seg() asm_where = seg.start_ea if seg else ida_idaapi.BADADDR if asm_where == ida_idaapi.BADADDR: return (False, "No segments defined") # regular expression to distinguish between opcodes and instructions re_opcode = re.compile('^[0-9a-f]{2} *', re.I) # split lines lines = instr.split(";") # all the assembled buffers (for each instruction) bufs = [] for line in lines: if re_opcode.match(line): # convert from hex string to a character list then join the list to form one string buf = bytes(bytearray([int(x, 16) for x in line.split()])) else: # assemble the instruction ret, buf = idautils.Assemble(asm_where, line) if not ret: return (False, "Failed to assemble:" + line) # add the assembled buffer bufs.append(buf) # join the buffer into one string buf = b''.join(bufs) # take total assembled instructions length tlen = len(buf) # convert from binary string to space separated hex string bin_str = ' '.join( ["%02X" % (ord(x) if sys.version_info.major < 3 else x) for x in buf]) # find all binary strings print("Searching for: [%s]" % bin_str) ea = ida_ida.cvar.inf.min_ea ret = [] while True: ea = ida_search.find_binary(ea, ida_idaapi.BADADDR, bin_str, 16, ida_search.SEARCH_DOWN) if ea == ida_idaapi.BADADDR: break ret.append(ea) ida_kernwin.msg(".") ea += tlen if not ret: return (False, "Could not match [%s]" % bin_str) ida_kernwin.msg("\n") return (True, ret)
def walk_classes(self, segment_map): msg("Walking classes\n") classes = [] objc_data_start, objc_data_end = segment_map["__objc_data"] for va in range(objc_data_start, objc_data_end, self.objc2ClassSize): objc_class = ObjcClass(va, segment_map, arch=self.arch) classes.append(objc_class) self.extend(objc_class.patched_xrefs()) self.classes = classes
def init(self): global banner self.forms = [] self.options = (PluginForm.WOPN_MENU | PluginForm.WOPN_ONTOP | PluginForm.WOPN_RESTORE | PluginForm.FORM_SAVE | PluginForm.WOPN_PERSIST | PluginForm.WCLS_CLOSE_LATER) msg('%s' % banner) return PLUGIN_KEEP
def activate(self, ctx): global IS_ACTIVATED IS_ACTIVATED = not IS_ACTIVATED vu = ida_hexrays.get_widget_vdui(ctx.widget) if vu: vu.refresh_ctext() kw.msg("[%s] %sactivated.\n" % (PLUGIN_NAME, "" if IS_ACTIVATED else "de")) return 1
def create_exprom_segment(): success = add_segm(0, EXPROM_START_ADDRESS, EXPROM_START_ADDRESS + EXPROM_SIZE, "EXP_ROM", None) == 1 msg("creating EXP_ROM segment..%s" % ("ok!\n" if success else "failure!\n")) if (not success): return set_segm_addressing(getseg(EXPROM_START_ADDRESS), 0)
def init(self): self.gamma_hooks = None if not is_compatible(): kw.msg("%s: decompiler not available, skipping." % PLUGIN_NAME) return ida_idaapi.PLUGIN_SKIP self.gamma_hooks = gamma_hooks_t() self.gamma_hooks.hook() return ida_idaapi.PLUGIN_KEEP
def coffee_main(): global coffee if coffee and not coffee.is_dead(): coffee.die() coffee = None return coffee = painter_t() ida_kernwin.msg("Caffeinated\n")
def FindInstructions(instr, asm_where=None): """ Finds instructions/opcodes @return: Returns a tuple(True, [ ea, ... ]) or a tuple(False, "error message") """ if not asm_where: # get first segment seg = ida_segment.get_first_seg() asm_where = seg.start_ea if seg else ida_idaapi.BADADDR if asm_where == ida_idaapi.BADADDR: return (False, "No segments defined") # regular expression to distinguish between opcodes and instructions re_opcode = re.compile('^[0-9a-f]{2} *', re.I) # split lines lines = instr.split(";") # all the assembled buffers (for each instruction) bufs = [] for line in lines: if re_opcode.match(line): # convert from hex string to a character list then join the list to form one string buf = ''.join([chr(int(x, 16)) for x in line.split()]) else: # assemble the instruction ret, buf = idautils.Assemble(asm_where, line) if not ret: return (False, "Failed to assemble:"+line) # add the assembled buffer bufs.append(buf) # join the buffer into one string buf = ''.join(bufs) # take total assembled instructions length tlen = len(buf) # convert from binary string to space separated hex string bin_str = ' '.join(["%02X" % ord(x) for x in buf]) # find all binary strings print("Searching for: [%s]" % bin_str) ea = ida_ida.cvar.inf.min_ea ret = [] while True: ea = ida_search.find_binary(ea, ida_idaapi.BADADDR, bin_str, 16, ida_search.SEARCH_DOWN) if ea == ida_idaapi.BADADDR: break ret.append(ea) ida_kernwin.msg(".") ea += tlen if not ret: return (False, "Could not match [%s]" % bin_str) ida_kernwin.msg("\n") return (True, ret)
def load_trainer(li): if (not INES_MASK_SRAM(hdr.rom_control_byte_0)): success = add_segm(0, TRAINER_START_ADDRESS, TRAINER_START_ADDRESS + TRAINER_SIZE, "TRAINER", "CODE") == 1 msg("creating TRAINER segment..%s", "ok!\n" if success else "failure!\n") set_segm_addressing(getseg(TRAINER_START_ADDRESS), 0) li.file2base(INES_HDR_SIZE, TRAINER_START_ADDRESS, TRAINER_START_ADDRESS + TRAINER_SIZE, FILEREG_PATCHABLE)
def SCRIPT_ENTRY(): """Entry point of this code if launched as a script.""" if not is_plugin(): if not is_installed(): kw.msg(("%s: Available commands:\n" "[+] \"install_plugin()\" - install script to ida_userdir/plugins\n") % ( PLUGIN_NAME)) create_mc_widget() return True return False
def apply(self, opnum, path, top_tif, spath): typename = ida_typeinf.print_tinfo('', 0, 0, ida_typeinf.PRTYPE_1LINE, top_tif, '', '') ida_kernwin.msg("User selected %s of type %s\n" % (spath, typename)) if path.empty(): return False vu.cfunc.set_user_union_selection(self.ea, path) vu.cfunc.save_user_unions() return True
def OnSelectLine(self, n): module, symbol, docstring = self.items[n] postfix = " (%s)" % module if len(module) else "" if not len(docstring): ida_kernwin.msg("No documentation available for \"%s\"\n" % symbol) else: f = DocstringViewer("%s%s" % (symbol, postfix), docstring) f.modal = False f.openform_flags = ida_kernwin.PluginForm.FORM_TAB f, args = f.Compile() f.Open() return (ida_kernwin.Choose.NOTHING_CHANGED, )
def OnSelectLine(self, n): data = self.items[n] postfix = " (%s)" % data.mod_name if len(data.mod_name) else "" if not data.doc_str: ida_kernwin.msg("No documentation available for \"%s\"\n" % data.sym_name) else: f = DocstringViewer("%s%s" % (data.sym_name, postfix), data.doc_str) f.modal = False f.openform_flags = ida_kernwin.PluginForm.WOPN_TAB f, args = f.Compile() f.Open() return (ida_kernwin.Choose.NOTHING_CHANGED, )
def create_mc_widget(): """Checks minimum requirements for the script/plugin to be able to run. Displays microcode or in case of failure, displays error message. This function acts as the main entry point that is invoked if the code is run as a script or as a plugin.""" if not is_compatible(): kw.msg("%s: Unsupported IDA / Hex-rays version\n" % (PLUGIN_NAME)) return False success, message = show_microcode() output = kw.msg if success else kw.warning output("%s: %s\n" % (PLUGIN_NAME, message)) return success
def load_file(li, _a, _b): # set processor to 6502 if (ph.id != PLFM_6502): msg("Nintendo Entertainment System ROM detected: setting processor type to M6502.\n" ) set_processor_type("M6502", SETPROC_LOADER_NON_FATAL) try: return load_ines_file(li) except: import traceback traceback.print_exc() return 0
def OnViewKeydown(self, key, state): c = chr(key & 0xFF) if c == 'C': self.center_node = not self.center_node ida_kernwin.msg("%s: centering %sabled\n" % (PLUGIN_NAME, "en" if self.center_node else "dis")) elif c == 'D': self.debug = (self.debug + 1) % 3 ida_kernwin.msg("%s: debug %d\n" % (PLUGIN_NAME, self.debug)) self.redraw = True self.Refresh() return True
def __init__(self, method_va, segment_map): """Do not instantiate directly Arguments: method_va segment_map """ msg("Found method at virtual address: 0x%x\n" % method_va) self.method_va = method_va self.segment_map = segment_map self.name_pointer = get_qword(method_va) self.method_type = get_qword(method_va + self.OBJC_METHOD_TYPE_OFFSET) self.method_pointer_va = method_va + self.OBJC_METHOD_IMP_OFFSET self.method_pointer = get_qword(self.method_pointer_va) self.patched_xrefs = [] objc_selrefs = segment_map["__objc_selrefs"] objc_msgrefs = segment_map["__objc_msgrefs"] objc_const = segment_map["__objc_const"] msg("Method name: %s\n" % get_func_name(self.method_pointer)) is_msg_ref, selector_ref, const_ref_count = self.get_xref( objc_selrefs, objc_msgrefs, objc_const) self.is_msg_ref = is_msg_ref self.const_ref_count = const_ref_count if not selector_ref: msg("No selref found.\n") self.selector_ref = None return if const_ref_count == 1: #We can only work with unambiguous situations where there is exactly one const reference #to the selector. self.selector_ref = selector_ref else: msg("Selector ref count not exactly 1. Potentially ambiguous: %d" % const_ref_count) # Otherwise this same selector is used by more than one class. (Or none at all) self.selector_ref = None return self.sel_ref_va = self.selector_ref.frm if is_msg_ref: # adjust pointer to beginning of message ref struct to get xrefs self.sel_ref_va -= POINTER_SIZE msg("selref VA: 0x%X - function VA: 0x%X\n" % (self.sel_ref_va, self.method_pointer)) #Find all the references to this *selref* (note: not the string itself but the selref) #These should precede calls to the method #Patch the references to the selref with a reference to the method implementation self.walk_selector_refs()
def load_chr_rom_bank(li, banknr, address): # todo: add support for PPU # this function currently is disabled, since no # segment for the PPU is created msg("The loader was trying to load a CHR bank but the PPU is not supported yet.\n" ) return if ((banknr == 0) or (hdr.chr_page_count_8k == 0)): return # this is the file offset to begin reading pages from offset = INES_HDR_SIZE + \ (TRAINER_SIZE if INES_MASK_TRAINER(hdr.rom_control_byte_0) else 0) + \ PRG_PAGE_SIZE * hdr.prg_page_count_16k + \ (banknr - 1) * CHR_ROM_BANK_SIZE # load page from ROM file into segment msg("mapping CHR-ROM page %02d to %08x-%08x (file offset %08x) ..", banknr, address, address + CHR_PAGE_SIZE, offset) if (file2base(li, offset, address, address + CHR_ROM_BANK_SIZE, FILEREG_PATCHABLE) == 1): msg("ok\n") else: msg("failure (corrupt ROM image?)\n")
def install_plugin(): """Installs script to IDA userdir as a plugin.""" dst = get_dest_filename() src = SELF if is_installed(): btnid = kw.ask_yn(kw.ASKBTN_NO, "File exists:\n\n%s\n\nReplace?" % dst) if btnid is not kw.ASKBTN_YES: return False else: btnid = kw.ask_yn(kw.ASKBTN_NO, "This plugin is about to be installed to:\n\n%s\n\nInstall now?" % dst) if btnid is not kw.ASKBTN_YES: return False usrdir = os.path.dirname(dst) kw.msg("%s: copying script from \"%s\" to \"%s\" ..." % (PLUGIN_NAME, src, usrdir)) if not os.path.exists(usrdir): try: os.path.makedirs(usrdir) except OSError as e: if e.errno != errno.EEXIST: kw.msg("failed (mkdir)!\n") return False try: shutil.copy(src, dst) except: kw.msg("failed (copy)!\n") return False kw.msg(("done\n" "Plugin installed - please restart this instance of IDA.\n")) return True
def _update_key(self, buffers): if buffers: tmp = '' for mapped, buf in buffers: tmp += buf if mapped else '' self.size = len(tmp) c = Counter(tmp.replace("\x00","")) mc = c.most_common(1) if len(mc): cur, self.occurence = mc[0] cur = ord(cur) if cur != self.key: msg('Key %02Xh - %d/%d (%.2f%%)\n' % (cur, self.occurence, self.size, float(self.occurence)/float(self.size)*100.0)) self.key = cur
def save_trainer_as_blob(li): node = ida_netnode.netnode() if (not INES_MASK_TRAINER(hdr.rom_control_byte_0)): return False li.seek(INES_HDR_SIZE) buffer = li.read(TRAINER_SIZE) if (not node.create("$ Trainer")): return False if (not node.setblob(buffer, TRAINER_SIZE, 0, 'I')): msg("Could not store trainer to netnode!\n") return True
def write(self, text): # NB: in case 'text' is Unicode, msg() will decode it # and call msg() to print it ida_kernwin.msg(text)