def dump(): ret = [] for addr, name in idautils.Names(): flags = ida_bytes.get_flags(addr) # The 'a' heuristic is fairly bad but we need to filter out IDA's default # naming for strings if ida_bytes.has_dummy_name(flags) or ida_bytes.has_auto_name(flags) or not ida_bytes.is_data(flags) or name[0] == 'a': continue # Sometimes the auto-generated names don't actually usually have the # right flags set, so skip these auto-looking names. if any(name.startswith(s) for s in ['byte_', 'word_', 'dword_', 'unk_', 'jpt_']): continue sz = ida_bytes.get_item_size(addr) if ida_bytes.is_struct(flags): ti = ida_nalt.opinfo_t() ida_bytes.get_opinfo(ti, addr, 0, flags) typ = ida_struct.get_struc_name(ti.tid) else: typ = None ret.append(filter_none({ 'address': addr, 'name': name, 'type': typ, 'sz': sz, 'flags': flags, })) return ret
def struc_member_changed(self, sptr, mptr): extra = {} sname = ida_struct.get_struc_name(sptr.id) soff = 0 if mptr.unimem() else mptr.soff flag = mptr.flag mt = ida_nalt.opinfo_t() is_not_data = ida_struct.retrieve_member_info(mt, mptr) if is_not_data: if flag & ida_bytes.off_flag(): extra['target'] = mt.ri.target extra['base'] = mt.ri.base extra['tdelta'] = mt.ri.tdelta extra['flags'] = mt.ri.flags self._send_event( StrucMemberChangedEvent(sname, soff, mptr.eoff, flag, extra)) # Is it really possible to create an enum? elif flag & ida_bytes.enum_flag(): extra['serial'] = mt.ec.serial self._send_event( StrucMemberChangedEvent(sname, soff, mptr.eoff, flag, extra)) elif flag & ida_bytes.stru_flag(): extra['id'] = mt.tid if flag & ida_bytes.strlit_flag(): extra['strtype'] = mt.strtype self._send_event( StrucMemberChangedEvent(sname, soff, mptr.eoff, flag, extra)) else: self._send_event( StrucMemberChangedEvent(sname, soff, mptr.eoff, flag, extra)) return 0
def member_data(self, member): d = {} # TODO: variable size bool # TODO: retrieve_member_info - get operand type member info d['name'] = ida_struct.get_member_name(member.id) d['size'] = ida_struct.get_member_size(member) d['flag'] = member.flag d['offset'] = member.soff d['comment'] = ida_struct.get_member_cmt(member.id, False) d['repeatable_comment'] = ida_struct.get_member_cmt(member.id, True) if member.has_ti(): tinfo = ida_typeinf.tinfo_t() ida_struct.get_member_tinfo(tinfo, member) d['type_info_serialize'] = tinfo.serialize() d['type_info'] = str(tinfo) oi = ida_nalt.opinfo_t() ida_struct.retrieve_member_info(oi, member) # TODO: Do things with OI sptr = ida_struct.get_sptr(member) if sptr: struct_name = ida_struct.get_struc_name(sptr.id) d['struct_name'] = struct_name d['struct_uuid'] = StructureAnnotation.depend(self, struct_name) return d
def struc_member_changed(self, sptr, mptr): extra = {} sname = ida_struct.get_struc_name(sptr.id) soff = 0 if mptr.unimem() else mptr.soff flag = mptr.flag mt = ida_nalt.opinfo_t() is_not_data = ida_struct.retrieve_member_info(mt, mptr) if is_not_data: if flag & ida_bytes.off_flag(): extra["target"] = mt.ri.target extra["base"] = mt.ri.base extra["tdelta"] = mt.ri.tdelta extra["flags"] = mt.ri.flags self._send_packet( evt.StrucMemberChangedEvent(sname, soff, mptr.eoff, flag, extra)) elif flag & ida_bytes.enum_flag(): extra["serial"] = mt.ec.serial self._send_packet( evt.StrucMemberChangedEvent(sname, soff, mptr.eoff, flag, extra)) elif flag & ida_bytes.stru_flag(): extra["struc_name"] = ida_struct.get_struc_name(mt.tid) if flag & ida_bytes.strlit_flag(): extra["strtype"] = mt.strtype self._send_packet( evt.StrucMemberChangedEvent(sname, soff, mptr.eoff, flag, extra)) else: self._send_packet( evt.StrucMemberChangedEvent(sname, soff, mptr.eoff, flag, extra)) return 0
def apply(self): func_frame = self.func_frame_pointer if self.new: ida_struct.add_struc_member(func_frame, self.data, self.offset, 0, ida_nalt.opinfo_t(), self.var_size) else: ida_struct.set_member_name(func_frame, self.offset, self.data) return 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 get_member_params(member_tif, is_offs): """@return: tuple(flag, mt, member_size)""" substruct_ptr = get_struc_from_tinfo(member_tif) if substruct_ptr: flag = idaapi.FF_STRUCT mt = ida_nalt.opinfo_t() mt.tid = substruct_ptr.id member_size = ida_struct.get_struc_size(substruct_ptr.id) else: flag = idaapi.FF_QWORD if WORD_LEN == 8 else idaapi.FF_DWORD mt = None member_size = WORD_LEN if is_offs: 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 return flag, mt, member_size
def op_type_changed(self, ea, n): flags = ida_bytes.get_flags(ea) self.log("op_type_changed(ea=0x%08X, n=%d). Flags now: 0x%08X" % (ea, n, flags)) buf = ida_nalt.opinfo_t() opi = ida_bytes.get_opinfo(buf, ea, n, flags) if opi: if ida_bytes.is_struct(flags): self.log("New struct: 0x%08X (name=%s)" % ( opi.tid, ida_struct.get_struc_name(opi.tid))) elif ida_bytes.is_strlit(flags): encidx = ida_nalt.get_str_encoding_idx(opi.strtype) if encidx == ida_nalt.STRENC_DEFAULT: encidx = ida_nalt.get_default_encoding_idx(ida_nalt.get_strtype_bpu(opi.strtype)) encname = ida_nalt.get_encoding_name(encidx) strlen = ida_bytes.get_max_strlit_length( ea, opi.strtype, ida_bytes.ALOPT_IGNHEADS | ida_bytes.ALOPT_IGNCLT) raw = ida_bytes.get_strlit_contents(ea, strlen, opi.strtype) or b"" self.log("New strlit: 0x%08X, raw hex=%s (encoding=%s)" % ( opi.strtype, binascii.hexlify(raw), encname)) elif ida_bytes.is_off(flags, n): self.log("New offset: refinfo={target=0x%08X, base=0x%08X, tdelta=0x%08X, flags=0x%X}" % ( opi.ri.target, opi.ri.base, opi.ri.tdelta, opi.ri.flags)) elif ida_bytes.is_enum(flags, n): self.log("New enum: 0x%08X (enum=%s), serial=%d" % ( opi.ec.tid, ida_enum.get_enum_name(opi.ec.tid), opi.ec.serial)) pass elif ida_bytes.is_stroff(flags, n): parts = [] for i in range(opi.path.len): tid = opi.path.ids[i] parts.append("0x%08X (name=%s)" % (tid, ida_struct.get_struc_name(tid))) self.log("New stroff: path=[%s] (len=%d, delta=0x%08X)" % ( ", ".join(parts), opi.path.len, opi.path.delta)) elif ida_bytes.is_custom(flags) or ida_bytes.is_custfmt(flags, n): self.log("New custom data type") # unimplemented else: print("Cannot retrieve opinfo_t")
def __call__(self): mt = ida_nalt.opinfo_t() if ida_bytes.is_struct(self.flag): mt.tid = self.extra['id'] if ida_bytes.is_off0(self.flag) or ida_bytes.is_off1(self.flag): mt.ri = ida_nalt.refinfo_t(self.extra['flags'], self.extra['base'], self.extra['target'], self.extra['tdelta']) if ida_bytes.is_strlit(self.flag): mt.strtype = self.extra['strtype'] struc = ida_struct.get_struc_id(Event.encode(self.sname)) sptr = ida_struct.get_struc(struc) ida_struct.set_member_type(sptr, self.soff, self.flag, mt, self.eoff - self.soff)
def __call__(self): mt = ida_nalt.opinfo_t() if ida_bytes.is_struct(self.flag): mt.tid = self.extra["id"] if ida_bytes.is_off0(self.flag) or ida_bytes.is_off1(self.flag): mt.ri = ida_nalt.refinfo_t( self.extra["flags"], self.extra["base"], self.extra["target"], self.extra["tdelta"], ) if ida_bytes.is_strlit(self.flag): mt.strtype = self.extra["strtype"] struc = ida_struct.get_struc_id(Event.encode(self.sname)) sptr = ida_struct.get_struc(struc) ida_struct.set_member_type(sptr, self.soff, self.flag, mt, self.eoff - self.soff)
def struc_member_created(self, sptr, mptr): extra = {} sname = ida_struct.get_struc_name(sptr.id) fieldname = ida_struct.get_member_name(mptr.id) offset = 0 if mptr.unimem() else mptr.soff flag = mptr.flag nbytes = mptr.eoff if mptr.unimem() else mptr.eoff - mptr.soff mt = ida_nalt.opinfo_t() is_not_data = ida_struct.retrieve_member_info(mt, mptr) if is_not_data: if flag & ida_bytes.off_flag(): extra["target"] = mt.ri.target extra["base"] = mt.ri.base extra["tdelta"] = mt.ri.tdelta extra["flags"] = mt.ri.flags self._send_packet( evt.StrucMemberCreatedEvent( sname, fieldname, offset, flag, nbytes, extra ) ) # Is it really possible to create an enum? elif flag & ida_bytes.enum_flag(): extra["serial"] = mt.ec.serial self._send_packet( evt.StrucMemberCreatedEvent( sname, fieldname, offset, flag, nbytes, extra ) ) elif flag & ida_bytes.stru_flag(): extra["id"] = mt.tid if flag & ida_bytes.strlit_flag(): extra["strtype"] = mt.strtype self._send_packet( evt.StrucMemberCreatedEvent( sname, fieldname, offset, flag, nbytes, extra ) ) else: self._send_packet( evt.StrucMemberCreatedEvent( sname, fieldname, offset, flag, nbytes, extra ) ) return 0
def implement(self): id_of_struct = ida_struct.get_struc_id(str(self._id)) sturct_obj = ida_struct.get_struc(long(id_of_struct)) flags = 0 size = 0 if self._value == "db": flags = ida_bytes.FF_BYTE size = 1 elif self._value == "dw": flags = ida_bytes.FF_WORD size = 2 elif self._value == "dd": flags = ida_bytes.FF_DWORD size = 4 elif self._value == "dq": flags = ida_bytes.QWORD size = 8 ida_struct.set_member_type(sturct_obj, int(self._offset), flags, ida_nalt.opinfo_t(), size)
def _is_address_of_struct_field(ea): prev_head_ea = idc.prev_head(ea) if is_invalid_ea(prev_head_ea): return False prev_item_size = idc.get_item_size(prev_head_ea) if ea >= (prev_head_ea + prev_item_size): return False # Try to get a type for the last item head. flags = ida_bytes.get_full_flags(ea) ti = ida_nalt.opinfo_t() oi = ida_bytes.get_opinfo(ti, ea, 0, flags) if not oi: return False # Get the size of the struct, and keep going if the suze of the previous # item is a multiple of the struct's size (e.g. one struct or an array # of that struct). struct_size = idc.get_struc_size(oi.tid) if not struct_size or 0 != (prev_item_size % struct_size): return False # Figure out the offset of `ea` within its structure, which may belong to # an array of structures, and then check if that offset is associated with # a named field. arr_index = int((ea - prev_head_ea) / struct_size) struct_begin_ea = (arr_index & struct_size) + prev_head_ea off_in_struct = ea - struct_begin_ea if not idc.get_member_name(oi.tid, off_in_struct): return False field_begin_ea = struct_begin_ea + off_in_struct if field_begin_ea != ea: return False field_size = idc.get_member_size(oi.tid, off_in_struct) if not field_size: return False return True
def _is_address_of_struct_field(ea): prev_head_ea = idc.prev_head(ea) if is_invalid_ea(prev_head_ea): return False prev_item_size = idc.get_item_size(prev_head_ea) if ea >= (prev_head_ea + prev_item_size): return False # Try to get a type for the last item head. flags = ida_bytes.get_full_flags(ea) ti = ida_nalt.opinfo_t() oi = ida_bytes.get_opinfo(ti, ea, 0, flags) if not oi: return False # Get the size of the struct, and keep going if the suze of the previous # item is a multiple of the struct's size (e.g. one struct or an array # of that struct). struct_size = idc.get_struc_size(oi.tid) if not struct_size or 0 != (prev_item_size % struct_size): return False # Figure out the offset of `ea` within its structure, which may belong to # an array of structures, and then check if that offset is associated with # a named field. arr_index = int((ea - prev_head_ea) / struct_size) struct_begin_ea = (arr_index & struct_size) + prev_head_ea off_in_struct = ea - struct_begin_ea if not idc.get_member_name(oi.tid, off_in_struct): return False field_begin_ea = struct_begin_ea + off_in_struct if field_begin_ea != ea: return False field_size = idc.GetMemberSize(oi.tid, off_in_struct) if not field_size: return False return True
def struc_member_changed(self, sptr, mptr): print("struc member changed") extra = {} sname = ida_struct.get_struc_name(sptr.id) soff = 0 if mptr.unimem() else mptr.soff flag = mptr.flag mt = ida_nalt.opinfo_t() is_not_data = ida_struct.retrieve_member_info(mt, mptr) if is_not_data: if flag & ida_bytes.off_flag(): extra["target"] = mt.ri.target extra["base"] = mt.ri.base extra["tdelta"] = mt.ri.tdelta extra["flags"] = mt.ri.flags elif flag & ida_bytes.enum_flag(): extra["serial"] = mt.ec.serial elif flag & ida_bytes.stru_flag(): extra["struc_name"] = ida_struct.get_struc_name(mt.tid) if flag & ida_bytes.strlit_flag(): extra["strtype"] = mt.strtype return 0
def dump(): ret = [] for addr, name in idautils.Names(): flags = ida_bytes.get_flags(addr) if ida_bytes.has_dummy_name(flags) or ida_bytes.has_auto_name( flags) or not ida_bytes.is_data(flags): print('skip auto:', name) continue # Sometimes the auto-generated names don't actually usually have the # right flags set, so skip these auto-looking names. if any( name.startswith(s) for s in ['byte_', 'word_', 'dword_', 'unk_', 'jpt_']): continue # print('%08x' % addr, '%08x' % flags, name, # ida_bytes.is_data(flags)) sz = ida_bytes.get_item_size(addr) if ida_bytes.is_struct(flags): ti = ida_nalt.opinfo_t() ida_bytes.get_opinfo(ti, addr, 0, flags) # itemsize = ida_bytes.get_data_elsize(addr, flags, ti) typ = ida_struct.get_struc_name(ti.tid) else: # itemsize = ida_bytes.get_item_size(addr) typ = None ret.append({ 'address': addr, 'name': name, 'type': typ, 'sz': sz, 'flags': flags, }) return ret
def __call__(self): mt = ida_nalt.opinfo_t() if ida_bytes.is_struct(self.flag): mt.tid = self.extra["id"] if ida_bytes.is_off0(self.flag) or ida_bytes.is_off1(self.flag): mt.ri = ida_nalt.refinfo_t( self.extra["flags"], self.extra["base"], self.extra["target"], self.extra["tdelta"], ) if ida_bytes.is_strlit(self.flag): mt.strtype = self.extra["strtype"] struc = ida_struct.get_struc_id(self.sname) sptr = ida_struct.get_struc(struc) ida_struct.add_struc_member( sptr, self.fieldname, self.offset, self.flag, mt, self.nbytes, )
def struc_member_created(self, sptr, mptr): print("struc member created") extra = {} sname = ida_struct.get_struc_name(sptr.id) fieldname = ida_struct.get_member_name(mptr.id) offset = 0 if mptr.unimem() else mptr.soff flag = mptr.flag nbytes = mptr.eoff if mptr.unimem() else mptr.eoff - mptr.soff mt = ida_nalt.opinfo_t() is_not_data = ida_struct.retrieve_member_info(mt, mptr) if is_not_data: if flag & ida_bytes.off_flag(): extra["target"] = mt.ri.target extra["base"] = mt.ri.base extra["tdelta"] = mt.ri.tdelta extra["flags"] = mt.ri.flags # Is it really possible to create an enum? elif flag & ida_bytes.enum_flag(): extra["serial"] = mt.ec.serial elif flag & ida_bytes.stru_flag(): extra["struc_name"] = ida_struct.get_struc_name(mt.tid) if flag & ida_bytes.strlit_flag(): extra["strtype"] = mt.strtype return 0
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