def qualify_stack_struct_references(s, struct_vars): for (nam, tid) in struct_vars: p = re.compile("\+" + nam + "\.([^\]]+)\]") if p.search(s) != None: return p.sub("+" + nam + "]." + idaapi.get_struc_name(tid) + ".\g<1>", s) return s
def __init__(self, name): sid = -1 nametype = type(name) if nametype is str: self.name = name sid = idaapi.get_struc_id(name) elif nametype is int or nametype is long: sid = name self.name = idaapi.get_struc_name(sid) self.sid = sid ssize = 0 memberlist = None offs = 0 if not warnBad(sid): struc = idaapi.get_struc(sid) ssize = idaapi.get_struc_size(sid) #memberqty = idc.GetMemberQty(sid) memberqty = struc.memqty memberlist = [None] * memberqty for i in range(0, memberqty): #memberlist.append(idamember(sid, offs)) memberlist[i] = idamember(sid, offs) offs = idaapi.get_struc_next_offset(struc, offs) self.size = ssize self.members = memberlist
def tid_is_struc(tid): # get_struc_name return name for struc or enum tid_name = idaapi.get_struc_name(tid) if idaapi.get_struc_id(tid_name) != idc.BADADDR: return True return False
def qualify_stack_struct_references(s, struct_vars): for (nam, tid) in struct_vars: p = re.compile('\+' + nam + '\.([^\]]+)\]') if p.search(s) != None: return p.sub( '+' + nam + '].' + idaapi.get_struc_name(tid) + '.\g<1>', s) return s
def changing_struc(self, *args): """ changing_struc(self, sptr) -> int """ sptr, = args logger.debug("Changing structure %s", idaapi.get_struc_name(sptr.id)) return ida_idp.IDB_Hooks.changing_struc(args)
def deleting_struc(self, *args): """ deleting_struc(self, sptr) -> int """ sptr, = args name = idaapi.get_struc_name(sptr.id) struc_id = self.skel_conn.get_struct_by_name(name) self.skel_conn.delete_struct(struc_id) return ida_idp.IDB_Hooks.deleting_struc(self, *args)
def foreachStructureNameAndSize(struct_iterator, *additionalArgs): assertFunction(struct_iterator) first = int(getFirstStructIdx()) last = int(getLastStructIdx()) for i in range(first, last): sid = idaapi.get_struc_by_idx(i) if not struct_iterator(idaapi.get_struc_name(sid), idaapi.get_struc_size(sid), *additionalArgs): break
def loadStructs(): idx = idaapi.get_first_struc_idx() existingStructs = [] while idx != idc.BADADDR: tid = idaapi.get_struc_by_idx(idx) existingStructs.append(idaapi.get_struc_name(tid)) idx = idaapi.get_next_struc_idx(idx) existingStructs.sort() return existingStructs
def struc_cmt_changed(self, struc, *args): self.pre_hook() if LOG_IDB_EVENTS: self.debug_event("struc_cmt_changed for id 0x%08X (%s)" % (struc, idaapi.get_struc_name(struc))) sidx = idc.GetStrucIdx(struc) if sidx is None or sidx == idc.BADADDR or not sidx: # this is either a stackframe, or a member of a structure fullname = idaapi.get_struc_name(struc) if "." in fullname: # it is a member id, retreive the struc id st = idaapi.get_member_struc(fullname) struc = st.id else: # it is a stackframe id pass hooks.ida.struc_updated(struc) return idaapi.IDB_Hooks.struc_cmt_changed(self, struc, *args)
def struc_created(self, *args): """ args -> id """ struct_name = idaapi.get_struc_name(args[0]) self.skel_conn.create_struct(struct_name) g_logger.debug("New structure %s created", struct_name) return idaapi.IDB_Hooks.struc_created(self, *args)
def struc_member_created(self, *args): """ struc_member_created(self, sptr, mptr) -> int """ sptr, mptr = args g_logger.debug("New member for structure %s", idaapi.get_struc_name(sptr.id)) m_start_offset = mptr.soff # g_logger.debug("Member start offset 0x%x", m_start_offset) # g_logger.debug("Member end offset 0x%x", m_end_offset) struct_name = idaapi.get_struc_name(sptr.id) struct_id = self.skel_conn.get_struct_by_name(struct_name) mname = idaapi.get_member_name2(mptr.id) self.skel_conn.create_struct_member(struct_id, mname, m_start_offset) return idaapi.IDB_Hooks.struc_member_created(self, *args)
def struc_created(self, *args): """ args -> id """ struct_name = idaapi.get_struc_name(args[0]) self.skel_conn.create_struct(struct_name) logger.debug("New structure %s created", struct_name) return ida_idp.IDB_Hooks.struc_created(self, *args)
def struc_cmt_changed(self, id, repeatable_cmt): fullname = idaapi.get_struc_name(id) if "." in fullname: sname, smname = fullname.split(".", 1) else: sname = fullname smname = '' cmt = idaapi.get_struc_cmt(id, repeatable_cmt) self._send_event( StrucCmtChangedEvent(sname, smname, cmt, repeatable_cmt)) return 0
def applied_structs(): dataseg = sark.Segment(name='seg004') for line in dataseg.lines: ti = idaapi.opinfo_t() f = idaapi.getFlags(line.ea) if idaapi.get_opinfo(line.ea, 0, f, ti): struct_name = idaapi.get_struc_name(ti.tid) if struct_name: print (line.ea - dataseg.ea, struct_name) yield line.ea - dataseg.ea, struct_name
def struc_member_created(self, *args): """ struc_member_created(self, sptr, mptr) -> int """ sptr, mptr = args logger.debug("New member for structure %s", idaapi.get_struc_name(sptr.id)) m_start_offset = mptr.soff # logger.debug("Member start offset 0x%x", m_start_offset) # logger.debug("Member end offset 0x%x", m_end_offset) struct_name = idaapi.get_struc_name(sptr.id) struct_id = self.skel_conn.get_struct_by_name(struct_name) mname = idaapi.get_member_name(mptr.id) self.skel_conn.create_struct_member(struct_id, mname, m_start_offset) return ida_idp.IDB_Hooks.struc_member_created(self, *args)
def __init__(self, struc): self.mems = [] self.src = struc self.tid = struc.id self.name = idaapi.get_struc_name(self.tid) self.deps = set([]) for i in range(struc.memqty): m = struc.get_member(i) self.mems.append(member.create_member_node(m, struc)) d = util.member_str_id(m, struc) if d != None: self.deps = self.deps | set([d])
def renaming_struc_member(self, *args): """ renaming_struc_member(self, sptr, mptr, newname) -> int """ sptr, mptr, newname = args logger.debug("Renaming struct member %s of struct %s", mptr.id, sptr.id) sname = idaapi.get_struc_name(sptr.id) oldname = idaapi.get_member_name(mptr.id) struct_id = self.skel_conn.get_struct_by_name(sname) mid = self.skel_conn.get_member_by_name(struct_id, oldname) self.skel_conn.rename_struct_member(struct_id, mid, newname) return ida_idp.IDB_Hooks.renaming_struc_member(self, *args)
def get_stack_var_name(self, var): """Get the name of a stack variable and return it parsed.""" var_name = idaapi.get_struc_name(var.id) if not isinstance(var_name, str): return None res = self.stack_name_parse.match(var_name) if res: return res.group(1) else: #raise Exception('Cannot get operand name.') #print '*** Cannot get operand name!!! ***' return None
def _f1(idx, ctx): import idc import ida_bytes obj = ctx.get_memref('stroff') print "%x" % obj.ea ti = idaapi.opinfo_t() f = idc.GetFlags(obj.ea) if idaapi.get_opinfo(obj.ea, 0, f, ti): print("tid=%08x - %s" % (ti.tid, idaapi.get_struc_name(ti.tid))) print "Offset: {}".format(obj.offset) import ida_struct obj2 = ctx.get_obj('fcn') print "%x" % obj2.addr name_str = ida_name.get_name(obj2.addr) print "Name {}".format(name_str) ida_struct.set_member_name(ida_struct.get_struc(ti.tid), obj.offset, name_str)
def add_dref(self, ea, struct_id, flags, member_id=None): if ((ea, struct_id, member_id) not in self.xrefs or flags < self.xrefs[(ea, struct_id, member_id)]): self.xrefs[(ea, struct_id, member_id)] = flags strname = idaapi.get_struc_name(struct_id) if member_id is None: idaapi.add_dref(ea, struct_id, flags) log.debug((" 0x{:X} \t" "struct {} \t" "{}").format(ea, strname, flags_to_str(flags))) else: idaapi.add_dref(ea, member_id, flags) log.debug((" 0x{:X} \t" "member {}.{} \t" "{}").format(ea, strname, idaapi.get_member_name(member_id), flags_to_str(flags))) self.save()
def struct_member_error(err, sid, name, offset, size): """Create and format a struct member exception. Args: err: The error value returned from struct member creation sid: The struct id name: The member name offset: Memeber offset size: Member size Returns: A ``SarkErrorAddStructMemeberFailed`` derivative exception, with an informative message. """ exception, msg = STRUCT_ERROR_MAP[err] struct_name = idaapi.get_struc_name(sid) return exception( ('AddStructMember(struct="{}", member="{}", offset={}, size={}) ' 'failed: {}').format(struct_name, name, offset, size, msg))
def rename(self, ea, new_name): """ This function only records information about the element *before* it is renamed """ if idaapi.is_member_id(ea): name = idaapi.get_member_fullname(ea) elif idaapi.get_struc(ea) is not None: name = idaapi.get_struc_name(ea) elif idaapi.get_enum_idx(ea) != idc.BADADDR: name = idaapi.get_enum_name(ea) elif idaapi.get_enum_idx(idaapi.get_enum_member_enum(ea)) != idc.BADADDR: # this is an enum member id enum_id = idaapi.get_enum_member_enum(ea) name = idaapi.get_enum_name(enum_id) + "." + idaapi.get_enum_member_name(ea) else: name = idc.Name(ea) hooks.current_rename_infos[ea] = name return 0
def add_dref(self, ea, struct_id, flags, member_id=None): if (ea, struct_id, member_id) not in self.xrefs or flags < self.xrefs[ (ea, struct_id, member_id)]: self.xrefs[(ea, struct_id, member_id)] = flags strname = idaapi.get_struc_name(struct_id) if member_id is None: idaapi.add_dref(ea, struct_id, flags) log.debug(" %08X \tstruct %s \t%s", ea, strname, flags_to_str(flags)) else: idaapi.add_dref(ea, member_id, flags) log.debug( " %08X \tmember %s.%s \t%s", ea, strname, idaapi.get_member_name(member_id), flags_to_str(flags), ) self.save()
def get_struc_id_from_member_if(member_id): try: return member_struc_ids[member_id] except KeyError: idx = idc.GetFirstStrucIdx() while idx != idc.BADADDR: struc_id = idc.GetStrucId(idx) if idc.IsUnion(struc_id): offset = idc.GetFirstMember(struc_id) while offset != idc.BADADDR: smember_id = idc.GetMemberId(struc_id, offset) if smember_id == member_id: member_struc_ids[member_id] = struc_id return struc_id offset = idc.GetStrucNextOff(struc_id, offset) idx = idc.GetNextStrucIdx(idx) logger.error("Could not find struc id from member id 0x%08X (name=%s)" % (member_id, idaapi.get_struc_name(member_id))) return None
def struc_member_created(self, sptr, mptr): extra = {} sname = idaapi.get_struc_name(sptr.id) fieldname = idaapi.get_member_name2(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 = idaapi.opinfo_t() is_not_data = idaapi.retrieve_member_info(mt, mptr) if is_not_data: if idaapi.isOff0(flag) or idaapi.isOff1(flag): extra['target'] = mt.ri.target extra['base'] = mt.ri.base extra['tdelta'] = mt.ri.tdelta extra['flags'] = mt.ri.flags self._send_event( StrucMemberCreatedEvent(sname, fieldname, offset, flag, nbytes, extra)) # Is it really possible to create an enum? elif idaapi.isEnum0(flag): extra['serial'] = mt.ec.serial self._send_event( StrucMemberCreatedEvent(sname, fieldname, offset, flag, nbytes, extra)) elif idaapi.isStruct(flag): extra['id'] = mt.tid self._send_event( StrucMemberCreatedEvent(sname, fieldname, offset, flag, nbytes, extra)) elif idaapi.isASCII(flag): extra['strtype'] = mt.strtype self._send_event( StrucMemberCreatedEvent(sname, fieldname, offset, flag, nbytes, extra)) else: self._send_event( StrucMemberCreatedEvent(sname, fieldname, offset, flag, nbytes, extra)) return 0
def get_decl_for_member(mem, struc): if idaapi.isStruct(mem.flag): return idaapi.get_struc_name(util.member_str_id(mem, struc)) else: return get_decl_for_prim(mem.flag)
def name(self): return idaapi.get_struc_name(self.id)
def name(id): '''Return the name of the structure identified by ``id``.''' return idaapi.get_struc_name(id)
def struc_created(self, tid): name = idaapi.get_struc_name(tid) is_union = idaapi.is_union(tid) self._send_event(StrucCreatedEvent(tid, name, is_union)) return 0
def struc_renamed(self, sptr): new_name = idaapi.get_struc_name(sptr.id) self._send_event(StrucRenamedEvent(sptr.id, new_name)) return 0
def name(id, name=None): """set/get the name of a particular structure""" if name is None: return idaapi.get_struc_name(id) return idaapi.set_struc_name(id, name)
def name(self): '''Return the name for the structure.''' return idaapi.get_struc_name(self.id)
def make_data(self, object_version, address): size = 0 try: size = object_version.get_size() except KeyError: pass flags = None try: flags = object_version.get_object_flags() except KeyError: pass if size == 0: idc.MakeUnkn(address, idc.DOUNK_EXPAND) else: if flags is not None: if idc.isASCII(flags): try: str_type = object_version.get_string_type() YaToolIDATools.check_and_set_str_type(str_type) except KeyError: pass idc.MakeStr(address, address + size) idc.SetFlags(address, flags) if idc.isStruct(flags): found = False for xref_offset_operand, xref_id_attr in object_version.get_xrefed_id_map( ).iteritems(): (xref_offset, xref_operand) = xref_offset_operand for xref_hash, xref_attrs in xref_id_attr: if xref_hash in self.struc_ids: struc_id = self.struc_ids[xref_hash] if DEBUG_EXPORTER: logger.debug( "making unknown from 0x%08X to 0x%08X" % (address, address + size)) idaapi.do_unknown_range( address, size, idc.DOUNK_DELNAMES) # idc.MakeUnkn(address, DOUNK_SIMPLE | idc.DOUNK_DELNAMES) # for i in xrange(1, size): # MakeName(address + i, "") # idc.MakeUnkn(address + i, DOUNK_SIMPLE | idc.DOUNK_DELNAMES) # idc.MakeStructEx uses idaapi.doStruct (but asks for name while # we already have the struc id) if DEBUG_EXPORTER: logger.debug( "Making struc at %s : %s (sizeof(%s)=0x%08X, size=0x%08X, flags=0x%08X" % (self.yatools.address_to_hex_string( address), self.yatools.address_to_hex_string( struc_id), idaapi.get_struc_name(struc_id), idc.GetStrucSize(struc_id), size, flags)) idc.SetCharPrm(idc.INF_AUTO, True) idc.Wait() if idaapi.doStruct(address, size, struc_id) == 0: if DEBUG_EXPORTER: logger.warning("Making struc failed") idc.SetCharPrm(idc.INF_AUTO, False) # idc.SetFlags(address, flags) found = True else: logger.error( "bad struc flags : idc.isStruct is true but no xref available for object %s" % self.hash_provider.hash_to_string( object_version.get_id())) if not found: logger.error( "bad struc flags : idc.isStruct is true " "but no struc available for object %s (%s)" % (self.hash_provider.hash_to_string( object_version.get_id()), object_version.get_name())) else: idc.MakeData(address, flags & (idc.DT_TYPE | idc.MS_0TYPE), size, 0) else: idc.MakeData(address, idc.FF_BYTE, size, 0) self.make_name(object_version, address, False) self.set_type(object_version, address)
def get_struc_enum_xrefs_at_ea(base_address, ea, strucs, enums, stackframe, func): # structures # TODO: fix use a lot of CPU !!!! (call twice) if idaapi.decode_insn(ea) == 0: logger.warning("Invalid instruction at %x." % (ea)) # TODO: check that it is a good thing not to exit """ Code Example : .text:000000010003D73A E8 CD FB 01+ call _CxxThrowException .text:000000010003D73A 00 ; --------------------------------------------------------------------------- .text:000000010003D73F CC db 0CCh .text:000000010003D73F sub_10003D6D8 endp .text:000000010003D73F .text:000000010003D740 CC CC CC CC+ db 8 dup(0CCh) .text:000000010003D748 90 90 90 90+ align 10h 0xCC can be used as padding : it is recognized as an illegal instruction by IDA The instruction should be just ignored, no need to exit """ # sys.exit(-1) else: # TODO: add 2 xrefs instead of one in struc operands """ following instruction : cmp eax, struc_1.field_1 should add 2 xrefs : (in XML format) <xrefs offset="0x0000004A" operand="0x00000001" delta="X">UUID(struc_1)</xrefstrucs> <xrefs offset="0x0000004A" operand="0x00000001">UUID(struc_1.field_1)</xrefstrucs> This way, if field_1 is moved inside struc_1 (between 2 different versions of binary), it will still be identified """ op_index = 0 for op in idaapi.cmd.Operands: if op.type != idaapi.o_void: ti = idaapi.opinfo_t() f = idc.GetFlags(ea) if isEnum(f, op_index): if idaapi.get_opinfo(ea, op_index, f, ti): name = idc.GetEnumName(ti.ec.tid) if name is not None: # name can be None if the enum was deleted try: ll = enums[ea - base_address] except KeyError: ll = list() enums[ea - base_address] = ll ll.append((op_index, ti.ec.tid, name)) elif isStroff(f, op_index): if idaapi.get_opinfo(ea, op_index, f, ti): struc_path = ti.path.ids struc_delta = ti.path.delta path_len = ti.path.len try: struc_xrefs = strucs[ea - base_address] except KeyError: struc_xrefs = list() strucs[ea - base_address] = struc_xrefs for path_idx in xrange(0, path_len): field_id = struc_path[path_idx] if path_len > 1: logger.debug("adding path_idx=%d, id=0x%08X, name=%s" % ( path_idx, field_id, idaapi.get_struc_name(field_id))) struc_dict = None if struc_delta != 0: struc_dict = {'delta': "0x%08X" % struc_delta} if path_idx != 0: if struc_dict is None: struc_dict = {'path_idx': "0x%08X" % path_idx} else: struc_dict['path_idx'] = "0x%08X" % path_idx struc_xrefs.append((op_index, struc_dict, field_id)) # # STACK VARIABLE # # check if op if var stack if func is not None and ( ((op_index == 0) and idaapi.isStkvar0(f)) or ((op_index == 1) and idaapi.isStkvar1(f)) ): t = idaapi.get_stkvar(op, op.addr) if t is not None: (member, actval) = t if ea - base_address not in stackframe: stackframe[ea - base_address] = list() stackframe[ea - base_address].append((op_index, member, idaapi.get_spd(func, ea))) op_index += 1