def implement(self): ida_struct.set_struc_name(self._id, self._name)
def __call__(self): struc = ida_struct.get_struc_id(Event.encode(self.oldname)) ida_struct.set_struc_name(struc, Event.encode(self.newname))
def __call__(self): struc = ida_struct.get_struc_id(self.oldname) ida_struct.set_struc_name(struc, self.newname)
def analyze_function_frame(self, function: Function) -> None: """ inspect the given function to determine the frame layout and set references appropriately. args: function (Function): function instance. """ # given a function prologue like the following: # # 23 80 80 80 80 00 get_global $global0 # 21 04 set_local $local4 # 41 20 i32.const 0x20 # 21 05 set_local $local5 # 20 04 get_local $local4 # 20 05 get_local $local5 # 6B i32.sub # 21 06 set_local $local6 # # recognize that the function frame is 0x20 bytes. if not self.has_llvm_prologue(function): return bc = self.get_prologue_bc(function['offset']) if len(bc) == 0: return global_frame_pointer = bc[0].imm.global_index frame_size = bc[2].imm.value local_frame_pointer = bc[7].imm.local_index # add a frame structure to the function f = ida_funcs.get_func(function['offset']) ida_frame.add_frame(f, 0x0, 0x0, frame_size) ida_struct.set_struc_name(f.frame, 'frame%d' % function['index']) # ensure global variable $frame_stack is named appropriately ida_name.set_name(self.proc.globals[global_frame_pointer]['offset'], '$frame_stack') # re-map local variable to $frame_pointer ida_frame.add_regvar(f, function['offset'], function['offset'] + function['size'], '$local%d' % local_frame_pointer, '$frame_pointer', '') # define the frame structure layout by scanning for references within this function frame_references = self.find_function_frame_references( function, local_frame_pointer) for frame_offset, refs in frame_references.items(): member_name = 'field_%x' % frame_offset for ref in refs: if 'parameter' in ref: member_name = 'param%d' % (ref['parameter']) # pick largest element size for the element type flags = 0 size = 0 for ref in refs: fl = { 'i8': ida_bytes.FF_BYTE | ida_bytes.FF_DATA, 'i16': ida_bytes.FF_WORD | ida_bytes.FF_DATA, 'i32': ida_bytes.FF_DWORD | ida_bytes.FF_DATA, 'i64': ida_bytes.FF_QWORD | ida_bytes.FF_DATA, 'f32': ida_bytes.FF_FLOAT | ida_bytes.FF_DATA, 'f64': ida_bytes.FF_DOUBLE | ida_bytes.FF_DATA, }[ref['element_size']] s = { 'i8': 1, 'i16': 2, 'i32': 4, 'i64': 8, 'f32': 4, 'f64': 8, }[ref['element_size']] # by luck, FF_BYTE < FF_WORD < FF_DWORD < FF_QWORD, # so we can order flag values. if fl > flags: flags = fl size = s logger.debug('adding frame member %s to function %d', member_name, function['index']) ida_struct.add_struc_member(ida_struct.get_struc(f.frame), member_name, frame_offset, flags & 0xFFFFFFFF, None, size) # mark struct references for refs in frame_references.values(): for ref in refs: # set type of operand 0 to function frame structure offset # ref: https://github.com/idapython/src/blob/a3855ab969fd16758b3de007525feeba3a920344/tools/inject_pydoc/bytes.py#L5 insn = ida_ua.insn_t() if not ida_ua.decode_insn(insn, ref['offset']): continue path = ida_pro.tid_array(1) path[0] = f.frame ida_bytes.op_stroff(insn, 0, path.cast(), 1, 0)
def install_vtables_union(class_name, class_vtable_member=None, vtable_member_tinfo=None, offset=0): # pylint: disable=too-many-locals # TODO: this function is too big and must be refactored log.debug( "install_vtables_union(%s, %s, %s)", class_name, class_vtable_member, str(vtable_member_tinfo), ) if class_vtable_member and vtable_member_tinfo: old_vtable_sptr = utils.extract_struct_from_tinfo(vtable_member_tinfo) old_vtable_class_name = ida_struct.get_struc_name(old_vtable_sptr.id) else: old_vtable_class_name = get_class_vtable_struct_name(class_name, offset) old_vtable_sptr = utils.get_sptr_by_name(old_vtable_class_name) vtables_union_name = old_vtable_class_name if old_vtable_sptr and not ida_struct.set_struc_name( old_vtable_sptr.id, old_vtable_class_name + "_orig" ): # FIXME: why log exception? log.exception( "Failed changing %s->%s_orig", old_vtable_class_name, old_vtable_class_name, ) # FIXME: why -1 and not None? return -1 vtables_union_id = utils.get_or_create_struct_id(vtables_union_name, True) vtable_member_tinfo = utils.get_typeinf(old_vtable_class_name + "_orig") if vtables_union_id == BADADDR: log.exception( "Cannot create union vtable for %s()%s", class_name, vtables_union_name, ) # FIXME: why -1 and not None? return -1 vtables_union = ida_struct.get_struc(vtables_union_id) if not vtables_union: log.exception("Could retrieve vtables union for %s", class_name) # FIXME: return -1? if vtable_member_tinfo is not None: vtables_union_vtable_field_name = get_class_vtables_field_name(class_name) else: vtables_union_vtable_field_name = get_interface_empty_vtable_name() utils.add_to_struct(vtables_union, vtables_union_vtable_field_name, vtable_member_tinfo) parent_struct = utils.get_sptr_by_name(class_name) flag = idaapi.FF_STRUCT mt = idaapi.opinfo_t() mt.tid = vtables_union_id struct_size = ida_struct.get_struc_size(vtables_union_id) vtables_union_ptr_type = utils.get_typeinf_ptr(vtables_union_name) if class_vtable_member: member_ptr = class_vtable_member else: # FIXME: add_struc_member returns error code, not member id member_id = ida_struct.add_struc_member( parent_struct, get_class_vtable_field_name(class_name), offset, flag, mt, struct_size, ) # FIXME: get_member_by_id returns tuple, not member ptr member_ptr = ida_struct.get_member_by_id(member_id) ida_struct.set_member_tinfo( parent_struct, member_ptr, 0, vtables_union_ptr_type, idaapi.TINFO_DEFINITE, ) # FIXME: might be None! Is this OK, considering we return -1 everywhere else? return vtables_union
def implement(self): sturc_id = ida_struct.get_struc_id(str(self._id)) ida_struct.set_struc_name(sturc_id, self._name)
def install_vtables_union( class_name, class_vtable_member=None, vtable_member_tinfo=None, offset=0 ): logging.debug( "install_vtables_union(%s, %s, %s)", class_name, class_vtable_member, str(vtable_member_tinfo), ) if class_vtable_member and vtable_member_tinfo: old_vtable_sptr = utils.extract_struct_from_tinfo(vtable_member_tinfo) old_vtable_class_name = ida_struct.get_struc_name(old_vtable_sptr.id) else: old_vtable_class_name = get_class_vtable_struct_name(class_name, offset) old_vtable_sptr = utils.get_sptr_by_name(old_vtable_class_name) vtables_union_name = old_vtable_class_name if old_vtable_sptr and not ida_struct.set_struc_name( old_vtable_sptr.id, old_vtable_class_name + "_orig" ): logging.exception( f"Failed changing {old_vtable_class_name}->" f"{old_vtable_class_name+'orig'}" ) return -1 vtables_union_id = utils.get_or_create_struct_id(vtables_union_name, True) vtable_member_tinfo = utils.get_typeinf(old_vtable_class_name + "_orig") if vtables_union_id == BADADDR: logging.exception( f"Cannot create union vtable for {class_name}(){vtables_union_name}" ) return -1 vtables_union = ida_struct.get_struc(vtables_union_id) if not vtables_union: logging.exception(f"Could retrieve vtables union for {class_name}") if vtable_member_tinfo is not None: vtables_union_vtable_field_name = get_class_vtables_field_name(class_name) else: vtables_union_vtable_field_name = get_interface_empty_vtable_name() utils.add_to_struct( vtables_union, vtables_union_vtable_field_name, vtable_member_tinfo ) parent_struct = utils.get_sptr_by_name(class_name) flag = idaapi.FF_STRUCT mt = idaapi.opinfo_t() mt.tid = vtables_union_id struct_size = ida_struct.get_struc_size(vtables_union_id) vtables_union_ptr_type = utils.get_typeinf_ptr(vtables_union_name) if class_vtable_member: member_ptr = class_vtable_member else: member_id = ida_struct.add_struc_member( parent_struct, get_class_vtable_field_name(class_name), offset, flag, mt, struct_size, ) member_ptr = ida_struct.get_member_by_id(member_id) ida_struct.set_member_tinfo( parent_struct, member_ptr, 0, vtables_union_ptr_type, idaapi.TINFO_DEFINITE ) return vtables_union