def process(self): self.apply_to(self.__cfunc.body, None) if len(self.__possible_names) == 1: # Only one potential name was found, rename function using it new_name = self.__possible_names.pop() logging.info("Renaming function at {} to `{}`".format( helper.to_hex(self.__cfunc.entry_ea), new_name)) idc.set_name(self.__cfunc.entry_ea, new_name) elif len(self.__possible_names) > 1: logger.error( "Function at {} has more than one candidate for renaming: {}". format(helper.to_hex(self.__cfunc.entry_ea), ", ".join(self.__possible_names)))
def visit_expr(self, expression): # Checks if expression is reference by pointer or by value if expression.op == idaapi.cot_memptr: struct_type = expression.x.type.get_pointed_object() elif expression.op == idaapi.cot_memref: struct_type = expression.x.type else: return 0 # Getting information about structure, field offset, address and one line corresponding to code ordinal = helper.get_ordinal(struct_type) field_offset = expression.m ea = self.__find_ref_address(expression) usage_type = self.__get_type(expression) if ea == idaapi.BADADDR or not ordinal: logger.warning( "Failed to parse at address {0}, ordinal - {1}, type - {2}". format(helper.to_hex(ea), ordinal, struct_type.dstr())) one_line = self.__get_line() occurrence_offset = ea - self.__function_address xref_info = (occurrence_offset, one_line, usage_type) # Saving results if ordinal not in self.__result: self.__result[ordinal] = {field_offset: [xref_info]} elif field_offset not in self.__result[ordinal]: self.__result[ordinal][field_offset] = [xref_info] else: self.__result[ordinal][field_offset].append(xref_info) return 0
def visit_expr(self, expr): if expr.op == idaapi.cot_call and expr.x.op == idaapi.cot_obj and expr.x.obj_ea == self.__func_addr: arg_expr = expr.a[self.__arg_idx] if arg_expr.op != idaapi.cot_obj: cexpr_ea = helper.find_asm_address(expr, self.parents) logger.error("Argument is a not string at {}".format( helper.to_hex(cexpr_ea))) return 1 self.__add_func_name(arg_expr) return 0
def __add_func_name(self, arg_expr): new_name = idc.get_strlit_contents(arg_expr.obj_ea) if not idaapi.is_valid_typename(new_name): logger.warn("Argument has a weird name `{}` at {}".format( new_name, helper.to_hex(helper.find_asm_address(arg_expr, self.parents)))) return self.__possible_names.add(new_name)
def data(self, column): if column == 0: return self.name elif column == 1: return self.tinfo.get_pointed_object().dstr() elif column == 2: addresses = self.addresses if len(addresses) > 1: return "LIST" elif len(addresses) == 1: return helper.to_hex(addresses[0])
def __add_func_name(self, arg_expr): new_name = idc.get_strlit_contents(arg_expr.obj_ea) if type(new_name) is not str: # convert bytes to str (python 3) new_name = new_name.decode('ascii') if not idaapi.is_valid_typename(new_name): logger.warn("Argument has a weird name `{}` at {}".format( new_name, helper.to_hex(helper.find_asm_address(arg_expr, self.parents)))) return self.__possible_names.add(new_name)
def __get_type(self, cexpr): """ Returns one of the following types: 'R' - read value, 'W' - write value, 'A' - function argument""" child = cexpr for p in reversed(self.parents): assert p, "Failed to get type at " + helper.to_hex(self.__function_address) if p.cexpr.op == idaapi.cot_call: return 'Arg' if not p.is_expr(): return 'R' if p.cexpr.op == idaapi.cot_asg: if p.cexpr.x == child: return 'W' return 'R' child = p.cexpr
def _manipulate(self, cexpr, obj): if self.crippled: logger.debug("Skipping crippled function at {}".format( helper.to_hex(self._cfunc.entry_ea))) return if obj.id == api.SO_GLOBAL_OBJECT: old_name = idaapi.get_short_name(cexpr.obj_ea) if settings.PROPAGATE_THROUGH_ALL_NAMES or _is_default_name( old_name): new_name = self.__rename_with_prefix( lambda x: idaapi.set_name(cexpr.obj_ea, x), self.__propagated_name) logger.debug("Renamed global variable from {} to {}".format( old_name, new_name)) elif obj.id == api.SO_LOCAL_VARIABLE: lvar = self._cfunc.get_lvars()[cexpr.v.idx] old_name = lvar.name if settings.PROPAGATE_THROUGH_ALL_NAMES or _is_default_name( old_name): new_name = self.__rename_with_prefix( lambda x: self.__hx_view.rename_lvar(lvar, x, True), self.__propagated_name) logger.debug("Renamed local variable from {} to {}".format( old_name, new_name)) elif obj.id in (api.SO_STRUCT_POINTER, api.SO_STRUCT_REFERENCE): struct_tinfo = cexpr.x.type offset = cexpr.m struct_tinfo.remove_ptr_or_array() old_name = helper.get_member_name(struct_tinfo, offset) if settings.PROPAGATE_THROUGH_ALL_NAMES or _is_default_name( old_name): new_name = self.__rename_with_prefix( lambda x: helper.change_member_name( struct_tinfo.dstr(), offset, x), self.__propagated_name) logger.debug("Renamed struct member from {} to {}".format( old_name, new_name))