def get_overriden_func_names(union_name, offset, get_not_funcs_members=False): sptr = utils.get_sptr_by_name(union_name) res = [] if not sptr.is_union: return res for i in range(ida_struct.get_max_offset(sptr)): member = ida_struct.get_member(sptr, i) cls = ida_struct.get_member_name(member.id) tinfo = utils.get_member_tinfo(member) log.debug("Trying %s", cls) if cls == get_interface_empty_vtable_name() or not tinfo.is_ptr(): continue pointed_obj = tinfo.get_pointed_object() if not pointed_obj.is_struct(): continue vtable_sptr = utils.get_sptr_by_name(pointed_obj.get_final_type_name()) if ida_struct.get_max_offset(vtable_sptr) <= offset: continue funcptr_member = ida_struct.get_member(vtable_sptr, offset) funcptr_type = utils.get_member_tinfo(funcptr_member) func_name = ida_struct.get_member_name(funcptr_member.id) if not funcptr_type.is_funcptr() and not get_not_funcs_members: continue res.append((cls, func_name)) return res
def get_vtable_member_type(self, vtable_sptr, offset): vtable_struct_name = ida_struct.get_struc_name(vtable_sptr.id) try: funcptr_member = ida_struct.get_member(vtable_sptr, offset) except TypeError as e: logging.exception("0x%x: bad offset: 0x%x", self.cfunc.entry_ea, offset) return None if funcptr_member is None: logging.debug( "0x%x: %s.%d is not a valid struct member", self.cfunc.entry_ea, vtable_struct_name, offset, ) return None funcptr_member_type = utils.get_member_tinfo(funcptr_member) if not funcptr_member_type.is_funcptr(): logging.debug( "0x%x: member type (%s) isn't funcptr!", self.cfunc.entry_ea, funcptr_member_type.dstr(), ) return None return funcptr_member_type
def apply_member(cls, struct, data): ida_struct.add_struc_member(struct, data['name'], data['offset'], data['flag'], data['opinfo'], data['size']) member = ida_struct.get_member(struct, data['offset']) if 'comment' in data and data['comment']: ida_struct.set_member_cmt(member, data['comment'], False) if 'repeatable_comment' in data and data['repeatable_comment']: ida_struct.set_member_cmt(member, data['repeatable_comment'], True)
def push_ptr_member_to_struct( struct, member_name, member_type, offset=BADADDR, overwrite=False ): mt = None flag = idaapi.FF_DWORD member_size = WORD_LEN if member_type is not None and (member_type.is_struct() or member_type.is_union()): logging.debug("Is struct!") substruct = extract_struct_from_tinfo(member_type) if substruct is not None: flag = idaapi.FF_STRUCT mt = ida_nalt.opinfo_t() mt.tid = substruct.id logging.debug( f"Is struct: {ida_struct.get_struc_name(substruct.id)}/{substruct.id}" ) member_size = ida_struct.get_struc_size(substruct.id) member_type = None elif WORD_LEN == 4: flag = idaapi.FF_DWORD elif WORD_LEN == 8: flag = idaapi.FF_QWORD new_member_name = member_name if overwrite and ida_struct.get_member(struct, offset): logging.debug("Overwriting!") ret_val = ida_struct.set_member_name(struct, offset, member_name) i = 0 while ret_val == ida_struct.STRUC_ERROR_MEMBER_NAME: new_member_name = "%s_%d" % (member_name, i) i += 1 if i > 250: return ret_val = ida_struct.set_member_name(struct, offset, new_member_name) else: ret_val = ida_struct.add_struc_member( struct, new_member_name, offset, flag, mt, member_size ) i = 0 while ret_val == ida_struct.STRUC_ERROR_MEMBER_NAME: new_member_name = "%s_%d" % (member_name, i) i += 1 if i > 250: return ret_val = ida_struct.add_struc_member( struct, new_member_name, offset, flag, mt, member_size ) if ret_val != 0: logging.debug(f"ret_val: {ret_val}") member_ptr = ida_struct.get_member_by_name(struct, new_member_name) if member_ptr is None: logging.debug("member is None") if member_type is not None and member_ptr is not None: ida_struct.set_member_tinfo( struct, member_ptr, 0, member_type, idaapi.TINFO_DEFINITE ) return member_ptr
def main(): is_selected, sel_start, sel_end = ida_kernwin.read_selection() if not is_selected: logger.error('range must be selected') return -1 sel_end = ida_bytes.next_head(sel_end) buf = ida_bytes.get_bytes(sel_start, sel_end - sel_start) if buf is None: logger.error('failed to fetch instruction bytes') return -1 f = ida_funcs.get_func(sel_start) if f != ida_funcs.get_func(sel_end): logger.error('range must be within a single function') return -1 # find mappings from "$localN" to "custom_name" regvars = {} for i in range(0x1000): regvar = ida_frame.find_regvar(f, sel_start, '$local%d' % i) if regvar is None: continue regvars[regvar.canon] = regvar.user if len(regvars) >= f.regvarqty: break globals_ = {} for i, offset in netnode.Netnode('$ wasm.offsets').get('globals', {}).items(): globals_['$global' + i] = ida_name.get_name(offset) frame = {} if f.frame != ida_idaapi.BADADDR: names = set([]) for i in range(ida_struct.get_struc_size(f.frame)): s = ida_struct.get_struc(f.frame) if not s: continue m = ida_struct.get_member(s, i) if not m: continue name = ida_struct.get_member_name(m.id) if name in names: continue frame[i] = name names.add(name) emu = Emulator(buf) emu.run() print( emu.render(ctx={ 'regvars': regvars, 'frame': frame, 'globals': globals_, }))
def create_structs(self): self.struct_id = ida_struct.add_struc(BADADDR, self.name) self.struct_ptr = ida_struct.get_struc(self.struct_id) if self.struct_ptr is None: logging.exception("self.struct_ptr is None at %s", self.name) previous_parent_offset = 0 previous_parent_size = 0 previous_parent_struct_id = BADADDR for _, parent_name, parent_offset in self.parents: if ( parent_offset - previous_parent_offset > previous_parent_size and previous_parent_struct_id != BADADDR ): utils.expand_struct( previous_parent_struct_id, parent_offset - previous_parent_offset ) baseclass_id = ida_struct.get_struc_id(parent_name) baseclass_size = ida_struct.get_struc_size(baseclass_id) if baseclass_id == BADADDR or baseclass_size == 0: logging.warning( "bad struct id or size: %s(0x%x:%s) - %s, %d", self.name, parent_offset, parent_name, baseclass_id, baseclass_size, ) member_name = cpp_utils.get_base_member_name(parent_name, parent_offset) idc.add_struc_member( self.struct_id, member_name, parent_offset, idaapi.FF_STRUCT, baseclass_id, baseclass_size, ) previous_parent_offset = parent_offset previous_parent_size = baseclass_size previous_parent_struct_id = baseclass_id for _, parent_name, parent_offset in self.parents: ida_struct.get_member( self.struct_ptr, parent_offset ).props |= ida_struct.MF_BASECLASS
def find_vtable_at_offset(struct_ptr, vtable_offset): current_struct = struct_ptr current_offset = 0 member = ida_struct.get_member(current_struct, vtable_offset) if member is None: return None parents_vtables_classes = [] current_offset += member.get_soff() while current_offset < vtable_offset and member is not None: current_struct = utils.get_member_substruct(member) if current_struct is None: return parents_vtables_classes.append( [ ida_struct.get_struc_name(current_struct.id), vtable_offset - current_offset, ] ) member = ida_struct.get_member(current_struct, vtable_offset - current_offset) if member is None: logging.exception( "Couldn't find vtable at offset %d for %d", vtable_offset - current_offset, struct_ptr.id, ) current_offset += member.get_soff() if current_offset != vtable_offset: return None while member is not None: if is_member_vtable(member): return member, current_struct, parents_vtables_classes current_struct = utils.get_member_substruct(member) if current_struct is None: return None parents_vtables_classes.append( [ida_struct.get_struc_name(current_struct.id), 0] ) member = ida_struct.get_member(current_struct, 0) return None
def get_struc_name(self): x = self.target.operands['x'] m = self.target.operands['m'] xtype = x.type xtype.remove_ptr_or_array() typename = ida_typeinf.print_tinfo('', 0, 0, ida_typeinf.PRTYPE_1LINE, xtype, '', '') sid = ida_struct.get_struc_id(typename) sptr = ida_struct.get_struc(sid) member = ida_struct.get_member(sptr, m) return '%s::%s' % (typename, member)
def add_child_vtable(parent_name, child_name, child_vtable_id, offset): logging.debug( "add_child_vtable (%s, %s, %s)", parent_name, child_name, child_vtable_id, ) parent_vtable_member = ida_struct.get_member( utils.get_sptr_by_name(parent_name), offset ) vtable_member_tinfo = utils.get_member_tinfo(parent_vtable_member) parent_vtable_struct = utils.get_sptr_by_name( get_class_vtable_struct_name(parent_name, offset) ) if parent_vtable_struct is None: return None pointed_struct = utils.extract_struct_from_tinfo(vtable_member_tinfo) logging.debug("pointed_struct: %s", str(pointed_struct)) if ( (pointed_struct is None) or (not is_struct_vtable(pointed_struct)) or (parent_vtable_struct.id != pointed_struct.id) ): parent_vtable_member = None logging.debug("Not a struct vtable: %s", str(vtable_member_tinfo)) # TODO: Check that struct is a valid vtable by name if not parent_vtable_struct.is_union(): logging.debug("%s vtable isn't union -> unionize it!", parent_name) parent_vtable_struct = install_vtables_union( parent_name, parent_vtable_member, vtable_member_tinfo, offset ) child_vtable_name = ida_struct.get_struc_name(child_vtable_id) child_vtable = utils.get_typeinf(child_vtable_name) logging.debug( "add_to_struct %s %s", parent_vtable_struct.id, str(child_vtable) ) if ida_struct.get_struc_size(child_vtable_id) == 0: utils.add_to_struct( ida_struct.get_struc(child_vtable_id), "dummy", None ) new_member = utils.add_to_struct( parent_vtable_struct, get_class_vtables_field_name(child_name), child_vtable ) ida_xref.add_dref( new_member.id, child_vtable_id, ida_xref.XREF_USER | ida_xref.dr_O )
def create_struct(name, fields, size): struct_id = idaapi.get_struc_id(name) # print struct_id if struct_id != idaapi.BADADDR: i = ida_kernwin.ask_yn( 0, "A class structure for %s already exists. Are you sure you want to remake it?" % name) if i == idaapi.BADADDR: return if i == 1: idaapi.del_struc_members(idaapi.get_struc(struct_id), 0, idaapi.get_struc_size(struct_id)) # struct_id = idc.AddStrucEx(idaapi.BADADDR, name + "_vtbl", 0) else: struct_id = idaapi.add_struc(idaapi.BADADDR, name, 0) if struct_id == idaapi.BADADDR: Warning( "Could not create the class structure!.\nPlease check something.") return sptr = idaapi.get_struc(struct_id) for off in fields: off, type_name, type_kind, field_name = fields[off] print( "Process field. Off = 0x%04X, type_name = %s (%d: %s), field_name = %s" % (off, type_name, type_kind, type_sizes[type_kind][0], field_name)) type_size = type_sizes[type_kind][1] ret = ida_struct.add_struc_member(sptr, field_name.decode(), off, flags_dict[type_size], None, type_size) if ret != 0: ida_kernwin.warning("Unknown error! Err = %d" % ret) return mptr = ida_struct.get_member(sptr, off) ida_struct.set_member_cmt( mptr, " --> %s (%d: %s)" % (type_name.decode(), type_kind, type_sizes[type_kind][0]), False) struct_size = ida_struct.get_struc_size(sptr) if size < struct_size: ida_kernwin.warning( "Struct create error! final size (%d) > instanse size (%d)" % (struct_size, size)) elif size > struct_size: for i in range(size - struct_size): ida_struct.add_struc_member(sptr, "dummy%d" % i, idaapi.BADADDR, idaapi.FF_BYTE, None, 1)
def view_dblclick(self, viewer, point): widget_type = ida_kernwin.get_widget_type(viewer) if not (widget_type == 48 or widget_type == 28): return # Decompiler or Structures window func_cand_name = None place, x, y = ida_kernwin.get_custom_viewer_place(viewer, False) if place.name() == "structplace_t": # Structure window: structplace = ida_kernwin.place_t_as_structplace_t(place) if structplace is not None: s = ida_struct.get_struc(ida_struct.get_struc_by_idx(structplace.idx)) if s: member = ida_struct.get_member(s, structplace.offset) if member: func_cand_name = ida_struct.get_member_name(member.id) if func_cand_name is None: line = utils.get_curline_striped_from_viewer(viewer) func_cand_name = cpp_utils.find_valid_cppname_in_line(line, x) if func_cand_name is not None: func_cand_ea = ida_name.get_name_ea(BADADDR, func_cand_name) if func_cand_ea is not None and utils.is_func_start(func_cand_ea): idc.jumpto(func_cand_ea)
def add_to_struct( struct_ptr, member_name, member_tif=None, offset=BADADDR, is_offs=False, overwrite=False, ): """@return: member_ptr, or None if failed""" member_ptr = ida_struct.get_member(struct_ptr, offset) if member_ptr: # pylint: disable=too-many-function-args if not _update_member_name(member_ptr, member_name, overwrite): return None else: member_ptr = _add_new_member(struct_ptr, offset, member_name, member_tif, is_offs) if not member_ptr: return None _update_member_type(struct_ptr, member_ptr, member_tif) return member_ptr
def get_member_type(struct, idx): """ Retrieve the type information for the struct member :return: Type string """ member = ida_struct.get_member(struct, idx) tif = idaapi.tinfo_t() ida_struct.get_member_tinfo(tif, member) elements = str(tif).split(' ') typ = None if len(elements) == 2 and elements[0] == 'unsigned': if elements[1] == '__int8': typ = 'uint8_t' elif elements[1] == '__int16': typ = 'uint16_t' elif elements[1] == '__int32': typ = 'uint32_t' elif elements[1] == '__int64': typ = 'uint64_t' elif elements[1] != '': typ = elements[1] elif len(elements) == 1: if elements[0] == '__int8': typ = 'int8_t' elif elements[0] == '__int16': typ = 'int16_t' elif elements[0] == '__int32': typ = 'int32_t' elif elements[0] == '__int64': typ = 'int64_t' elif elements[0] != '': typ = str(tif) return typ
def update_form(update): """ Processes an incoming update by adding it to the form. Args: update (IdbUpdate) - The message received from the ZMQ server, as a class that inherits IdbUpdate """ try: g_item_list_mutex.lock() message_type = update.update_type address = update.address current_data = None if message_type == idb_push_ops.UpdateTypes.Name: current_data = psida_common.get_non_default_name(address, update.is_local) if current_data == update.data: return elif message_type == idb_push_ops.UpdateTypes.Comment: current_data = psida_common.get_comment(address) if current_data == update.data: return elif message_type == idb_push_ops.UpdateTypes.RepeatableComment: current_data = psida_common.get_repeated_comment(address) if current_data == update.data: return elif message_type in [idb_push_ops.UpdateTypes.AnteriorLine, idb_push_ops.UpdateTypes.PosteriorLine]: current_data = idc.get_extra_cmt(address, update.line_index) if current_data == update.data: return elif message_type == idb_push_ops.UpdateTypes.LookHere: current_data = psida_common.get_non_default_name(address) elif message_type == idb_push_ops.UpdateTypes.StackVariableRenamed: func_frame = ida_frame.get_frame(address) update.func_frame_pointer = func_frame member = ida_struct.get_member(func_frame, update.offset) current_data = None if member is not None: current_data = ida_struct.get_member_name(member.id) if current_data == update.data: return if current_data is not None: update.new = False else: update.new = True elif message_type in [idb_push_ops.UpdateTypes.MakeData, idb_push_ops.UpdateTypes.MakeCode, idb_push_ops.UpdateTypes.MakeFunc]: current_data = update.get_conflict() if current_data == '': return else: if CONFIGURATION[DEBUG]: print 'DEBUG - UI - Unrecognized/Unimplemented type %d: in message %s' % (message_type, update.to_dict()) return update.data_at_address = current_data add_item(update) except: if CONFIGURATION['debug']: traceback.print_exc() print 'ERROR - UI - General error while updating form' finally: g_item_list_mutex.unlock()
def replace_dword_in_struct(idx, ctx): print '%x' % idx.ea struct_expr = ctx.get_expr('struct_part')[0] var = ctx.get_var("struct_var") values = ctx.get_expr('values')[0] offset = struct_expr.m vals = [] N = extract_number(values) typename = struct_expr.x.type.dstr() s_id = ida_struct.get_struc_id(typename) if s_id == idc.BADADDR: return sptr = ida_struct.get_struc(s_id) is_suits = True fields = [] inner_offset = 0 while inner_offset < 4: memb = ida_struct.get_member(sptr, offset + inner_offset) if memb is None: print "Not enought members!" is_suits = False break size = ida_struct.get_member_size(memb) if inner_offset + size > 4: print "Size fail!(%d bytes lenft but member size is %d)" % ( 4 - inner_offset, size) is_suits = False break if size == 1: val = N & 0xff N = N >> 8 elif size == 2: val = N & 0xffff N = N >> 16 else: print "Unkn size" is_suits = False break fields.append((inner_offset, val)) inner_offset += size if is_suits is False: print "Not suitable!" return inslist = [] for i in fields: ins = make_asgn_refvar_number(idx.ea, var, offset + i[0], i[1]) inslist.append(ins) ######### # Not foldable ######### blk = make_cblk(inslist) cblk = make_cblock_insn(idx.ea, blk) idx.cleanup() idaapi.qswap(idx, cblk) del cblk ########################## # Foldable - not working - IDA crashes at exit idk why;[ ########################## #fake_cond = make_helper_expr("fold") #blk = make_cblk(inslist) #cblk = make_cblock_insn(idx.ea, blk) #cif = make_if(idx.ea, fake_cond, cblk) #idx.cleanup() #idaapi.qswap(idx, cif) #del cif return True
def add_to_struct( struct, member_name, member_type=None, offset=BADADDR, is_offset=False, overwrite=False, ): mt = None flag = idaapi.FF_DWORD member_size = WORD_LEN if member_type is not None and (member_type.is_struct() or member_type.is_union()): logging.debug("Is struct!") substruct = extract_struct_from_tinfo(member_type) if substruct is not None: flag = idaapi.FF_STRUCT mt = ida_nalt.opinfo_t() mt.tid = substruct.id logging.debug( f"Is struct: {ida_struct.get_struc_name(substruct.id)}/{substruct.id}" ) member_size = ida_struct.get_struc_size(substruct.id) elif WORD_LEN == 4: flag = idaapi.FF_DWORD elif WORD_LEN == 8: flag = idaapi.FF_QWORD if is_offset: flag |= idaapi.FF_0OFF mt = ida_nalt.opinfo_t() r = ida_nalt.refinfo_t() r.init( ida_nalt.get_reftype_by_size(WORD_LEN) | ida_nalt.REFINFO_NOBASE) mt.ri = r new_member_name = member_name member_ptr = ida_struct.get_member(struct, offset) if overwrite and member_ptr: if ida_struct.get_member_name(member_ptr.id) != member_name: logging.debug("Overwriting!") ret_val = ida_struct.set_member_name(struct, offset, member_name) i = 0 while ret_val == ida_struct.STRUC_ERROR_MEMBER_NAME: new_member_name = "%s_%d" % (member_name, i) i += 1 if i > 250: logging.debug("failed change name") return ret_val = ida_struct.set_member_name(struct, offset, new_member_name) else: ret_val = ida_struct.add_struc_member(struct, new_member_name, offset, flag, mt, member_size) i = 0 while ret_val == ida_struct.STRUC_ERROR_MEMBER_NAME: new_member_name = "%s_%d" % (member_name, i) i += 1 if i > 250: return ret_val = ida_struct.add_struc_member(struct, new_member_name, offset, flag, mt, member_size) if ret_val != 0: logging.debug(f"ret_val: {ret_val}") member_ptr = ida_struct.get_member_by_name(struct, new_member_name) if member_type is not None and member_ptr is not None: ida_struct.set_member_tinfo(struct, member_ptr, 0, member_type, idaapi.TINFO_DEFINITE) return member_ptr
def _member(self): return ida_struct.get_member(self._struc, self.stack_offset)