Beispiel #1
0
 def makeInterface(self, offset):
     idc.SetType(offset, "interfaceType")
     ifaceid = idc.GetStrucIdByName("interfaceType")
     meth_offs = idc.GetMemberOffset(ifaceid, "methods")
     slice_id = idc.GetStrucIdByName("slice")
     size_off = idc.GetMemberOffset(slice_id, "len")
     size = self.stepper.ptr(offset + meth_offs + size_off)
     if size != 0:
         addr = self.getPtr(slice_id, offset + meth_offs, "data")
         idc.SetType(addr, "imethod")
         sz = idc.GetStrucSize(idc.GetStrucIdByName("imethod"))
         self.make_arr(addr, size, sz, "imethod")
         names = self.processIMethods(addr, size)
         # For now only for go1.7
         if names is None:
             return
         name = self.getName(offset)
         while name[0] == "*":
             name = name[1:]
         name = Utils.relaxName(name)
         name = "user_interface_" + name
         # TODO: this is for go1.7 need additional check for other versions
         fields = [("inter", "void *"), ("type", "void *"),
                   ("link", "void *"), ("bad", "__int32"),
                   ("unused", "__int32")]
         for i in names:
             fields.append((i, "void *"))
         itype = [(name, fields)]
         self.settings.structCreator.createTypes(itype)
Beispiel #2
0
 def parseFuncType(self, offset):
     return
     sid = idc.GetStrucIdByName("funcType")
     in_size = idc.Word(offset + idc.GetMemberOffset(sid, "incount"))
     out_size = idc.Word(offset + idc.GetMemberOffset(sid, "outcount"))
     sz = idc.GetStrucSize(sid)
     for i in xrange(in_size + out_size):
         idc.SetType(offset + sz + i * self.stepper.size, "type *")
Beispiel #3
0
 def createUserTypeStruct(self, addr, name, size, self_size):
     fields = []
     sid = idc.GetStrucIdByName("structField")
     sz = idc.GetStrucSize(sid)
     sid_type = idc.GetStrucIdByName("type")
     fields = []
     curr_offset = 0
     idc.MakeComm(addr, name)
     for i in xrange(size):
         fieldname = self.nameFromOffset(
             self.getPtr(sid, addr + i * sz, "Name"))
         type_addr = self.getPtr(sid, addr + i * sz, "typ")
         typename = self.getType(type_addr)
         size = self.getPtr(sid_type, type_addr, "size")
         if fieldname == "" or fieldname is None:
             fieldname = "unused_" + Utils.id_generator()
         offset = self.getStructFieldOffset(sid, addr + i * sz)
         if offset != curr_offset:
             print "Offset missmatch.Got %d expected %d. Adding padding..." % (
                 curr_offset, offset)
             if offset < curr_offset:
                 raise ("Too many bytes already")
             while offset != curr_offset:
                 fields.append(("padding", "char"))
                 curr_offset += 1
         curr_offset += size
         if size != 0:
             offset_kind = idc.GetMemberOffset(sid_type, "kind")
             kind_of_type = self.getKindEnumName(type_addr)
             print kind_of_type
             if kind_of_type == "STRUCT_":  #Disabled for now
                 name_type = self.getName(type_addr)
                 while name_type[0] == "*":
                     name_type = name_type[1:]
                 name_type = Utils.relaxName(name_type)
                 name_type = "ut_" + name_type
                 #print "setting type %s" % name_type
                 fields.append((fieldname, name_type))
             elif kind_of_type == "STRING":
                 fields.append((fieldname, "string"))
             elif kind_of_type == "SLICE":
                 fields.append((fieldname, "slice"))
             elif kind_of_type == "INTERFACE":
                 fields.append((fieldname, "__iface"))
             else:
                 fields.append((fieldname, "char [%d]" % size))
     if curr_offset != self_size:
         print "%x: Structure size mismatch: %x" % (addr, curr_offset)
         if self_size < curr_offset:
             raise ("Too many bytes already")
         while self_size != curr_offset:
             fields.append(("padding", "char"))
             curr_offset += 1
     new_type = [(name, fields)]
     self.settings.structCreator.createTypes(new_type)
     new_type_sid = idc.GetStrucIdByName(name)
     sz = idc.GetStrucSize(new_type_sid)
     if sz != self_size:
         print "%x" % addr
         raise ("Error at creating structure")
Beispiel #4
0
 def fillStruct(self, sid, data):
     for i in data:
         new_type = None
         #(i1, i2, i3) = self.stepper.parseField(i[1])
         name = i[1]
         if name[0] == "*":
             name = name[1:]
         if i[1] != "uintptr":
             i1, i2, i3 = (idc.FF_BYTE | idc.FF_DATA, -1, 1)
         else:
             i1, i2, i3 = self.uintptr
         if name == i[1]:
             new_type = i[1]
         else:
             new_type = name + " *"
         res = idc.AddStrucMember(sid, i[0], -1, i1, i2, i3)
         use_name = i[0]
         if res == -1:  #Bad name
             #print "Bad name %s for struct member" % i[0]
             use_name = i[0] + "_autogen_" + id_generator()
             idc.AddStrucMember(sid, use_name, -1, i1, i2, i3)
         if new_type is not None:
             offset = idc.GetMemberOffset(sid, use_name)
             #print "Setting %s as %s" % (i[0], new_type)
             idc.SetType(idc.GetMemberId(sid, offset), new_type)
Beispiel #5
0
def _populate_wrapper_struct__slices(sid, classinfo):
    """Fill in the members of the wrapper struct."""
    # First add the vtable pointer.
    offset = 0
    vtable_ptr_type = '{}::vtable *'.format(classinfo.classname)
    ret = idau.struct_add_ptr(sid, 'vtable', offset, type=vtable_ptr_type)
    if ret not in (0, idc.STRUC_ERROR_MEMBER_OFFSET):
        _log(0, 'Could not create {}.vtable: {}', classinfo.classname, ret)
        return False
    # Now add all the ::fields structs.
    offset += idau.WORD_SIZE
    for ci in classinfo.ancestors(inclusive=True):
        # Get the sid of the ::fields struct.
        fields_sid = idau.struct_open(ci.classname + '::fields')
        if fields_sid is None:
            _log(0, 'Could not find {}::fields', ci.classname)
            return False
        # If this is a 0-length struct (no fields), skip it.
        size = idc.GetStrucSize(fields_sid)
        if size == 0:
            continue
        # If this is already in the wrapper struct, skip it. This avoids weird
        # STRUC_ERROR_MEMBER_VARLAST errors.
        if idc.GetMemberOffset(sid, ci.classname) != -1:
            continue
        # Add the ::fields struct to the wrapper.
        ret = idau.struct_add_struct(sid, ci.classname, offset, fields_sid)
        if ret != 0:
            _log(0, 'Could not create {}.{}: {}', classinfo.classname,
                 ci.classname, ret)
            return False
        offset += size
    return True
Beispiel #6
0
 def getName(self, offset):
     sid = idc.GetStrucIdByName("type")
     string_addr = offset + idc.GetMemberOffset(sid, "string")
     ptr = self.stepper.ptr(string_addr)
     idc.SetType(ptr, "string")
     name = self.stepper.ptr(ptr)
     return idc.GetString(name)
Beispiel #7
0
def get_struc_offset(ea, opn):
    path = idaapi.tid_array(1)
    delta = idaapi.sval_pointer()
    idaapi.get_stroff_path(ea, opn, path.cast(), delta.cast())
    struct = path[0]
    if idaapi.decode_insn(ea) == 0:
        print 'error in {0}'.format(GetDisasm(ea))
    else:
        op = idaapi.cmd.Operands[opn]
        offset = op.value
        result = []
        idaapi.get_stroff_path(ea, opn, path.cast(), delta.cast())
        struct = path[0]
        while offset:
            member_id = idc.GetMemberId(struct, offset)
            member_name = idc.GetMemberName(member_id)
            field_struct_id = idc.GetMemberStrId(struct, offset)
            if field_struct_id != idc.BADADDR:
                result.append(
                    [field_struct_id,
                     idc.GetStrucName(field_struct_id)])
            else:
                result.append([member_name, idc.GetMemberFlag(struct, offset)])
                return result
            offset -= idc.GetMemberOffset(member_name)
Beispiel #8
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
Beispiel #9
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
Beispiel #10
0
    def makeStructType(self, offset):
        idc.SetType(offset, "structType")
        sid = idc.GetStrucIdByName("structType")
        slice_id = idc.GetStrucIdByName("slice")
        offset_elem = idc.GetMemberOffset(sid, "fields")
        inner_offset = idc.GetMemberOffset(slice_id, "data")
        addr = self.stepper.ptr(offset_elem + offset + inner_offset)

        inner_offset = idc.GetMemberOffset(slice_id, "len")
        size = self.stepper.ptr(offset + offset_elem + inner_offset)
        if size == 0:
            return
        idc.SetType(addr, "structField")
        sz = idc.GetStrucSize(idc.GetStrucIdByName("structField"))
        self.make_arr(addr, size, sz, "structField")
        sid_type = idc.GetStrucIdByName("type")
        size_new_struct = self.getPtr(sid_type, offset, "size")
        for i in xrange(size):
            self.processStructField(addr, i * sz)
Beispiel #11
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
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
Beispiel #13
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
Beispiel #14
0
 def getPtrToThis(self, sid, offset):
     memb_offs = idc.GetMemberOffset(sid, "ptrtothis")
     return idc.Dword(offset + memb_offs)
Beispiel #15
0
 def getKindEnumName(self, addr):
     struc_id = idc.GetStrucIdByName("type")
     offset_kind = idc.GetMemberOffset(struc_id, "kind")
     kind = idc.Byte(addr + offset_kind) & 0x1f
     return self.settings.typer.standardEnums[0][1][kind]
Beispiel #16
0
 def getPtr(self, sid, addr, name):
     name_off = idc.GetMemberOffset(sid, name)
     return self.stepper.ptr(addr + name_off)
Beispiel #17
0
 def getDword(self, sid, addr, name):
     name_off = idc.GetMemberOffset(sid, name)
     return idc.Dword(addr + name_off)