def run(self, arg): """ Ask user for BAP args to pass, BIR attributes to print; and run BAP. Allows users to also use {screen_ea} in the BAP args to get the address at the location pointed to by the cursor. """ args_msg = "Arguments that will be passed to `bap'" args = idaapi.askstr(ARGS_HISTORY, '--passes=', args_msg) if args is None: return attr_msg = "A comma separated list of attributes,\n" attr_msg += "that should be propagated to comments" attr_def = self.recipes.get(args, '') attr = idaapi.askstr(ATTR_HISTORY, attr_def, attr_msg) if attr is None: return # store a choice of attributes for the given set of arguments # TODO: store recipes in IDA's database self.recipes[args] = attr ea = idc.ScreenEA() attrs = [] if attr != '': attrs = attr.split(',') analysis = BapScripter(args, attrs) analysis.on_finish(lambda bap: self.load_script(bap, ea)) analysis.run()
def activate_conda_env(envs=None, env=None, interactive=True): folder = "Scripts" if os.name == "nt" else "bin" # Get env if env == None: if envs == None: envs = os.environ.get("ANACONDA_ENVS") if not envs and interactive: envs = idaapi.askstr(0, root_path(), "Anaconda envs dir") # Check envs if not envs: raise ValueError("No Conda base envs dir") if not os.path.isdir(envs): raise ValueError("This path is not a dir: " + envs) env = os.environ.get("CONDA_DEFAULT_ENV") if not env and interactive: env = idaapi.askstr(0, envs, "Select a env") # Check env if not env: raise ValueError("No Conda env") if not os.path.isabs(env): env = os.path.join(envs, env) if not os.path.isdir(env): raise ValueError("This path is not a dir: " + env) # Patch PATH old_os_path = os.environ['PATH'] os.environ['PATH'] = env + os.pathsep + os.path.join(env, folder) + os.pathsep + old_os_path # Compose new system path if sys.platform == 'win32': site_packages = os.path.join(env, 'Lib', 'site-packages') else: site_packages = os.path.join(env, 'lib', 'python%s' % sys.version[:3], 'site-packages') # Patch system path prev_sys_path = list(sys.path) import site site.addsitedir(site_packages) sys.real_prefix = sys.prefix sys.prefix = env # Move the added items to the front of the path: new_sys_path = [] for item in list(sys.path): if item not in prev_sys_path: new_sys_path.append(item) sys.path.remove(item) sys.path[:0] = new_sys_path return env
def _make_item(self): """ make custom element """ item = [ idaapi.askstr(0, "", "Address"), idaapi.askstr(0, "", "Name"), idaapi.askstr(0, "", "Service"), idaapi.askstr(0, "", "Place"), idaapi.askstr(0, "", "GUID") ] self.n += 1 return item
def activate_virtualenv_env(virtualenv=None, interactive=True): """ Activate a Virtualenv based virtual environment. """ folder = "Scripts" if os.name == "nt" else "bin" if virtualenv == None: virtualenv = os.environ.get("VIRTUAL_ENV") if not virtualenv and interactive: default_virtualenv = os.path.join(idaapi.get_user_idadir(), "virtualenv") virtualenv = idaapi.askstr(0, default_virtualenv, "Select a virtualenv") if not virtualenv: raise ValueError("No active virtualenv") if not os.path.isdir(virtualenv): raise ValueError("This path is not a dir: " + virtualenv) virtualenv_script = os.path.join(virtualenv, folder, "activate_this.py") if not os.path.isfile(virtualenv_script): raise ValueError('Enable to find "' + folder + os.sep + 'activate_this.py" in virtualenv: ' + virtualenv) with open(virtualenv_script) as infile: exec(infile.read(), dict(__file__=virtualenv_script)) return virtualenv
def ensure_git_globals(self): user_name = self.repo.config_get_string("user.name") user_email = self.repo.config_get_string("user.email") if user_name in [None, ""]: new_username = None while new_username is None: new_username = idaapi.askstr(0, "username", "Entrer git user.name") self.repo.config_set_string("user.name", new_username) if user_email in [None, ""]: new_user_email = None while new_user_email is None: new_user_email = idaapi.askstr(0, "username@localdomain", "Entrer git user.email") self.repo.config_set_string("user.email", new_user_email)
def bulk_prefix(): """ Prefix the Functions window selection with a user defined string. """ # prompt the user for a prefix to apply to the selected functions tag = idaapi.askstr(0, PREFIX_DEFAULT, "Function Tag") # the user closed the window... ignore if tag == None: return # the user put a blank string and hit 'okay'... notify & ignore elif tag == '': idaapi.warning("[ERROR] Tag cannot be empty [ERROR]") return # # loop through all the functions selected in the 'Functions window' and # apply the user defined prefix tag to each one. # for func_name in get_selected_funcs(): # ignore functions that already have the specified prefix applied if func_name.startswith(tag): continue # apply the user defined prefix to the function (rename it) new_name = '%s%s%s' % (str(tag), PREFIX_SEPARATOR, func_name) func_addr = idaapi.get_name_ea(idaapi.BADADDR, func_name) idaapi.set_name(func_addr, new_name, idaapi.SN_NOWARN) # refresh the IDA views refresh_views()
def find_hash(*args): # read le hash needle = idaapi.askstr(0, "ERROR", "Hash value") if needle is None or needle == "ERROR" or len(needle) > 8: idaapi.warning("Bad input, please specify a 8 bytes hash") return fHash(needle) return
def activate(self): new_type_declaration = idaapi.askstr(0x100, self.type_name, "Enter type:") result = idc.parse_decl(new_type_declaration, 0) if result is None: return _, tp, fld = result tinfo = idaapi.tinfo_t() tinfo.deserialize(idaapi.cvar.idati, tp, fld, None) self.tinfo = tinfo self.is_array = False
def activate_conda_env(base=None, env=None, interactive=True): """ Activate a Conda based virtual environment. """ folder = "Scripts" if os.name == "nt" else "bin" # Get env if env == None: env = os.environ.get("CONDA_PREFIX") if not env and interactive: root_path = os.path.abspath(os.sep) env = idaapi.askstr(0, root_path, "Select a env") # Check env if not env: raise ValueError("No active Conda env") if not os.path.isdir(env): raise ValueError("This path is not a dir: " + env) ### # Based on the virtualenv script 'activate_this.py' ### # Patch PATH old_os_path = os.environ['PATH'] os.environ['PATH'] = env + os.pathsep + os.path.join( env, folder) + os.pathsep + old_os_path # Compose new system path if sys.platform == 'win32': site_packages = os.path.join(env, 'Lib', 'site-packages') else: site_packages = os.path.join(env, 'lib', 'python%s' % sys.version[:3], 'site-packages') # Patch system path prev_sys_path = list(sys.path) import site site.addsitedir(site_packages) sys.real_prefix = sys.prefix sys.prefix = env # Move the added items to the front of the path: new_sys_path = [] for item in list(sys.path): if item not in prev_sys_path: new_sys_path.append(item) sys.path.remove(item) sys.path[:0] = new_sys_path return env
def _rename_ea_requested(self, addr, name_idx): old_name = name_idx.data() if idaapi.IDA_SDK_VERSION >= 700: new_name = idaapi.ask_str(str(old_name), 0, 'New name:') else: new_name = idaapi.askstr(0, str(old_name), 'New name:') if new_name is None: return self._rename(addr, new_name) renamed_name = idaapi.get_ea_name(addr) name_idx.model().setData(name_idx, renamed_name)
def __init__(self, addr, kind): super(PropagateTaint,self).__init__() # If a user is not fast enough in providing the answer # IDA Python will popup a modal window that will block # a user from providing the answer. idaapi.disable_script_timeout() engine = idaapi.askstr(ENGINE_HISTORY, self.ENGINE, ask_engine) \ or self.ENGINE depth = idaapi.asklong(self.DEPTH, ask_depth) \ or self.DEPTH # don't ask for the loop depth as a user is already annoyed. loop_depth = self.LOOP_DEPTH self.action = 'propagating taint from {:s}0x{:X}'.format( '*' if kind == 'ptr' else '', addr) propagate = 'run' if engine == 'primus' else 'propagate-taint' self.passes = ['taint', propagate, 'map-terms','emit-ida-script'] self.script = self.tmpfile('py') scheme = self.tmpfile('scm') stdin=self.tmpfile('stdin') stdout=self.tmpfile('stdout') for (pat,color) in patterns: scheme.write('(({0}) (color {1}))\n'.format(pat,color)) scheme.close() name = idc.GetFunctionName(addr) self.args += [ '--taint-'+kind, '0x{:X}'.format(addr), '--passes', ','.join(self.passes), '--map-terms-using', scheme.name, '--emit-ida-script-attr', 'color', '--emit-ida-script-file', self.script.name ] if engine == 'primus': self.args += [ '--run-entry-points={}'.format(name), '--primus-limit-max-length={}'.format(depth), '--primus-limit-max-visited={}'.format(loop_depth), '--primus-promiscuous-mode', '--primus-greedy-scheduler', '--primus-propagate-taint-from-attributes', '--primus-propagate-taint-to-attributes', '--primus-lisp-channel-redirect=<stdin>:{0},<stdout>:{1}'.format( stdin.name, stdout.name) ]
def activate(self, ctx=idaapi.action_activation_ctx_t): if not self.sync_on: # Get the name: name = idaapi.askstr(0, self.name, 'Override idb name:') if not name: return 1 self.name = name self.init_broker() else: self.smooth_kill() # Swap state self.sync_on = not self.sync_on idaapi.update_action_icon(ctx.action, self.icon) return 1
def recursive_prefix(addr): """ Recursively prefix a function tree with a user defined string. """ func_addr = idaapi.get_name_ea(idaapi.BADADDR, idaapi.get_func_name(addr)) if func_addr == idaapi.BADADDR: idaapi.msg("Prefix: 0x%08X does not belong to a defined function\n" % addr) return # NOTE / COMPAT: # prompt the user for a prefix to apply to the selected functions if using_ida7api: tag = idaapi.ask_str(PREFIX_DEFAULT, 0, "Function Tag") else: tag = idaapi.askstr(0, PREFIX_DEFAULT, "Function Tag") # the user closed the window... ignore if tag == None: return # the user put a blank string and hit 'okay'... notify & ignore elif tag == '': idaapi.warning("[ERROR] Tag cannot be empty [ERROR]") return # recursively collect all the functions called by this function nodes_xref_down = graph_down(func_addr, path=set([])) # graph_down returns the int address needs to be converted tmp = [] tmp1 = '' for func_addr in nodes_xref_down: tmp1 = idaapi.get_func_name(func_addr) if tmp1: tmp.append(tmp1) nodes_xref_down = tmp # prefix the tree of functions for rename in nodes_xref_down: func_addr = idaapi.get_name_ea(idaapi.BADADDR, rename) if tag not in rename: idaapi.set_name(func_addr, '%s%s%s' % (str(tag), PREFIX_SEPARATOR, rename), idaapi.SN_NOWARN) # refresh the IDA views refresh_views()
def __init__(self, addr, kind): super(PropagateTaint, self).__init__() # If a user is not fast enough in providing the answer # IDA Python will popup a modal window that will block # a user from providing the answer. idaapi.disable_script_timeout() engine = idaapi.askstr(ENGINE_HISTORY, self.ENGINE, ask_engine) \ or self.ENGINE depth = idaapi.asklong(self.DEPTH, ask_depth) \ or self.DEPTH # don't ask for the loop depth as a user is already annoyed. loop_depth = self.LOOP_DEPTH self.action = 'propagating taint from {:s}0x{:X}'.format( '*' if kind == 'ptr' else '', addr) propagate = 'run' if engine == 'primus' else 'propagate-taint' self.passes = ['taint', propagate, 'map-terms', 'emit-ida-script'] self.script = self.tmpfile('py') scheme = self.tmpfile('scm') stdin = self.tmpfile('stdin') stdout = self.tmpfile('stdout') for (pat, color) in patterns: scheme.write('(({0}) (color {1}))\n'.format(pat, color)) scheme.close() name = idc.GetFunctionName(addr) self.args += [ '--taint-' + kind, '0x{:X}'.format(addr), '--passes', ','.join(self.passes), '--map-terms-using', scheme.name, '--emit-ida-script-attr', 'color', '--emit-ida-script-file', self.script.name ] if engine == 'primus': self.args += [ '--run-entry-points={}'.format(name), '--primus-limit-max-length={}'.format(depth), '--primus-limit-max-visited={}'.format(loop_depth), '--primus-promiscuous-mode', '--primus-greedy-scheduler', '--primus-propagate-taint-from-attributes', '--primus-propagate-taint-to-attributes', '--primus-lisp-channel-redirect=<stdin>:{0},<stdout>:{1}'. format(stdin.name, stdout.name) ]
def main(): analyser = Analyser() if analyser.valid: analyser.print_all() analyser.analyse_all() if not analyser.valid: analyser.arch = idaapi.askstr( 0, "x86 / x64", "Set architecture manually (x86 or x64)") if not (analyser.arch == "x86" or analyser.arch == "x64"): return False if (analyser.arch == "x86"): analyser.BOOT_SERVICES_OFFSET = BOOT_SERVICES_OFFSET_x86 if (analyser.arch == "x64"): analyser.BOOT_SERVICES_OFFSET = BOOT_SERVICES_OFFSET_x64 analyser.print_all() analyser.analyse_all() return True
def run(self, arg): try: self._data = dict() fn = idaapi.get_func(idaapi.get_screen_ea()) if idaapi.IDA_SDK_VERSION >= 700: orig_name = idaapi.get_func_name(idaapi.get_screen_ea()) addr_str = '{:x}'.format(self.start_ea_of(fn)) print("checking function start addr: ", addr_str) #set default name if orig_name.lower().find(addr_str): default_name = orig_name else: default_name = orig_name + '_' + addr_str #append current function address as sufix as default user_name = idaapi.ask_str(default_name, 0, 'New name:') else: user_name = idaapi.askstr( 0, default_name, 'New name:') #jeanfixme: check old version support if user_name == '': return if orig_name == user_name: return #if len(fn_an['math']) < self._MIN_MAX_MATH_OPS_TO_ALLOW_RENAME: jeanfixme: check the max length can be set here force_name(self.start_ea_of(fn), user_name) print("rename \"" + str(orig_name) + "\" to " + str(user_name)) user_prefix = user_name.lower().replace(addr_str, '') query = 'Use \"' + user_prefix + '\" to rename the callers\' names' #yesno= idaapi.askyn_c(1, query) jeanfixme: check how to interact with user yesno = idaapi.ask_str( "yes", 0, query) #jeanfixme: check how to interact with user #user the rename the parrents if yesno == 'yes': #rename the parent print "start rename parents.." self.rename_parents(fn, user_prefix, 1) except: idaapi.msg('Ancestor RE: error: %s\n' % traceback.format_exc())
def main(): idc.auto_wait() analyser = Analyser() if analyser.valid: analyser.print_all() analyser.analyse_all() if not analyser.valid: analyser.arch = idaapi.askstr( 0, 'x86 / x64', 'Set architecture manually (x86 or x64)') if not (analyser.arch == 'x86' or analyser.arch == 'x64'): return False if (analyser.arch == 'x86'): analyser.BOOT_SERVICES_OFFSET = BOOT_SERVICES_OFFSET_x86 if (analyser.arch == 'x64'): analyser.BOOT_SERVICES_OFFSET = BOOT_SERVICES_OFFSET_x64 analyser.print_all() analyser.analyse_all() return True
def IssueCommand(self): s = idaapi.askstr(0, self.last_cmd, "Please enter a debugger command") if not s: return # Save last command self.last_cmd = s # Add it using a different color self.AddLine("debugger>" + idaapi.COLSTR(s, idaapi.SCOLOR_VOIDOP)) try: r = SendDbgCommand(s).split("\n") for s in r: self.AddLine(idaapi.COLSTR(s, idaapi.SCOLOR_LIBNAME)) except: self.AddLine(idaapi.COLSTR("Debugger is not active or does not export SendDbgCommand()", idaapi.SCOLOR_ERROR)) self.Refresh()
def main(): idc.auto_wait() analyser = Analyser() if analyser.valid: analyser.print_all() analyser.analyse_all() if not analyser.valid: analyser.arch = idaapi.askstr( 0, "x86 / x64", "Set architecture manually (x86 or x64)" ) if analyser.arch == "x86": analyser.BOOT_SERVICES_OFFSET = BOOT_SERVICES_OFFSET_x86 elif analyser.arch == "x64": analyser.BOOT_SERVICES_OFFSET = BOOT_SERVICES_OFFSET_x64 else: return False analyser.print_all() analyser.analyse_all() return True
def run(): analyser = Analyser() if analyser.valid: analyser.print_all() analyser.analyse_all() if not analyser.valid: analyser.arch = idaapi.askstr( 0, "x86 / x64", "Set architecture manually (x86 or x64)") if not (analyser.arch == "x86" or analyser.arch == "x64"): return False if (analyser.arch == "x86"): analyser.BOOT_SERVICES_OFFSET = BOOT_SERVICES_OFFSET_x86 if (analyser.arch == "x64"): analyser.BOOT_SERVICES_OFFSET = BOOT_SERVICES_OFFSET_x64 analyser.print_all() analyser.analyse_all() if len(analyser.Protocols["All"]): wind = ProtsWindow("Protocols", analyser, nb=10) wind.show() return True
def activate_virtualenv_env(virtualenv=None, interactive=True): folder = "Scripts" if os.name == "nt" else "bin" if virtualenv == None: virtualenv = os.environ.get("VIRTUAL_ENV") if not virtualenv and interactive: default_virtualenv = os.path.join(idaapi.get_user_idadir(), "virtualenv") virtualenv = idaapi.askstr(0, default_virtualenv, "Select a virtualenv") if not virtualenv: raise ValueError("No virtualenv env") if not os.path.isdir(virtualenv): raise ValueError("This path is not a dir: " + virtualenv) virtualenv_script = os.path.join(virtualenv, folder, "activate_this.py") if not os.path.isfile(virtualenv_script): raise ValueError('Enable to find "' + folder + os.sep + 'activate_this.py" in virtualenv: ' + virtualenv) execfile(virtualenv_script, dict(__file__=virtualenv_script)) return virtualenv
def ask_for_input_dir(): input_dir = idaapi.askstr(0, "pinnacle_results", "Directory containing Pinnacle results") if input_dir is None: idaapi.msg("You must specify an input directory\n") return -1 else: if not os.path.exists(input_dir): idaapi.msg("%s does not exist\n" % input_dir) return -1 elif not os.path.isdir(input_dir): idaapi.msg("%s is not a directory\n" % input_dir) return -1 elif not os.access(input_dir, os.R_OK): idaapi.msg("Insufficient permissions to read %s\n" % \ input_dir) return -1 else: idaapi.msg("Processing results from %s\n" % input_dir) return input_dir
def main(): path_before = idaapi.askstr( 0, "", "Please give me path of type information file").strip() f_before = open(path_before, "rb") if not len(path_before) or not f_before: raise Exception("Error on opening the type information file") typed_inst_info = json.loads(f_before.read()) f_before.close() # Optimize inst_type """ Optimization idea: 1. Accesses to memory region looks like: RVA1 : Access to [REG1 + IMM1] RVA2 : Access to [REG2 + IMM2] Note: RVA1 is executed prior to RVA2 2. If both accesses points same area of same object, we do not have to verify accesses from RVA2 => To avoid redundant checks 3. How we know whether both accesses points same area of same object? => (a) Both accesses points same area(s) => condition (a) tells us RVA1 and RVA2 points same *area* => (b) We have to ensure REG1 == REG2 => (c) The value of IMM1/IMM2 are not important, but we have to ensure these are constant => conditions (b) and (c) tell us RVA1 and RVA2 points same *object* """ for rva in typed_inst_info.keys(): typed_inst_info[int(rva)] = typed_inst_info[rva] del typed_inst_info[rva] rvas = typed_inst_info.keys() rvas.sort() will_be_removed_rvas = [] rva1 = None for rva1_idx in xrange(len(rvas)): print("{0}/{1}".format(rva1_idx, len(rvas))) rva1 = rvas[rva1_idx] if len(typed_inst_info[rva1]) != 1: continue for rva2_idx in xrange(rva1_idx + 1, len(rvas)): rva2 = rvas[rva2_idx] if rva2 in will_be_removed_rvas: continue # We consider instruction with only one mem-ref (for PoC) if len(typed_inst_info[rva2]) != 1: continue assert (rva2 != rva1) bbl_rva1 = GetBBLFromEA(rva1) if bbl_rva1.startEA > rva2 or rva2 >= bbl_rva1.end_ea: # rva1 and rva2 doesn't exist in same bbl break assert (rva1 <= rva2) possible_identifier1 = RetrievePossibleIdentifiersOfRVA( rva1, typed_inst_info) possible_identifier2 = RetrievePossibleIdentifiersOfRVA( rva2, typed_inst_info) if possible_identifier1 != possible_identifier2: # Area identifiers doesn't matched :( continue sym1 = ExecuteSymbolicSingleStep(rva1) sym2 = ExecuteSymbolicSingleStep(rva2) reg1 = ExtractMemAccessBaseReg(sym1.keys() + sym1.values()) reg2 = ExtractMemAccessBaseReg(sym2.keys() + sym2.values()) if reg1 == None or reg2 == None: # Failed to extract reg continue if reg1 != reg2: # Object doesn't matched :( continue state = INIT_REG cur_ea = rva1 while cur_ea < rva2: state = ExecuteSymbolicSingleStep(cur_ea) cur_ea = idc.NextHead(cur_ea) if ExprId(reg1, 64) in state.keys(): if state[ExprId(reg1, 64)] != ExprId(reg1 + "_init", 64): # reg has been overwritten continue will_be_removed_rvas.append(rva2) print("%08x %08x" % (rva1, rva2)) will_be_removed_rvas = list(set(will_be_removed_rvas)) will_be_removed_rvas.sort() print("{0} / {1}".format(len(will_be_removed_rvas), len(rvas))) for will_be_removed_rva in will_be_removed_rvas: del typed_inst_info[will_be_removed_rva] f_after = open("optimized_{0}".format(path_before), "wb") f_after.write(json.dumps(typed_inst_info)) f_after.close() return
def readline(self): return idaapi.askstr(0, '', 'Help topic?')
def repo_init(self, ask_for_remote=True): # create git try: self.repo = ya.GitRepo(".") self.repo.init() self.ensure_git_globals() # add current IDB to repo self.repo.add_file(self.idb_filename) # create an initial commit with IDB self.repo.commit("Initial commit") if IDA_RUNNING and IDA_IS_INTERACTIVE: # add a remote to git repo if ask_for_remote: url = idaapi.askstr(0, "ssh://gitolite@repo/", "Specify a remote origin :") else: url = None if url not in [None, ""]: self.repo.create_remote("origin", url) if not url.startswith("ssh://"): if not os.path.exists(url): if idaapi.askyn_c( True, "The target directory doesn't exist, do you want to create it ?" ) == 1: os.mkdir(url) temp_repo = ya.GitRepo(url) temp_repo.init_bare() # copy idb to local idb copy_idb_to_local_file() # push master to remote self.push_origin_master() return except Exception as exc: logger.error("an error occured during repo_init, error :%s" % exc) traceback.print_exc() if idaapi.askyn_c(True, "could not initialised repo, try again ?") == 1: while True: try: url = idaapi.askstr(0, "ssh://gitolite@repo/", "Specify a remote origin :") if url is not None: url = url.strip() while url.endswith("/"): url = url[:-1] self.repo.remove_remote("origin") self.repo.create_remote("origin", url) # push master to remote self.push_origin_master() return except Exception as exc: logger.error( "an error occured during repo_init, error :%s" % exc) traceback.print_exc() if idaapi.askyn_c( True, "could not initialised repo, try again ?" ) != 1: raise exc raise exc