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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
 def fields(self, reload=False):
     if reload or not self._fields:
         self._fields = {}
         m = 0
         while True:
             if m >= idc.GetStrucSize(self.id):
                 break
             n = idc.GetMemberName(self.id, m)
             if n == idc.BADADDR:
                 break
             sz = idc.GetMemberSize(self.id, m)
             mid = idc.GetMemberId(self.id, m)
             tp = idc.GetType(mid)
             fld = {
                 'offset': m,
                 'id': mid,
                 'name': n,
                 'size': sz,
                 'type': [tp, None]
             }
             if n != '':
                 fld['type'][1] = idc.GetMemberFlag(self.id, m)
             self._fields[m] = fld
             m = idc.GetStrucNextOff(self.id, m)
             if m == idc.BADADDR:
                 break
     return self._fields
Ejemplo n.º 4
0
def build_stack_args(f):
  stackArgs = dict()
  name = idc.Name(f)
  end = idc.GetFunctionAttr(f, idc.FUNCATTR_END)
  _locals = idc.GetFunctionAttr(f, idc.FUNCATTR_FRSIZE)
  _uses_bp = 0 != (idc.GetFunctionFlags(f) & idc.FUNC_FRAME)
  frame = idc.GetFrame(f)
  if frame is None:
    return stackArgs

  func_type = idc.GetType(f)
  if (func_type is not None) and ("(" in func_type):
    args = func_type[ func_type.index('(')+1: func_type.rindex(')') ]
    args_list = [ x.strip() for x in args.split(',')]
    if "..." in args_list:
      return stackArgs

  if name in RECOVER_DEBUG_FL:
    return stackArgs

  #grab the offset of the stored frame pointer, so that
  #we can correlate offsets correctly in referent code
  # e.g., EBP+(-0x4) will match up to the -0x4 offset
  delta = idc.GetMemberOffset(frame, " s")
  if -1 == delta:
    #indicates that it wasn't found. Unsure exactly what to do
    # in that case, punting for now
    delta = 0

  offset = idc.GetFirstMember(frame)
  while -1 != _signed_from_unsigned(offset):
    memberName = idc.GetMemberName(frame, offset)
    if memberName is None:
      # gaps in stack usage are fine, but generate trash output
      # gaps also could indicate a buffer that IDA doesn't recognize
      offset = idc.GetStrucNextOff(frame, offset)
      continue
    if (memberName == " r" or memberName == " s"):
      #the return pointer and start pointer, who cares
      offset = idc.GetStrucNextOff(frame, offset)
      continue
    memberSize = idc.GetMemberSize(frame, offset)
    if offset >= delta:
      offset = idc.GetStrucNextOff(frame, offset)
      continue
    memberFlag = idc.GetMemberFlag(frame, offset)
    #TODO: handle the case where a struct is encountered (FF_STRU flag)
    flag_str = _get_flags_from_bits(memberFlag)
    stackArgs[offset-delta] = {"name":memberName,
                               "size":memberSize,
                               "flags":flag_str,
                               "writes":list(),
                               "referent":list(),
                               "reads":list(),
                               "safe": False}
    offset = idc.GetStrucNextOff(frame, offset)

  return stackArgs
Ejemplo n.º 5
0
def build_stack_variable(func_ea):
  stack_vars = dict()

  frame = idc.get_func_attr(func_ea, idc.FUNCATTR_FRAME)
  if not frame:
    return stack_vars

  f_name = get_symbol_name(func_ea)
  #grab the offset of the stored frame pointer, so that
  #we can correlate offsets correctly in referent code
  # e.g., EBP+(-0x4) will match up to the -0x4 offset
  delta = idc.GetMemberOffset(frame, " s")
  if delta == -1:
    delta = 0

  if f_name not in _FUNC_UNSAFE_LIST:
    offset = idc.get_first_member(frame)
    while -1 != _signed_from_unsigned(offset):
      member_name = idc.get_member_name(frame, offset)
      if member_name is None:
        offset = idc.get_next_offset(frame, offset)
        continue
      if (member_name == " r" or member_name == " s"):
        offset = idc.get_next_offset(frame, offset)
        continue

      member_size = idc.GetMemberSize(frame, offset)
      if offset >= delta:
        offset = idc.get_next_offset(frame, offset)
        continue

      member_flag = idc.GetMemberFlag(frame, offset)
      flag_str = _get_flags_from_bits(member_flag)
      member_offset = offset-delta
      stack_vars[member_offset] = {"name": member_name,
                                  "size": member_size,
                                  "flags": flag_str,
                                  "writes": list(),
                                  "referent": list(),
                                  "reads": list(),
                                  "safe": False }

      offset = idc.get_next_offset(frame, offset)
  else:
    offset = idc.get_first_member(frame)
    frame_size = idc.get_func_attr(func_ea, idc.FUNCATTR_FRSIZE)
    flag_str = ""
    member_offset = _signed_from_unsigned(offset) - delta
    stack_vars[member_offset] = {"name": f_name,
                                 "size": frame_size,
                                 "flags": flag_str,
                                 "writes": list(),
                                 "referent": list(),
                                 "reads": list(),
                                 "safe": False }

  return stack_vars
Ejemplo n.º 6
0
 def setStrucPntr(self, sid, ofs, name, tp=None):
     vnm = idc.GetMemberName(sid, ofs)
     if not vnm or vnm in (idc.BADADDR, -1):
         idc.AddStrucMember(sid, name, ofs, idc.FF_QWRD, -1, 8)
         vnm = name
     if vnm != name:
         idc.SetMemberName(sid, ofs, name)
     sz = idc.GetMemberSize(sid, ofs)
     if sz != 8:
         idc.SetMemberType(sid, ofs, idc.FF_QWRD, -1, 1)
     mid = idc.GetMemberId(sid, ofs)
     t = idc.GetType(mid) or ''
     if tp and t.replace(' ', '') != tp.replace(' ', ''):
         idc.SetType(mid, tp + ';')
Ejemplo n.º 7
0
def set_struct_offsets(offsets, sid):
    for offset in offsets:
        try:
            add_struct_member(sid, offset_name(offset), offset.offset,
                              offset.size)
        except exceptions.SarkErrorStructMemberName:
            # Get the offset of the member with the same name
            existing_offset = idc.GetMemberOffset(sid, offset_name(offset))
            if offset.offset == existing_offset:
                pass
            else:
                raise
        except exceptions.SarkErrorStructMemberOffset:
            # Get the size of the member at the same offset
            if offset.size == idc.GetMemberSize(sid, offset.offset):
                # If they are the same, all is well.
                pass
Ejemplo n.º 8
0
def StructMembers(sid):
    """
    Get a list of structure members information.

    @param sid: ID of the structure.

    @return: List of tuples (offset, name, size)

    @note: If 'sid' does not refer to a valid structure,
           an exception will be raised.
    """
    off = idc.GetFirstMember(sid)
    if off == idaapi.BADNODE:
        raise Exception("No structure with ID: 0x%x" % sid)
    members = idc.GetMemberQty(sid)
    for idx in range(0, members):
        yield (off, idc.GetMemberName(sid, off), idc.GetMemberSize(sid, off))
        off = idc.GetStrucNextOff(sid, off)
Ejemplo n.º 9
0
Archivo: hooks.py Proyecto: Spl3en/ipad
 def struc_member_created(self, struct, membr):
     sid = struct.id
     mid = membr.id
     moff = membr.soff
     flag = membr.flag
     size = idc.GetMemberSize(sid, moff)
     sname = idc.GetStrucName(sid)
     mname = idc.GetMemberName(sid, moff)
     idx = idc.GetStrucIdx(sid)
     self.ctrl._handle_action({
         'action': 'struct_member_created',
         'struct': idx,
         'member': mid,
         'sname': sname,
         'mname': mname,
         'off': moff,
         'flag': flag,
         'size': size
     })
     return 0
Ejemplo n.º 10
0
def StructMembers(sid):
    """
    Get a list of structure members information (or stack vars if given a frame).

    @param sid: ID of the structure.

    @return: List of tuples (offset, name, size)

    @note: If 'sid' does not refer to a valid structure,
           an exception will be raised.
    @note: This will not return 'holes' in structures/stack frames;
           it only returns defined structure members.
    """
    m = idc.GetFirstMember(sid)
    if m == -1:
        raise Exception("No structure with ID: 0x%x" % sid)
    while (m != idaapi.BADADDR):
        name = idc.GetMemberName(sid, m)
        if name:
            yield (m, name, idc.GetMemberSize(sid, m))
        m = idc.GetStrucNextOff(sid, m)
Ejemplo n.º 11
0
    def __init__(self, sid, offs):
        self.offs = offs
        #sid = struc
        name = None
        substruct = -1
        size = 0

        if not warnBad(sid):
            #struc = idaapi.get_struc(sid)
            #member = idaapi.get_member(struc, offs)

            name = idc.GetMemberName(sid, offs)
            substruct = idc.GetMemberStrId(sid, offs)
            size = idc.GetMemberSize(sid, offs)
            #name = idaapi.get_member_name(member.id)
            #substruct = idaapi.get_sptr(member)
            #size = idaapi.get_member_size(member)

        self.name = name
        self.struc = substruct
        self.size = size
Ejemplo n.º 12
0
    def check_field(self, sid, ftype, strid, offset, size, name):
        if ftype is None:
            for i in range(offset, offset + size):
                self.assertIsNone(idc.GetMemberName(sid, i))
                self.assertEqual(idc.GetMemberFlag(sid, i), -1)
            return

        try:
            self.assertNotEqual(idc.GetMemberName(sid, offset - 1), name)
        except:
            pass
        for k in range(offset, offset + size):
            self.assertEqual(idc.GetMemberName(sid, k), name)
            self.assertEqual(idc.GetMemberSize(sid, k), size)
            self.assertEqual(idc.GetMemberFlag(sid, k) & idaapi.DT_TYPE, ftype & 0xFFFFFFFF)
            if strid != -1:
                st = idaapi.get_struc(sid)
                mb = idaapi.get_member(st, offset)
                op = idaapi.opinfo_t()
                idaapi.retrieve_member_info(op, mb)
                self.assertEqual(op.tid, strid)
        self.assertNotEqual(idc.GetMemberName(sid, offset + size), name)
Ejemplo n.º 13
0
    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)
Ejemplo n.º 14
0
    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
Ejemplo n.º 15
0
 def size(self):
     "size of the member"
     return idc.GetMemberSize(self.parent.sid, self.struct_offset)