def call_execute_sync_and_get_result( prepped_function, execute_sync_flag=idaapi.MFF_WRITE ): """ we use MFF_WRITE to make sure that regardless of whether the operation reads/writes/ignores the database, it'll be fine """ # if the caller has deliberately specified no execute_sync flag, don't call it - just call the prepped function directly and return the result if execute_sync_flag is None: return prepped_function() # where we get our result return_object = WrapperReturn() # bind the prepped function bound with args into the callable wrapper we'll pass to execute sync, along with the return object prepped_wrapper = functools.partial( wrapper_execute_on_main_thread, prepped_function, return_object ) # run it on the main thread idaapi.execute_sync(prepped_wrapper, execute_sync_flag) if return_object.exception is not None: # something went wrong. reraise the exception on this thread, so it'll get passed back raise return_object.exception # and we're done! return return_object.result
def set_block_color(addr, color): def fun(addr, color): cb = sark.CodeBlock(addr) if cb: cb.color = color idaapi.execute_sync(partial(fun, addr, color), idaapi.MFF_WRITE)
def wrapper(*a, **kw): rv = [] error = [] def work(): try: result = f(*a, **kw) rv.append(result) except Exception as e: error.append(e) with mutex: flags = idaapi.MFF_WRITE if f == idc.SetColor: flags |= idaapi.MFF_NOWAIT rv.append(None) idaapi.execute_sync(work, flags) if error: msg = 'Failed on calling {}.{} with args: {}, kwargs: {}\nException: {}' \ .format(f.__module__, f.__name__, a, kw, str(error[0])) print('[!!!] ERROR:', msg) raise error[0] return rv[0]
def setup_timer(self): """ Setup an IDA timer to trigger regularly the update of data from the server """ def update(): """ Triggers the synchronization event """ if not self.update_event.isSet(): self.update_event.set() if self.kill_event.isSet(): # Unregister the timer if we are killed return -1 return self.delay def ts_setup_timer(): """ Thread safe wrapper for setting up the sync callback """ idaapi.register_timer(self.delay, update) if not self.timer_setup_flag: idaapi.execute_sync(ts_setup_timer, idaapi.MFF_FAST) self.timer_setup_flag = True
def reset_block_colors(f): def fun(): cbs = sark.codeblocks(start=f.startEA, end=f.endEA) for cb in cbs: cb.color = 0xFFFFFF idaapi.execute_sync(fun, idaapi.MFF_WRITE)
def run(self, *args, **kwargs): """ Resume the execution of the target :return: """ action = ResumeAndWaitBreakpoint(idc.WFNE_SUSP, -1) idaapi.execute_sync(action, 0)
def Sync(self, offset, added, removed): """ Sync(offset, added, removed) => None Synchronize debug info with gef. This is an internal function. It is not recommended using it from the command line. """ global _breakpoints, _current_instruction, _current_instruction_color if _current_instruction > 0: idc.SetColor(_current_instruction, CIC_ITEM, _current_instruction_color) base_addr = idaapi.get_imagebase() pc = base_addr + int(offset, 16) _current_instruction = long(pc) _current_instruction_color = GetColor(_current_instruction, CIC_ITEM) idc.SetColor(_current_instruction, CIC_ITEM, 0x00ff00) print("PC @ " + hex(_current_instruction).strip('L')) # post it to the ida main thread to prevent race conditions idaapi.execute_sync(lambda: idc.Jump(_current_instruction), idaapi.MFF_WRITE) cur_bps = set([ idc.GetBptEA(n)-base_addr for n in range(idc.GetBptQty()) ]) ida_added = cur_bps - _breakpoints ida_removed = _breakpoints - cur_bps _breakpoints = cur_bps # update bp from gdb for bp in added: idc.AddBpt(base_addr+bp) _breakpoints.add(bp) for bp in removed: if bp in _breakpoints: _breakpoints.remove(bp) idc.DelBpt(base_addr+bp) return [list(ida_added), list(ida_removed)]
def sync_wrapper(ff, safety_mode): logger.debug('sync_wrapper: {}, {}'.format(ff.__name__, safety_mode)) if safety_mode not in [IDASafety.SAFE_READ, IDASafety.SAFE_WRITE]: error_str = 'Invalid safety mode {} over function {}'\ .format(safety_mode, ff.__name__) logger.error(error_str) raise IDASyncError(error_str) queue = Queue.Queue() def runned(): logger.debug('Inside runned') if not call_stack.empty(): last_func_name = call_stack.get() error_str = ('Call stack is not empty while calling the ' 'function {} from {}').format(ff.__name__, last_func_name) logger.error(error_str) raise IDASyncError(error_str) call_stack.put((ff.__name__)) try: queue.put(ff()) except: queue.put(None) traceback.print_exc(file=sys.stdout) finally: call_stack.get() logger.debug('Finished runned') idaapi.execute_sync(runned, safety_mode) return queue.get()
def get_func_codeblocks(f): cbs = [None] def fun(): cbs[0] = list(sark.codeblocks(start=f.startEA, end=f.endEA)) idaapi.execute_sync(fun, idaapi.MFF_READ) return cbs[0]
def asklong(defval, prompt): res = [None] # Python 2 way to assign outside of a nested function def fun(defval, prompt): res[0] = idc.AskLong(defval, prompt) idaapi.execute_sync(partial(fun, defval, prompt), idaapi.MFF_FAST) return res[0]
def onmsg_safe(key, data, replay=False): def tmp(): try: onmsg(key, data, replay=replay) except Exception as e: print('error during callback for %s: %s' % (data.get('cmd'), e)) traceback.print_exc() idaapi.execute_sync(tmp, MFF_WRITE)
def make_comment(self, address, comment): action = MakeComment(address, comment) idaapi.execute_sync(action, 0) if action.exception: raise Exception else: return action.result
def make_function(self, address): action = MakeFunction(address) idaapi.execute_sync(action, 0) if action.exception: raise Exception else: return action.result
def get_current_codeblock(): cb = [None] def fun(): cb[0] = sark.CodeBlock() idaapi.execute_sync(fun, idaapi.MFF_READ) return cb[0]
def call(*args, **kwargs): holder = [None] # need a holder, because 'global' sucks def trampoline(): holder[0] = val(*args, **kwargs) return 1 idaapi.execute_sync(trampoline, idaapi.MFF_WRITE) return holder[0]
def set_line_color(self, color, address): action = SetLineColor(color, address) idaapi.execute_sync(action, 0) if action.exception: raise Exception else: return action.result
def make_unknown(self, address, size): action = MakeUnknown(address, size) idaapi.execute_sync(action, 0) if action.exception: raise Exception else: return action.result
def edit_function_boundaries(self, start_address, end_address): action = EditFunctionBoundaries(start_address, end_address) idaapi.execute_sync(action, 0) if action.exception: raise Exception else: return action.result
def get_segment_names(seg): names = [] def fun(seg): names.extend([(a, n) for (a, n) in idautils.Names() if seg.startEA <= a < seg.endEA]) idaapi.execute_sync(partial(fun, seg), idaapi.MFF_READ) return names
def remove_breakpoint(self, address, *args, **kwargs): l.debug("ida_target removing breakpoint at %x " % (address)) action = DeleteBreakpointCallable(address) idaapi.execute_sync(action, 0) if action.exception: raise SimConcreteBreakpointError else: return action.result
def wrapper(*args, **kwargs): output = [None] def thunk(): output[0] = function(*args, **kwargs) return 1 if threading.current_thread().name == 'MainThread': thunk() else: idaapi.execute_sync(thunk, sync_type) return output[0]
def call_wrap(*args, **kwargs): # Need a mutable value to store result rv = [None] # Wrapper that binds the args def c(): rv[0] = v(*args, **kwargs) idaapi.execute_sync(c, idaapi.MFF_WRITE) if isinstance(rv[0], types.GeneratorType): return IDAWrapper.gen_wrap(rv[0]) return rv[0]
def exposed_iterate(self, iterator): default = "IDoNotExistButNoReallyISeriouslyDoNotAndCannotExist {}".format(random.randint(0, 65535),) holder = [default] def trampoline(): try: holder[0] = next(iterator) except StopIteration: holder[0] = default return 1 while True: idaapi.execute_sync(trampoline, idaapi.MFF_WRITE) if holder[0] == default: return yield holder[0]
def wrapper(*a, **kw): try: rv = [] def work(): rv.append(f(*a,**kw)) with mutex: flags = idaapi.MFF_WRITE if f == idc.SetColor: flags |= idaapi.MFF_NOWAIT rv.append(None) idaapi.execute_sync(work, flags) return rv[0] except: import traceback traceback.print_exc() raise
def _locked_execution(self,to_lock_function,ida_lock_type): def make_function_waitable(f): def inner(): try: start = time.time() return f() finally: if self.debug: print "execution locked for:",time.time()-start q.put(None) return inner q = Queue.Queue() idaapi.execute_sync(make_function_waitable(to_lock_function),ida_lock_type) q.get()
def disassemble_in_context(self, function_addresses=None, with_ins_comments=True): from jvd.ida.ida_utils import get_all import idaapi # this import cannot be moved to the header since it can # be only imported when running in context res = {} def _get(): res.update( get_all(function_eas=function_addresses, with_blocks=with_ins_comments)) idaapi.execute_sync(_get, idaapi.MFF_FAST) return res
def make_name(): """ Thread safe renaming wrapper """ return idaapi.execute_sync( idc.MakeName(name["address"], name["data"].encode('ascii', 'ignore')), idaapi.MFF_FAST)
def write_memory(self, address, value, *args, **kwargs): """ Writing to memory of the target :param address: The address from where the memory-write should start :param value: The actual value written to memory :type value: str :returns: True on success else False """ l.debug("gdb target write memory at %x value %s " % (address, value.encode("hex"))) action = WriteMemoryCallable(address, value) idaapi.execute_sync(action, 0) if action.exception: raise SimConcreteMemoryError else: return action.written_bytes
def get_mappings(self): action = GetMappings() idaapi.execute_sync(action, 0) if action.exception: raise Exception else: # Building the list of vmmap objects vmmap = [] for module in action.result: vmmap.append( MemoryMap(module.base, module.base + module.size, module.name)) return vmmap
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 # send the synchronization request to IDA idaapi.execute_sync(thunk, sync_flags) # return the output of the synchronized function return output[0]
def wrapper(*a, **kw): try: rv = [] def work(): rv.append(f(*a, **kw)) with mutex: flags = idaapi.MFF_WRITE if f == idc.SetColor: flags |= idaapi.MFF_NOWAIT rv.append(None) idaapi.execute_sync(work, flags) return rv[0] except: import traceback traceback.print_exc() raise
def set_breakpoint(self, address, hardware=False, *args, **kwargs): """Inserts a breakpoint :param bool hardware: Hardware breakpoint :param bool temporary: Temporary breakpoint\ :returns: True on success else False """ l.debug("ida target set_breakpoint at %x " % (address)) action = SetBreakpointCallable(address, hardware) idaapi.execute_sync(action, 0) if action.exception: raise SimConcreteBreakpointError else: return action.result
def make_name(force=False): """ Thread safe renaming wrapper """ def sync_ask_rename(): rename_flag = 0 if force or idc.AskYN(rename_flag, "Replace %s by %s" % (get_name(), name["data"])) == 1: g_logger.debug("[x] renaming %s @ 0x%x as %s", get_name(), name["address"], name["data"]) idc.MakeName( name["address"], name["data"].encode( 'ascii', 'ignore')) return idaapi.execute_sync( sync_ask_rename, idaapi.MFF_FAST)
def execute_comment(comment): """ Thread safe comment wrapper """ def make_rpt(): idc.MakeRptCmt( comment["address"], comment["data"].encode( 'ascii', 'replace')) cmt = idc.Comment(comment["address"]) if cmt != comment["data"] and idc.RptCmt( comment["address"]) != comment["data"]: g_logger.debug( "[x] Adding comment %s @ 0x%x ", comment["data"], comment["address"]) return idaapi.execute_sync(make_rpt, idaapi.MFF_WRITE) else: pass
def make_name(force=False): """ Thread safe renaming wrapper """ def sync_ask_rename(): """ Dialog asking renaming confirmation to the user """ rename_flag = 0 if force or idc.ask_yn(rename_flag, "Replace %s by %s" % (get_name(), name["data"])) == 1: logger.debug("[x] renaming %s @ 0x%x as %s", get_name(), name["address"], name["data"]) ida_name.set_name( name["address"], name["data"].encode( 'ascii', 'ignore'), ida_name.SN_AUTO) return idaapi.execute_sync( sync_ask_rename, idaapi.MFF_FAST)
def execute_comment(comment): """ Thread safe comment wrapper """ def make_rpt(): """ Inserting a comment """ ida_bytes.set_cmt( comment["address"], comment["data"].encode( 'ascii', 'replace'), 1) cmt = idc.get_cmt(comment["address"], 0) if cmt != comment["data"] and idc.get_cmt( comment["address"], 1) != comment["data"]: logger.debug( "[x] Adding comment %s @ 0x%x ", comment["data"], comment["address"]) return idaapi.execute_sync(make_rpt, idaapi.MFF_FAST) return None
def sync_wrapper(ff,safety_mode): """ Call a function ff with a specific IDA safety_mode. """ logger.debug('sync_wrapper: {}, {}'.format(ff.__name__,safety_mode)) if safety_mode not in [IDASafety.SAFE_READ,IDASafety.SAFE_WRITE]: error_str = 'Invalid safety mode {} over function {}'\ .format(safety_mode,ff.__name__) logger.error(error_str) raise IDASyncError(error_str) # No safety level is set up: res_container = Queue.Queue() def runned(): logger.debug('Inside runned') # Make sure that we are not already inside a sync_wrapper: if not call_stack.empty(): last_func_name = call_stack.get() error_str = ('Call stack is not empty while calling the ' 'function {} from {}').format(ff.__name__,last_func_name) logger.error(error_str) raise IDASyncError(error_str) call_stack.put((ff.__name__)) try: res_container.put(ff()) finally: call_stack.get() logger.debug('Finished runned') ret_val = idaapi.execute_sync(runned,safety_mode) res = res_container.get() return res
def handleMessage(self): msg_queue.append(self.data) idaapi.execute_sync(handle_message_queue, idaapi.MFF_WRITE)
def sync(self, f): return idaapi.execute_sync(f, idaapi.MFF_FAST)
def wrapper(*args, **kwargs): ff = functools.partial(f, *args, **kwargs) return idaapi.execute_sync(ff, idaapi.MFF_READ)