def get_args(f): local_variables = [] arguments = [] current = local_variables frame = idc.GetFrame(f) arg_string = "" if frame == None: return None start = idc.GetFirstMember(frame) end = idc.GetLastMember(frame) count = 0 max_count = 10000 args_str = "" while start <= end and count <= max_count: size = idc.GetMemberSize(frame, start) count = count + 1 if size == None: start = start + 1 continue name = idc.GetMemberName(frame, start) start += size if name in [" r", " s"]: # Skip return address and base pointer current = arguments continue arg_string += " " + name current.append(name) if len(arguments) == 0: arguments.append("void") return arguments
def getStackVars(ea, base=-1): # type: (int, int) -> list[(str, int)] """ Gets the stack variables associted with the function at ea If no base is specified, the offsets don't include the base calculation in them :param ea: the address of the function :param base: the stack base, must obtain to compute the offsets relative to it :return: a list of tuples, the stack variable name and its offset """ stackVars = [] id = idc.GetFrame(ea) firstMember = idc.GetFirstMember(id) # if the function has stack variables if firstMember != idaapi.BADADDR and firstMember != -1: # build up disasm based on stack vars lastMember = idc.GetLastMember(id) i = firstMember # Stack can be offset, first member might not be found at index 0, and all offsets must be adjusted by this foundFirstElement = False stackOffset = 0 while i <= lastMember: name = idc.GetMemberName(id, i) off = idc.GetMemberOffset( id, name ) # this is the offset in the struct... which isn't always consistent! size = idc.GetMemberSize(id, i) # append if varname is found (sometimes, None is returned because the variables are not in the next index) if name: # first variable found! this is the stack of the stack variables! if not foundFirstElement: stackOffset = i foundFirstElement = True if base == -1: # absolute offsets appended stackVars.append((name, off - stackOffset)) else: # base-relative offsets appended stackVars.append((name, base - off - stackOffset)) # sometimes, for some reason, the offset for stack variables does not follow linearly if size: i += size else: # reach next var, which might not be one size unit after the last... while not idc.GetMemberSize(id, i) and i <= lastMember: i += 1 return stackVars
def get_last_member(sid): if idaapi.IDA_SDK_VERSION <= 699: id = idc.GetLastMember(sid) else: id = idc.last_member(sid) return id
def make_struc_member(self, object_version, address, member_type=ya.OBJECT_TYPE_STRUCT_MEMBER): struc_object_id = object_version.get_parent_object_id() struc_id = 0 try: struc_id = self.struc_ids[struc_object_id] except: return is_union = struc_id in self.union_ids offset = address if is_union: last_offset = idc.GetLastMember(struc_id) if last_offset == idc.BADADDR: last_offset = -1 if last_offset < offset: for i in xrange(last_offset + 1, offset + 1): idc.AddStrucMember(struc_id, "yaco_filler_%d" % i, 0, idc.FF_BYTE | idc.FF_DATA, -1, 1) # ensure that 'offset' fields are present member_size = object_version.get_size() member_name = object_version.get_name() flags = object_version.get_object_flags() if idc.isStruct(flags): # if the sub field is a struct, it must have a single Xref field with the struct object id try: sub_struc_object_id = object_version.getXRefIdsAt(0, 0)[0] sub_struc_id = self.struc_ids[sub_struc_object_id] # logger.debug("%20s: adding sub member at offset 0x%08X, # size=0x%08X (sub=0x%.016X, size=0x%08X) with name %s" % # ( # idc.GetStrucName(struc_id), offset, member_size, sub_struc_id, # idc.GetStrucSize(sub_struc_id), object_version.get_name() # )) sub_struc_size = idc.GetStrucSize(sub_struc_id) if sub_struc_size == 0: logger.error( "%20s: adding sub member at offset 0x%08X, size=0x%08X " "(sub=0x%.016X, size=0x%08X) with name %s : sub struc size is ZERO" % (idc.GetStrucName(struc_id), offset, member_size, sub_struc_id, idc.GetStrucSize(sub_struc_id), object_version.get_name())) else: nitems = member_size / sub_struc_size YaToolIDATools.SetStrucmember(struc_id, member_name, offset, flags, sub_struc_id, nitems) except KeyError: logger.error( "Error while looking for sub struc in struc %s, offset 0x%08X (field name='%s')" % (self.hash_provider.hash_to_string(struc_object_id), offset, object_version.get_name())) traceback.print_exc() elif idc.isEnum0(flags): # an enum is applied here try: sub_enum_object_id = object_version.getXRefIdsAt(0, 0)[0] sub_enum_id = self.enum_ids[sub_enum_object_id] name_ok = idc.SetMemberName(struc_id, offset, member_name) if name_ok is not True: logger.debug( "Error while setting member name (enum) : " "(struc=%s, member=%s, offset=0x%08X, mflags=%d, msize=%d, tid=0x%016X" % (name_ok, idc.GetStrucName(struc_id), member_name, offset, flags, member_size, sub_struc_id)) else: sub_enum_size = idc.GetEnumWidth(sub_enum_id) if sub_enum_size == 0: sub_enum_size = member_size nitems = member_size / sub_enum_size ret = idc.SetMemberType(struc_id, offset, flags, sub_enum_id, nitems) if ret == 0: logger.debug( "Error while setting member type (enum) : " "(struc=%s, member=%s, offset=0x%08X, mflags=%d, msize=%d, tid=0x%016X" % (ret, idc.GetStrucName(struc_id), member_name, offset, flags, member_size, sub_struc_id)) except KeyError: logger.error( "Error while looking for sub enum in struc %s, offset 0x%08X (field name='%s')" % (struc_object_id, offset, member_name)) traceback.print_exc() else: # logger.debug("%20s: adding member at offset 0x%08X, size=0x%08X with name %s" % # ( # idc.GetStrucName(struc_id), offset, member_size, object_version.get_name() # )) tid = -1 if idc.isASCII(flags): logger.debug( "object: %s : %s" % (self.hash_provider.hash_to_string( object_version.get_id()), object_version.get_name())) try: tid = object_version.get_string_type() except KeyError: tid = idc.ASCSTR_C name_ok = idc.SetMemberName(struc_id, offset, member_name) if name_ok is not True: logger.debug( "Error while setting member name :" + " (struc_id=0x%08X, struc=%s, member=%s, offset=0x%08X, mflags=%d, msize=%d)" % (struc_id, idc.GetStrucName(struc_id), member_name, offset, flags, member_size)) else: item_size = YaToolIDATools.get_field_size(flags, tid) nitems = member_size / item_size # IDA BUG : 4-byte chars are stored as 2 double words, thus me must # multiply nitem by 2! ret = idc.SetMemberType(struc_id, offset, flags, tid, nitems) if ret == 0: logger.debug( "Error while setting member type :" + " (struc=%s, member=%s, offset=0x%08X, mflags=%d, msize=%d)" % (idc.GetStrucName(struc_id), member_name, offset, flags, member_size)) try: repeatable_headercomment = self.sanitize_comment_to_ascii( object_version.get_header_comment(True)) idc.SetMemberComment(struc_id, offset, repeatable_headercomment, 1) except KeyError: pass try: nonrepeatable_headercomment = self.sanitize_comment_to_ascii( object_version.get_header_comment(False)) idc.SetMemberComment(struc_id, offset, nonrepeatable_headercomment, 0) except KeyError: pass member_id = idc.GetMemberId(struc_id, offset) self.set_struct_member_type(object_version, member_id) if object_version.get_type() == ya.OBJECT_TYPE_STRUCT_MEMBER: self.strucmember_ids[object_version.get_id()] = member_id
def clear_struc_fields(self, struc_id, struc_size, xref_keys, is_union=False, member_type=ya.OBJECT_TYPE_STRUCT_MEMBER, name_offset=0): idc.BeginTypeUpdating(idc.UTP_STRUCT) last_offset = idc.GetLastMember(struc_id) # get existing member offsets field_offsets = set() for (xref_offset, xref_operand) in xref_keys: field_offsets.add(xref_offset) new_offsets = set() struc = idaapi.get_struc(struc_id) # create missing members first (prevent from deleting all members) for offset in field_offsets: member = idaapi.get_member(struc, offset) if member is not None and member.soff < offset: # we have a member above this member that is too big and contain this member # clear it! if DEBUG_EXPORTER: logger.debug( "reduce field : set_member_type(0x%08X, 0x%08X), overlapping 0x%08X", struc_id, member.soff, offset) idaapi.set_member_type(struc, member.soff, idc.FF_BYTE, None, 1) member = idaapi.get_member(struc, offset) if member is None or idaapi.get_member_name(member.id) is None: new_offsets.add(offset) member_name = YaToolIDATools.get_default_struc_member_name( member_type, offset, name_offset) if offset == last_offset and offset == struc_size: field_size = 0 else: field_size = 1 if DEBUG_EXPORTER: logger.debug( "AddStrucMember(0x%08X, '%s', 0x%08X, idc.FF_BYTE, -1, 0x%08X), name_offset=%d", struc_id, member_name, offset, field_size, name_offset) retval = idc.AddStrucMember(struc_id, member_name, offset, idc.FF_BYTE, -1, field_size) if retval != 0: logger.error( "Error %d with idc.AddStrucMember(0x%08X, '%s', 0x%08X," "idc.FF_BYTE, -1, 0x%08X), name_offset=%d", retval, struc_id, member_name, offset, field_size, name_offset) elif DEBUG_EXPORTER: logger.debug("Member exists : (0x%08X, '%s', 0x%08X, 0x%08X)", struc_id, idc.GetMemberName(struc_id, offset), offset, idc.GetMemberSize(struc_id, offset)) kept_offsets = field_offsets - new_offsets # clear kept members # split the loop since we will modify the structure while iterating offsets = set() for (offset, member_name) in YaToolIDATools.struc_member_list( struc_id, is_union): offsets.add(offset) for offset in offsets: if offset in kept_offsets: # This member already existed and is kept if offset == last_offset and offset == struc_size: # this is the last field, and it is a variable sized structure field_size = 0 else: field_size = 1 if member_type == ya.OBJECT_TYPE_STRUCT_MEMBER: strucmember_id = self.hash_provider.get_struc_member_id( struc_id, offset) elif member_type == ya.OBJECT_TYPE_STACKFRAME_MEMBER: strucmember_id = self.hash_provider.get_stackframe_member_object_id( struc_id, offset) else: logger.error("Bad member_type : %d" % member_type) if strucmember_id not in self.strucmember_ids: # It is not necessary to clear the member if it is presnet in the resolved_objects if DEBUG_EXPORTER: logger.debug( "SetStrucmember(0x%08X, None, 0x%08X, idc.FF_BYTE, -1, 0x%08X, name_offset=%s)", struc_id, offset, field_size, name_offset) YaToolIDATools.SetStrucmember(struc_id, None, offset, idc.FF_BYTE, -1, field_size, member_type=member_type, name_offset=name_offset) idc.SetMemberComment(struc_id, offset, "", 0) idc.SetMemberComment(struc_id, offset, "", 1) elif offset not in new_offsets: if (member_type != ya.OBJECT_TYPE_STACKFRAME_MEMBER or not idaapi.is_special_member( idc.GetMemberId(struc_id, offset))): if DEBUG_EXPORTER: logger.debug( "DelStrucMember(0x%08X, 0x%08X) (=%s:%s)", struc_id, offset, idc.GetStrucName(struc_id), idc.GetMemberName(struc_id, offset)) idc.DelStrucMember(struc_id, offset) else: # in new_offsets : just created pass idc.EndTypeUpdating(idc.UTP_STRUCT)
def argCount(self): end = idc.GetFunctionAttr(self.addr, idc.FUNCATTR_END) start = idc.GetFunctionAttr(self.addr, idc.FUNCATTR_START) frame = idc.GetFrame(start) localv = idc.GetFunctionAttr(self.addr, idc.FUNCATTR_FRSIZE) frameSize = idc.GetFrameSize(start) #idc.GetStrucSize(frame) reg_off = 0 local_count = 0 arg_count = 0 sid = idc.GetFrame(self.addr) if sid: firstM = idc.GetFirstMember(sid) lastM = idc.GetLastMember(sid) arg_count = 0 if lastM - firstM > 0x1000: return for i in xrange(firstM, lastM): mName = idc.GetMemberName(sid, i) mSize = idc.GetMemberSize(sid, i) mFlag = idc.GetMemberFlag(sid, i) off = idc.GetMemberOffset(sid, mName) #print "%s: %d, %x, off=%x" % (mName, mSize, mFlag, off) if mName == " r": reg_off = off # XXX: just store the data, dont loop twice. for i in xrange(firstM, lastM): mName = idc.GetMemberName(sid, i) mSize = idc.GetMemberSize(sid, i) mFlag = idc.GetMemberFlag(sid, i) off = idc.GetMemberOffset(sid, mName) if off <= reg_off: local_count += 1 elif off > reg_off and reg_off != 0: arg_count += 1 if arg_count > 0: return arg_count / 4 elif arg_count == 0: return 0 # offset to return try: ret = idc.GetMemberOffset(frame, " r") except: if frameSize > localv: return (frameSize - localv) / 4 # error getting function frame (or none exists) return -1 if (ret < 0): if frameSize > localv: return (frameSize - localv) / 4 return -1 firstArg = ret + 4 args = frameSize - firstArg numArgs = args / 4 return numArgs