def exec_sync(func, *args, **kwargs): """ Wrap around the execute_sync API to perform a call on the function ``func`` in the main thread. If a function is not marked as THREAD_SAFE in the headers, then it can only be called from the main thread of IDA. .. todo:: unit test :param func: The function to call. :type func: Python Callable :param args: Arguments to ``func`` :param kwargs: Keyworded arguments to ``func`` :param MFF_FLAG: Flag describing the operation on the database. Default ``MFF_READ``. Can be ``MFF_FAST``, ``MFF_READ``, ``MFF_WRITE`` or ``MFF_NOWAIT`` (from ida_kernwin). :type MFF_FLAG: int :return: The return of ``func`` """ MFF_FLAG = kwargs.get("MFF_FLAG", ida_kernwin.MFF_READ) ret = {"ret": None} def handle(): ret["ret"] = func(*args, **kwargs) return 1 ida_kernwin.execute_sync(handle, MFF_FLAG) return ret["ret"]
def prepare_debug(self): def get_processes_list(): self.pis = ida_idd.procinfo_vec_t() ida_dbg.get_processes(self.pis) return 1 c = 0 found_pid = False while not found_pid: c = (c + 1) % 5 self.sinOut.emit("finding process: [%s]" % self.filename + ('.' * c).ljust(5, " ")) ida_kernwin.execute_sync(MainCallable(get_processes_list), \ ida_kernwin.MFF_FAST) for proc in self.pis: proc_name = proc.name.split(" ")[1] idx = proc_name.rfind("/") if idx != -1: proc_name = proc_name[idx + 1:] if self.filename == proc_name: self.target_pid = proc.pid found_pid = True break if not found_pid: self.sleep(1)
def req_DelNodesInfos(self, *nodes): w = self.w def f(): self.log("Deleting nodes infos..") w.DelNodesInfos(*nodes) ida_kernwin.execute_sync(f, ida_kernwin.MFF_FAST)
def req_SetNodeInfo(self, node, info, flags): w = self.w def f(): self.log("Setting node info..") w.SetNodeInfo(node, info, flags) ida_kernwin.execute_sync(f, ida_kernwin.MFF_FAST)
def req_SetCurrentRendererType(self, switch_to): w = self.w def f(): self.log("Switching to %s" % switch_to) w.SetCurrentRendererType(switch_to) ida_kernwin.execute_sync(f, ida_kernwin.MFF_FAST)
def enqueue(*args, **kwargs): def partial_callback(): # Store return value inside main thread, return a positive value self.__ret = callback(*args, **kwargs) return 1 # enqueue partial_callback to be executed by IDA's main thread is needed ida_kernwin.execute_sync(partial_callback, self.reqf) # retreive return value and set sync variable to None for safety ret, self.__ret = self.__ret, None return ret
def load(self, force=False): """ Actually does :code:`ida_loaders.load_plugin(paths)`, and updates IDAUSR variable. """ if not force and self.path in os.environ.get('IDAUSR', ''): # Already loaded, just update sys.path for python imports sys.path.append(self.path) return env = str(_idausr_add(os.getenv('IDAUSR'), self.path)) # XXX: find a more efficient way to ensure dependencies errors = [] for dependency in self.metadata().get('dependencies', {}).keys(): dep = LocalPackage.by_name(dependency) if not dep: errors.append('Dependency not found: %r' % dependency) continue dep.load() if errors: for error in errors: log.error(error) return def handler(): assert isinstance(threading.current_thread(), threading._MainThread) # Load plugins immediately # processors / loaders will be loaded on demand sys.path.append(self.path) # Update IDAUSR variable invalidate_idausr() putenv('IDAUSR', env) # Immediately load compatible plugins self._find_loadable_modules('plugins', ida_loader.load_plugin) # Find loadable processor modules, and if exists, invalidate cached process list (proccache). invalidates = [] self._find_loadable_modules('procs', invalidates.append) if invalidates: invalidate_proccache() ida_kernwin.execute_sync(handler, ida_kernwin.MFF_FAST)
def load(self, force=False): """ Actually does :code:`ida_loaders.load_plugin(paths)`, and updates IDAUSR variable. """ if not force and self.path in ida_diskio.get_ida_subdirs(''): # Already loaded, just update sys.path for python imports if self.path not in sys.path: sys.path.append(self.path) return # XXX: find a more efficient way to ensure dependencies errors = [] for dependency in self.info().get('dependencies', {}).keys(): dep = LocalPackage.by_name(dependency) if not dep: errors.append('Dependency not found: %r' % dependency) continue dep.load() if errors: for error in errors: log.error(error) return def handler(): # Load plugins immediately # processors / loaders will be loaded on demand if self.path not in sys.path: sys.path.append(self.path) # Update IDAUSR variable idausr_add(self.path) # Immediately load compatible plugins self._find_loadable_modules('plugins', ida_loader.load_plugin) # Find loadable processor modules, and if exists, invalidate cached process list (proccache). invalidates = [] self._find_loadable_modules('procs', invalidates.append) if invalidates: invalidate_proccache() # Run in main thread ida_kernwin.execute_sync(handler, ida_kernwin.MFF_FAST)
def wrapper(*args, **kwargs): output = [None] # # this inline function definition is technically what will execute # in the context of the main thread. we use this thunk to capture # any output the function may want to return to the user. # def thunk(): output[0] = function(*args, **kwargs) return 1 if is_mainthread(): thunk() else: ida_kernwin.execute_sync(thunk, sync_type) # return the output of the synchronized execution return output[0]
def fit_widget_a(): def do_fit_widget_a(): ida_graph.viewer_fit_window(widget_a) ida_kernwin.execute_sync(do_fit_widget_a, ida_kernwin.MFF_FAST)
def handle(self): idaapi.msg("Accepting connection from {}\n".format( self.client_address[0])) while True: try: data = self.request.recv(1024).decode() if len(data) == 0: break command = data.strip().split(' ') if len(command) == 0: continue idaapi.msg('recv> ' + ' '.join(command) + '\n') result = False if command[0] == 'attachWithExit': if ida_kernwin.execute_sync(ida_dbg.is_debugger_on, 0): ida_kernwin.execute_sync(ida_dbg.exit_process, 0) if len(command) == 1: pid = ida_kernwin.execute_sync( lambda: ida_dbg.attach_process(-1), 0) == 1 else: pid = ida_kernwin.execute_sync( lambda: ida_dbg.attach_process(int(command[1])), 0) == 1 result = (pid == 1) elif command[0] == 'continue': result = ida_kernwin.execute_sync(ida_dbg.continue_process, 0) == 1 elif command[0] == 'detach': result = ida_kernwin.execute_sync(ida_dbg.detach_process, 0) elif command[0] == 'attach': if len(command) == 1: pid = ida_kernwin.execute_sync( lambda: ida_dbg.attach_process(-1), 0) == 1 else: pid = ida_kernwin.execute_sync( lambda: ida_dbg.attach_process(int(command[1])), 0) == 1 result = (pid == 1) elif command[0] == 'exit': result = ida_kernwin.execute_sync(ida_dbg.exit_process, 0) elif command[0] == 'isDebugging': result = ida_kernwin.execute_sync(ida_dbg.is_debugger_on, 0) idaapi.msg('res> ' + str(result) + '\n') if result: self.request.sendall(b'T\n') else: self.request.sendall(b'F\n') except: traceback.print_exc() idaapi.msg("Closing connection from {}\n".format( self.client_address[0]))