def active_context(self): out = self.bridge.server.context() if not out: return Function(0, 0, header=FunctionHeader("", 0)) return Function(out['func_addr'], 0, header=FunctionHeader(out["name"], out['func_addr']))
def function(self, addr) -> Optional[Function]: """ TODO: fix how types and offsets are set @param addr: @return: """ bn_func = self.bv.get_function_at(addr) if not bn_func: return None func = Function(bn_func.start, bn_func.total_bytes) func_header = FunctionHeader( bn_func.name, func.addr, ret_type=bn_func.return_type.get_string_before_name(), args={ idx: FunctionArgument(idx, param.name, str(param.type), param.type.width) for idx, param in enumerate(bn_func.function_type.parameters) }) stack_vars = { v.storage: StackVariable(v.storage, StackOffsetType.BINJA, v.name, str(v.type), v.type.width, func.addr) for v in bn_func.stack_layout if v.source_type == VariableSourceType.StackVariableSourceType } func.header = func_header func.stack_vars = stack_vars return func
def test_nonconflicting_funcs(self): state1 = binsync.State("user1") state2 = binsync.State("user2") # setup top func1 = FunctionHeader("user1_func", 0x400000, ret_type="int *", args={}) func2 = FunctionHeader("main", func1.addr, ret_type="long *", args={}) state1.set_function_header(func1) state2.set_function_header(func2) state1.functions[func1.addr].size = 0x100 state2.functions[func1.addr].size = 0x100 stack_vars1 = { 0x0: StackVariable(0, 3, "v0", "int", 4, func1.addr), 0x4: StackVariable(4, 3, "my_var", "int", 4, func1.addr) } stack_vars2 = { 0x0: StackVariable(0, 3, "v0", "int", 4, func1.addr), 0x4: StackVariable(4, 3, "v4", "long", 8, func1.addr), 0x8: StackVariable(8, 3, "v8", "long", 8, func1.addr) } for stack_vars_info in [(stack_vars1, state1), (stack_vars2, state2)]: state = stack_vars_info[1] stack_vars = stack_vars_info[0] for off, var in stack_vars.items(): state.set_stack_variable(var) func1, func2 = state1.get_function(0x400000), state2.get_function( 0x400000) merge_func = func1.nonconflict_merge(func2) self.assertEqual(merge_func.name, "user1_func") self.assertEqual(merge_func.header.ret_type, "int *") self.assertEqual(merge_func.stack_vars[0].name, "v0") self.assertEqual(merge_func.stack_vars[4].name, "my_var") self.assertEqual(merge_func.stack_vars[4].type, "int") self.assertEqual(merge_func.stack_vars[8].name, "v8")
def push_function_header(self, addr, new_name, ret_type=None, args=None, user=None, state=None): func_header = FunctionHeader(new_name, addr, ret_type=ret_type, args=args) return state.set_function_header(func_header)
def conv_func_binja_to_binsync(binja_func): # # header: name, ret type, args # args = { i: FunctionArgument(i, parameter.name, parameter.type.get_string_before_name(), parameter.type.width) for i, parameter in enumerate(binja_func.parameter_vars) } sync_header = FunctionHeader( binja_func.name, binja_func.start, ret_type=binja_func.return_type.get_string_before_name(), args=args) # # stack vars # binja_stack_vars = { v.storage: v for v in binja_func.stack_layout if v.source_type == VariableSourceType.StackVariableSourceType } sorted_stack = sorted(binja_func.stack_layout, key=lambda x: x.storage) var_sizes = {} for off, var in binja_stack_vars.items(): i = sorted_stack.index(var) if i + 1 >= len(sorted_stack): var_sizes[var] = 0 else: var_sizes[var] = var.storage - sorted_stack[i].storage bs_stack_vars = { off: binsync.StackVariable(off, binsync.StackOffsetType.BINJA, var.name, var.type.get_string_before_name(), var_sizes[var], binja_func.start) for off, var in binja_stack_vars.items() } size = binja_func.address_ranges[0].end - binja_func.address_ranges[0].start return Function(binja_func.start, size, header=sync_header, stack_vars=bs_stack_vars)
def handle_func_arg_retyped(self, func, offset, old_type, new_type): decompilation = self.controller.decompile_function(func) func_args = AngrBinSyncController.get_func_args(decompilation) func_type = decompilation.cfunc.functy.returnty.c_repr() bs_args = { i: binsync.FunctionArgument(i, var_info[0].name, var_info[1], var_info[0].size) for i, var_info in func_args.items() } self.controller.schedule_job( self.controller.push_artifact, FunctionHeader(func.name, func.addr, ret_type=func_type, args=bs_args) ) return False
def symbol_updated(self, view, sym): if self._controller.sync_lock.locked(): return if sym.type == SymbolType.FunctionSymbol: func = view.get_function_at(sym.address) bs_func = conv_func_binja_to_binsync(func) self._controller.schedule_job( self._controller.push_artifact, FunctionHeader(sym.name, sym.address, ret_type=bs_func.header.ret_type, args=bs_func.header.args)) elif sym.type == SymbolType.DataSymbol: pass
def active_context(self): curr_view = self._workspace.view_manager.current_tab if not curr_view: return None try: func = curr_view.function except NotImplementedError: return None if func is None or func.am_obj is None: return None return binsync.data.Function(func.addr, 0, header=FunctionHeader( func.name, func.addr))
def active_context(self): all_contexts = UIContext.allContexts() if not all_contexts: return None ctx = all_contexts[0] handler = ctx.contentActionHandler() if handler is None: return None actionContext = handler.actionContext() func = actionContext.function if func is None: return None return binsync.data.Function(func.start, 0, header=FunctionHeader( func.name, func.start))
def function(self, addr) -> Optional[Function]: """ TODO: add support for stack variables and function args @param addr: @return: """ try: _func = self._instance.kb.functions[addr] except KeyError: return None func = Function(_func.addr, _func.size) func_header = FunctionHeader(_func.name, _func.addr, ret_type=_func.prototype.c_repr()) func.header = func_header return func
def renamed(self, ea, new_name, local_name): # #print("renamed(ea = %x, new_name = %s, local_name = %d)" % (ea, new_name, local_name)) if ida_struct.is_member_id(ea) or ida_struct.get_struc( ea) or ida_enum.get_enum_name(ea): return 0 ida_func = idaapi.get_func(ea) # global var renaming if ida_func is None: size = idaapi.get_item_size(ea) self.binsync_state_change(self.controller.push_artifact, GlobalVariable(ea, new_name, size=size)) # function name renaming elif ida_func.start_ea == ea: # grab the name instead from ida name = idc.get_func_name(ida_func.start_ea) self.binsync_state_change(self.controller.push_artifact, FunctionHeader(name, ida_func.start_ea)) return 0
def function_header(ida_cfunc) -> FunctionHeader: func_addr = ida_cfunc.entry_ea # collect the function arguments func_args = {} for idx, arg in enumerate(ida_cfunc.arguments): size = arg.width name = arg.name type_str = str(arg.type()) func_args[idx] = FunctionArgument(idx, name, type_str, size) # collect the header ret_type and name func_name = get_func_name(func_addr) try: ret_type_str = str(ida_cfunc.type.get_rettype()) except Exception: ret_type_str = "" ida_function_info = FunctionHeader(func_name, func_addr, ret_type=ret_type_str, args=func_args, last_change=int(time())) return ida_function_info
def test_func_diffing(self): state1 = binsync.State("user1") state2 = binsync.State("user2") # setup top func1 = FunctionHeader("func", 0x400000, ret_type="int *", args={ 0: FunctionArgument(0, "a1", "int", 4), 1: FunctionArgument(1, "a2", "long", 8) }) func2 = FunctionHeader("func_changed", func1.addr, ret_type="long *", args={ 0: FunctionArgument(0, "a1", "int", 4), 1: FunctionArgument(1, "a2", "int", 4) }) state1.set_function_header(func1) state2.set_function_header(func2) state1.functions[func1.addr].size = 0x100 state2.functions[func1.addr].size = 0x150 stack_vars1 = { 0x0: StackVariable(0, 3, "v0", "int", 4, func1.addr), 0x4: StackVariable(4, 3, "v4", "int", 4, func1.addr) } stack_vars2 = { 0x0: StackVariable(0, 3, "v0", "int", 4, func1.addr), 0x4: StackVariable(4, 3, "v4", "long", 8, func1.addr), 0x8: StackVariable(8, 3, "v8", "long", 8, func1.addr) } for stack_vars_info in [(stack_vars1, state1), (stack_vars2, state2)]: stack_vars, state = stack_vars_info[:] for off, var in stack_vars.items(): state.set_stack_variable(var) func1 = state1.get_function(func1.addr) func2 = state2.get_function(func1.addr) diff_dict = func1.diff(func2) header_diff = diff_dict["header"] vars_diff = diff_dict["stack_vars"] # size should not match self.assertNotEqual(func1.size, func2.size) self.assertEqual(diff_dict["size"]["before"], func1.size) self.assertEqual(diff_dict["size"]["after"], func2.size) # names should not match self.assertEqual(header_diff["name"]["before"], func1.name) self.assertEqual(header_diff["name"]["after"], func2.name) # arg1 should match self.assertFalse(header_diff["args"][0]) # arg2 should not match self.assertNotEqual(header_diff["args"][1]["type_str"]["before"], header_diff["args"][1]["type_str"]["after"]) # v4 and v8 should differ offsets = [0, 4, 8] for off in offsets: var_diff = vars_diff[off] if off == 0: self.assertFalse(var_diff) if off == 0x4: self.assertNotEqual(var_diff["size"]["before"], var_diff["size"]["after"]) elif off == 0x8: self.assertIsNone(var_diff["addr"]["before"]) self.assertEqual(var_diff["addr"]["after"], func1.addr) print(json.dumps(diff_dict, sort_keys=False, indent=4))
def handle_function_renamed(self, func, old_name, new_name): self.controller.schedule_job( self.controller.push_artifact, FunctionHeader(new_name, func.addr) ) return False