Пример #1
0
    def frame(cls, ea):
        '''Iterate through each field within the frame belonging to the function `ea`.'''
        F = func.by(ea)

        # iterate through all of the frame's members
        try:
            res = func.frame(F)
        except internal.exceptions.MissingTypeOrAttribute:
            logging.info(
                u"{:s}.frame({:#x}) : Skipping function at {:#x} due to a missing frame."
                .format('.'.join([__name__, cls.__name__]), ea, ea))
            return

        for member in res.members:
            # if ida has named it and there's no comment, then skip
            if lvarNameQ(member.name) and not member.comment:
                continue

            # if it's a structure, then the type is the structure name
            if isinstance(member.type, struc.structure_t):
                logging.debug(
                    u"{:s}.frame({:#x}) : Storing structure-based type as name for field {:+#x} with tne type {!s}."
                    .format('.'.join([__name__, cls.__name__]), ea,
                            member.offset,
                            internal.utils.string.repr(member.type)))
                type = member.type.name

            # otherwise, the type is a tuple that we can serializer
            else:
                type = member.type

            # otherwise, it's just a regular field. so we can just save what's important.
            yield member.offset, (member.name, type, member.comment)
        return
Пример #2
0
def apply_frame(ea, frame, **tagmap):
    F = fn.frame(ea)
    for offset, (name, type, comment) in frame.viewitems():
        try:
            member = F.by_offset(offset)
        except LookupError:
            logging.warn(
                "{:s}.apply_frame({:x}, ...) : Unable to find frame member at {:+#x}. Skipping application of data to it. : {!r}"
                .format(__name__, ea, offset, (name, type, comment)),
                exc_info=True)
            continue

        if member.name != name:
            if any(not member.name.startswith(n)
                   for n in ('arg_', 'var_', ' ')):
                print >> output, "{:x} : {:+x} : Renaming frame member with new name. : {!r} : {!r}".format(
                    ea, offset, member.name, name)
            member.name = name

        d, state = map(internal.comment.decode, (comment, member.comment))
        for k in d.viewkeys() & state.viewkeys():
            if state[k] == d[k]: continue
            print >> output, "{:x} : {:+x} : Overwriting frame member tag with new value. : {!r} : {!r}".format(
                ea, offset, state[k], d[k])
        mapstate = {tagmap.get(k, k): v for k, v in d.iteritems()}
        state.update(mapstate)
        member.comment = internal.comment.encode(state)

        if type is not None:
            member.type = type
        continue
    return
Пример #3
0
    def frame(cls, ea):
        '''Iterate through each field within the frame belonging to the function `ea`.'''
        F = func.by(ea)

        # iterate through all of the frame's members
        try:
            res = func.frame(F)
        except internal.exceptions.MissingTypeOrAttribute:
            logging.info(u"{:s}.frame({:#x}) : Skipping function at {:#x} due to a missing frame.".format('.'.join((__name__, cls.__name__)), ea, ea))
            return

        for member in res.members:
            # if ida has named it and there's no comment, then skip
            if lvarNameQ(member.name) and not member.comment:
                continue

            # if it's a structure, then the type is the structure name
            if isinstance(member.type, struc.structure_t):
                logging.debug(u"{:s}.frame({:#x}) : Storing structure-based type as name for field {:+#x} with tne type {!s}.".format('.'.join((__name__, cls.__name__)), ea, member.offset, internal.utils.string.repr(member.type)))
                type = member.type.name

            # otherwise, the type is a tuple that we can serializer
            else:
                type = member.type

            # otherwise, it's just a regular field. so we can just save what's important.
            yield member.offset, (member.name, type, member.comment)
        return
Пример #4
0
def frame(ea):
    for member in fn.frame(ea).members:
        if any(member.name.startswith(n)
               for n in ('arg_', 'var_', ' ')) and not member.comment:
            continue
        if isinstance(member.type, st.structure_t) or any(
                isinstance(n, st.structure_t) for n in member.type):
            logging.warn(
                "{:s}.frame({:#x}) : Skipping structure-based type for field {:+#x} : {!r}"
                .format(__name__, ea, member.offset, member.type))
            yield member.offset, (member.name, None, member.comment)
            continue
        yield member.offset, (member.name, member.type, member.comment)
    return
Пример #5
0
    def frame(cls, ea, frame, **tagmap):
        '''Apply the fields from `frame` back into the function at `ea`.'''
        tagmap_output = u", {:s}".format(u', '.join(
            u"{:s}={:s}".format(internal.utils.string.escape(k),
                                internal.utils.string.escape(v))
            for k, v in tagmap.items())) if tagmap else ''

        # nothing to do here, so we gtfo
        if not frame:
            return

        # grab the function's frame
        try:
            F = func.frame(ea)

        # if no frame exists for the function, we'll need to create it
        except internal.exceptions.MissingTypeOrAttribute:

            # first we figure out the bounds of our members in order to figure out the the lvars and args sizes
            framekeys = {item for item in frame.keys()}
            minimum, maximum = min(framekeys), max(framekeys)

            # calculate the size of regs by first finding everything that begins at offset 0
            res = sorted(offset for offset in framekeys if offset >= 0)

            # now we look for anything near offset 0 that begins with a space (which should be a register)
            regs = 0
            for offset in res:
                name, type, _ = frame[offset]
                if not name.startswith(' '): break

                # if type is a string, then treat it as a structure so we can calculate a size
                if isinstance(type, six.string_types):
                    try:
                        st = struc.by(type)
                    except internal.exceptions.StructureNotFoundError:
                        logging.fatal(
                            u"{:s}.frame({:#x}, ...{:s}): Unable to find structure \"{:s}\" for member {:+#x} in order to calculate register size for function at {:+#x}. Using register size of {:+#x}."
                            .format('.'.join([__name__, cls.__name__]), ea,
                                    tagmap_output,
                                    internal.utils.string.escape(type, '"'),
                                    offset, ea, regs))
                        break
                    type = [(int, 1), st.size]

                # extract the size components and calculate the total number of bytes
                realtype, reallength = type if isinstance(
                    type, builtins.list) else [type, 1]
                _, realsize = realtype
                cb = realsize * reallength

                # add it to the current aggregate of the register size
                regs += cb

            # finally we can create the frame
            logging.warning(
                u"{:s}.frame({:#x}, ...{:s}) : Creating a new frame for function {:#x} with the parameters lvars={:+#x} regs={:+#x} args={:+#x}."
                .format('.'.join([__name__, cls.__name__]), ea, tagmap_output,
                        ea, abs(minimum), regs, abs(maximum)))
            F = func.frame.new(ea, abs(minimum), regs, abs(maximum) - regs)

        # iterate through our dictionary of members
        for offset, (name, type, comment) in frame.items():

            # first try and locate the member
            try:
                member = F.members.by_offset(offset)
            except:
                member = None

            # if we didn't find a member, then try and add it with what we currently know
            if member is None:
                logging.warning(
                    u"{:s}.frame({:#x}, ...{:s}) : Unable to find frame member at {:+#x}. Attempting to create the member with the name (\"{:s}\"), type ({!s}), and comment (\"{:s}\")."
                    .format('.'.join([__name__, cls.__name__]), ea,
                            tagmap_output, offset,
                            internal.utils.string.escape(name, '"'),
                            internal.utils.string.repr(type),
                            internal.utils.string.escape(comment, '"')))
                try:
                    member = F.members.add(name, type, offset)
                except:
                    logging.fatal(
                        u"{:s}.frame({:#x}, ...{:s}) : Unable to add frame member at {:+#x}. Skipping application of the name (\"{:s}\"), type ({!s}), and comment (\"{:s}\") to it."
                        .format('.'.join([__name__, cls.__name__]), ea,
                                tagmap_output, offset,
                                internal.utils.string.escape(name, '"'),
                                internal.utils.string.repr(type),
                                internal.utils.string.escape(comment, '"')))
                    continue

            # check if the name has changed or is different in some way
            if member.name != name:
                log = logging.info if lvarNameQ(
                    member.name) else logging.warning
                log(u"{:s}.frame({:#x}, ...{:s}) : Renaming frame member {:+#x} from the name \"{:s}\" to \"{:s}\"."
                    .format('.'.join([__name__, cls.__name__]), ea,
                            tagmap_output, offset,
                            internal.utils.string.escape(member.name, '"'),
                            internal.utils.string.escape(name, '"')))
                member.name = name

            # check what's going to be overwritten with different values prior to doing it
            state, res = (internal.comment.decode(cmt)
                          for cmt in [member.comment, comment])

            # transform the new tag state using the tagmap
            new = {
                tagmap.get(name, name): value
                for name, value in res.items()
            }

            # check if the tag mapping resulted in the deletion of a tag
            if len(new) != len(res):
                reskeys, newkeys = ({item
                                     for item in items.keys()}
                                    for items in [res, new])
                for name in reskeys - newkeys:
                    logging.warning(
                        u"{:s}.frame({:#x}, ...{:s}) : Refusing requested tag mapping as it results in the tag \"{:s}\" overwriting tag \"{:s}\" for the frame member {:+#x}. The value {!s} would be overwritten by {!s}."
                        .format(
                            '.'.join([__name__,
                                      cls.__name__]), ea, tagmap_output,
                            internal.utils.string.escape(name, '"'),
                            internal.utils.string.escape(tagmap[name], '"'),
                            offset, internal.utils.string.repr(res[name]),
                            internal.utils.string.repr(res[tagmap[name]])))
                pass

            # warn the user about what's going to be overwritten prior to doing it
            statekeys, newkeys = ({item
                                   for item in items.keys()}
                                  for items in [state, new])
            for name in statekeys & newkeys:
                if state[name] == new[name]: continue
                logging.warning(
                    u"{:s}.frame({:#x}, ...{:s}) : Overwriting tag \"{:s}\" for frame member {:+#x} with new value {!s}. The old value was {!s}."
                    .format('.'.join([__name__, cls.__name__]), ea,
                            tagmap_output,
                            internal.utils.string.escape(name, '"'), offset,
                            internal.utils.string.repr(new[name]),
                            internal.utils.string.repr(state[name])))

            # now we can update the current dictionary
            mapstate = {
                name: value
                for name, value in new.items()
                if state.get(name, dummy) != value
            }
            state.update(mapstate)

            # convert it back to a multi-lined comment and assign it
            member.comment = internal.comment.encode(state)

            # if the type is a string, then figure out which structure to use
            if isinstance(type, six.string_types):
                try:
                    member.type = struc.by(type)
                except internal.exceptions.StructureNotFoundError:
                    logging.warning(
                        u"{:s}.frame({:#x}, ...{:s}): Unable to find structure \"{:s}\" for member at {:+#x}. Skipping it."
                        .format('.'.join([__name__,
                                          cls.__name__]), ea, tagmap_output,
                                internal.utils.string.escape(type, '"'),
                                offset))

            # otherwise, it's a pythonic tuple that we can just assign
            else:
                member.type = type
            continue
        return
Пример #6
0
    def frame(cls, ea, frame, **tagmap):
        '''Apply the fields from `frame` back into the function at `ea`.'''
        tagmap_output = u", {:s}".format(u', '.join(u"{:s}={:s}".format(internal.utils.string.escape(k), internal.utils.string.escape(v)) for k, v in six.iteritems(tagmap))) if tagmap else ''

        # nothing to do here, so we gtfo
        if not frame:
            return

        # grab the function's frame
        try:
            F = func.frame(ea)

        # if no frame exists for the function, we'll need to create it
        except internal.exceptions.MissingTypeOrAttribute:

            # first we figure out the bounds of our members in order to figure out the the lvars and args sizes
            minimum, maximum = min(six.viewkeys(frame)), max(six.viewkeys(frame))

            # calculate the size of regs by first finding everything that begins at offset 0
            res = sorted(offset for offset in six.viewkeys(frame) if offset >= 0)

            # now we look for anything near offset 0 that begins with a space (which should be a register)
            regs = 0
            for offset in res:
                name, type, _ = frame[offset]
                if not name.startswith(' '): break

                # if type is a string, then treat it as a structure so we can calculate a size
                if isinstance(type, basestring):
                    try:
                        st = struc.by(type)
                    except internal.exceptions.StructureNotFoundError:
                        logging.fatal(u"{:s}.frame({:#x}, ...{:s}): Unable to find structure \"{:s}\" for member {:+#x} in order to calculate register size for function at {:+#x}. Using register size of {:+#x}.".format('.'.join((__name__, cls.__name__)), ea, tagmap_output, internal.utils.string.escape(type, '"'), offset, ea, regs))
                        break
                    type = [(int, 1), st.size]

                # extract the size components and calculate the total number of bytes
                realtype, reallength = type if isinstance(type, builtins.list) else [type, 1]
                _, realsize = realtype
                cb = realsize * reallength

                # add it to the current aggregate of the register size
                regs += cb

            # finally we can create the frame
            logging.warn(u"{:s}.frame({:#x}, ...{:s}) : Creating a new frame for function {:#x} with the parameters lvars={:+#x} regs={:+#x} args={:+#x}.".format('.'.join((__name__, cls.__name__)), ea, tagmap_output, ea, abs(minimum), regs, abs(maximum)))
            F = func.frame.new(ea, abs(minimum), regs, abs(maximum) - regs)

        # iterate through our dictionary of members
        for offset, (name, type, comment) in six.iteritems(frame):

            # first try and locate the member
            try:
                member = F.members.by_offset(offset)
            except:
                member = None

            # if we didn't find a member, then try and add it with what we currently know
            if member is None:
                logging.warn(u"{:s}.frame({:#x}, ...{:s}) : Unable to find frame member at {:+#x}. Attempting to create the member with the name (\"{:s}\"), type ({!s}), and comment (\"{:s}\").".format('.'.join((__name__, cls.__name__)), ea, tagmap_output, offset, internal.utils.string.escape(name, '"'), internal.utils.string.repr(type), internal.utils.string.escape(comment, '"')))
                try:
                    member = F.members.add(name, type, offset)
                except:
                    logging.fatal(u"{:s}.frame({:#x}, ...{:s}) : Unable to add frame member at {:+#x}. Skipping application of the name (\"{:s}\"), type ({!s}), and comment (\"{:s}\") to it.".format('.'.join((__name__, cls.__name__)), ea, tagmap_output, offset, internal.utils.string.escape(name, '"'), internal.utils.string.repr(type), internal.utils.string.escape(comment, '"')))
                    continue

            # check if the name has changed or is different in some way
            if member.name != name:
                log = logging.info if lvarNameQ(member.name) else logging.warn
                log(u"{:s}.frame({:#x}, ...{:s}) : Renaming frame member {:+#x} from the name \"{:s}\" to \"{:s}\".".format('.'.join((__name__, cls.__name__)), ea, tagmap_output, offset, internal.utils.string.escape(member.name, '"'), internal.utils.string.escape(name, '"')))
                member.name = name

            # check what's going to be overwritten with different values prior to doing it
            state, res = map(internal.comment.decode, (member.comment, comment))

            # transform the new tag state using the tagmap
            new = { tagmap.get(name, name) : value for name, value in six.viewitems(res) }

            # check if the tag mapping resulted in the deletion of a tag
            if len(new) != len(res):
                for name in six.viewkeys(res) - six.viewkeys(new):
                    logging.warn(u"{:s}.frame({:#x}, ...{:s}) : Refusing requested tag mapping as it results in the tag \"{:s}\" overwriting tag \"{:s}\" for the frame member {:+#x}. The value {!s} would be overwritten by {!s}.".format('.'.join((__name__, cls.__name__)), ea, tagmap_output, internal.utils.string.escape(name, '"'), internal.utils.string.escape(tagmap[name], '"'), offset, internal.utils.string.repr(res[name]), internal.utils.string.repr(res[tagmap[name]])))
                pass

            # warn the user about what's going to be overwritten prior to doing it
            for name in six.viewkeys(state) & six.viewkeys(new):
                if state[name] == new[name]: continue
                logging.warn(u"{:s}.frame({:#x}, ...{:s}) : Overwriting tag \"{:s}\" for frame member {:+#x} with new value {!s}. The old value was {!s}.".format('.'.join((__name__, cls.__name__)), ea, tagmap_output, internal.utils.string.escape(name, '"'), offset, internal.utils.string.repr(new[name]), internal.utils.string.repr(state[name])))

            # now we can update the current dictionary
            mapstate = { name : value for name, value in six.iteritems(new) if state.get(name, dummy) != value }
            state.update(mapstate)

            # convert it back to a multi-lined comment and assign it
            member.comment = internal.comment.encode(state)

            # if the type is a string, then figure out which structure to use
            if isinstance(type, basestring):
                try:
                    member.type = struc.by(type)
                except internal.exceptions.StructureNotFoundError:
                    logging.warn(u"{:s}.frame({:#x}, ...{:s}): Unable to find structure \"{:s}\" for member at {:+#x}. Skipping it.".format('.'.join((__name__, cls.__name__)), ea, tagmap_output, internal.utils.string.escape(type, '"'), offset))

            # otherwise, it's a pythonic tuple that we can just assign
            else:
                member.type = type
            continue
        return
Пример #7
0
    def frame(cls, ea, frame, **tagmap):
        '''Apply the fields from `frame` back into the function at `ea`.'''
        tagmap_output = ", {:s}".format(', '.join(
            "{:s}={:s}".format(k, v)
            for k, v in six.iteritems(tagmap))) if tagmap else ''

        F = func.frame(ea)
        for offset, (name, type, comment) in six.iteritems(frame):
            try:
                member = F.by_offset(offset)
            except internal.exceptions.MemberNotFoundError:
                logging.warn(
                    "{:s}.frame({:#x}, ...{:s}) : Unable to find frame member at {:+#x}. Skipping application of the name ({!r}), type ({!r}), and comment ({!r}) to it."
                    .format('.'.join((__name__, cls.__name__)), ea,
                            tagmap_output, offset, name, type, comment))
                continue

            if member.name != name:
                if any(not member.name.startswith(n)
                       for n in ('arg_', 'var_', ' ')):
                    logging.warn(
                        "{:s}.frame({:#x}, ...{:s}) : Renaming frame member {:+#x} from the name {!r} to {!r}."
                        .format('.'.join((__name__, cls.__name__)), ea,
                                tagmap_output, offset, member.name, name))
                member.name = name

            # check what's going to be overwritten with different values prior to doing it
            state, res = map(internal.comment.decode,
                             (member.comment, comment))

            # transform the new tag state using the tagmap
            new = {
                tagmap.get(name, name): value
                for name, value in six.viewitems(res)
            }

            # check if the tag mapping resulted in the deletion of a tag
            if len(new) != len(res):
                for name in six.viewkeys(res) - six.viewkeys(new):
                    logging.warn(
                        "{:s}.frame({:#x}, ...{:s}) : Refusing requested tag mapping as it results in the tag {!r} overwriting tag {!r} for the frame member {:+#x}. The value {!r} would be overwritten by {!r}."
                        .format('.'.join((__name__, cls.__name__)), ea,
                                tagmap_output, name, tagmap[name], offset,
                                res[name], res[tagmap[name]]))
                pass

            # warn the user about what's going to be overwritten prior to doing it
            for name in six.viewkeys(state) & six.viewkeys(new):
                if state[name] == new[name]: continue
                logging.warn(
                    "{:s}.frame({:#x}, ...{:s}) : Overwriting tag {!r} for frame member {:+#x} with new value {!r}. The old value was {!r}."
                    .format('.'.join(
                        (__name__, cls.__name__)), ea, tagmap_output, name,
                            offset, new[name], state[name]))

            # now we can update the current dictionary
            mapstate = {
                name: value
                for name, value in six.iteritems(new)
                if state.get(name, dummy) != value
            }
            state.update(mapstate)

            # convert it back to a multi-lined comment and assign it
            member.comment = internal.comment.encode(state)

            # if the type is a string, then figure out which structure to use
            if isinstance(type, basestring):
                try:
                    member.type = struc.by(type)
                except internal.exceptions.StructureNotFoundError:
                    logging.warn(
                        "{:s}.frame({:#x}, ...{:s}): Unable to find structure {!r} for member at {:+#x}. Skipping it."
                        .format('.'.join((__name__, cls.__name__)), ea,
                                tagmap_output, type, offset))

            # otherwise, it's a pythonic tuple that we can just assign
            else:
                member.type = type
            continue
        return