def map(ea, size, newea, **kwds):
    """Map `size` bytes of data from `ea` into a new segment at `newea`.

    The keyword `name` can be used to name the segment.
    """

    # grab the file offset and the data we want
    fpos, data = idaapi.get_fileregion_offset(ea), database.read(ea, size)
    if len(data) != size:
        raise E.ReadOrWriteError(
            u"{:s}.map({:#x}, {:+#x}, {:#x}{:s}) : Unable to read {:#x} bytes from {:#x}."
            .format(
                __name__, ea, size, newea,
                u", {:s}".format(utils.string.kwargs(kwds)) if kwds else '',
                size, ea))

    # rebase the data to the new address
    res = idaapi.mem2base(data, newea, fpos)
    if not res:
        raise E.DisassemblerError(
            u"{:s}.map({:#x}, {:+#x}, {:#x}{:s}) : Unable to remap {:#x}:{:+#x} to {:#x}."
            .format(
                __name__, ea, size, newea,
                u", {:s}".format(utils.string.kwargs(kwds)) if kwds else '',
                ea, size, newea))

    # now we can create the new segment
    return new(newea, size, kwds.get("name", "map_{:x}".format(ea)))
示例#2
0
def new(name, flags=0):
    '''Create an enumeration with the specified `name` and `flags` using ``idaapi.add_enum``.'''
    idx = count()
    res = idaapi.add_enum(idx, utils.string.to(name), flags)
    if res == idaapi.BADADDR:
        raise E.DisassemblerError(u"{:s}.new({!r}, flags={:d}) : Unable to create enumeration named \"{:s}\".".format(__name__, name, flags, utils.string.escape(name, '"')))
    return res
示例#3
0
    def add(cls, enum, name, value, **bitmask):
        """Add an enumeration member `name` with the specified `value` to the enumeration `enum`.

        If the int, `bitmask`, is specified then used it as the bitmask for the enumeration.
        """
        eid = by(enum)
        bmask = bitmask.get('bitmask', idaapi.BADADDR & mask(eid))

        res = interface.tuplename(name) if isinstance(name, tuple) else name
        ok = idaapi.add_enum_member(eid, utils.string.to(res), value, bmask)

        err = {
            getattr(idaapi, item): item
            for item in [
                'ENUM_MEMBER_ERROR_NAME', 'ENUM_MEMBER_ERROR_VALUE',
                'ENUM_MEMBER_ERROR_ENUM', 'ENUM_MEMBER_ERROR_MASK',
                'ENUM_MEMBER_ERROR_ILLV'
            ]
        }
        if ok in err.keys():
            raise E.DisassemblerError(
                u"{:s}.add({:#x}, {!r}, {:#x}{:s}) : Unable to add member to enumeration due to error {:s}({:d})."
                .format(
                    '.'.join([__name__, cls.__name__]), eid, name, value,
                    u", {:s}".format(utils.string.kwargs(bitmask))
                    if bitmask else '', err[ok], ok))
        return eid
示例#4
0
 def remove(cls, mid):
     '''Remove the enumeration member with the given `mid`.'''
     eid, value = cls.parent(mid), cls.value(mid)
     # XXX: is a serial of 0 valid?
     res = idaapi.del_enum_member(eid, value, 0, idaapi.BADADDR & cls.mask(mid))
     if not res:
         raise E.DisassemblerError(u"{:s}.member.remove({:#x}) : Unable to remove member from enumeration.".format(__name__, mid))
     return res
示例#5
0
def new(name, flags=0):
    '''Create an enumeration with the specified ``name`` and ``flags`` using `idaapi.add_enum`.'''
    idx = count()
    res = idaapi.add_enum(idx, name, flags)
    if res == idaapi.BADADDR:
        raise E.DisassemblerError(
            "{:s}.new({!r}, flags={:d}) : Unable to create enumeration named {:s}."
            .format(__name__, name, flags, name))
    return res
示例#6
0
def __save_file(filename, ea, size, offset=0):
    path = os.path.abspath(filename)
    of = idaapi.fopenWB(path)
    if not of:
        raise E.DisassemblerError(
            "{:s}.save_file({!r}, {:#x}, {:+#x}) : Unable to open target file \"{:s}\"."
            .format(__name__, filename, ea, size, path))
    res = idaapi.base2file(of, offset, ea, ea + size)
    idaapi.eclose(of)
    return res
示例#7
0
def __load_file(filename, ea, size, offset=0):
    path = os.path.abspath(filename)
    res = idaapi.open_linput(path, False)
    if not res:
        raise E.DisassemblerError(
            "{:s}.load_file({!r}, {:#x}, {:+#x}) : Unable to create loader_input_t from path \"{:s}\"."
            .format(__name__, filename, ea, size, path))
    ok = idaapi.file2base(res, offset, ea, ea + size, False)
    idaapi.close_linput(res)
    return ok
def __load_file(filename, ea, size, offset=0):
    path = os.path.abspath(filename)

    # use IDA to open up the file contents
    # XXX: does IDA support unicode file paths?
    res = idaapi.open_linput(path, False)
    if not res:
        raise E.DisassemblerError(
            u"{:s}.load_file({!r}, {:#x}, {:+#x}) : Unable to create an `idaapi.loader_input_t` from path \"{:s}\"."
            .format(__name__, filename, ea, size, path))

    # now we can write the file into the specified address as a segment
    ok = idaapi.file2base(res, offset, ea, ea + size, False)
    idaapi.close_linput(res)
    return ok
def __save_file(filename, ea, size, offset=0):
    path = os.path.abspath(filename)

    # use IDA to open up a file to write to
    # XXX: does IDA support unicode file paths?
    of = idaapi.fopenWB(path)
    if not of:
        raise E.DisassemblerError(
            u"{:s}.save_file({!r}, {:#x}, {:+#x}) : Unable to open target file \"{:s}\"."
            .format(__name__, filename, ea, size,
                    utils.string.escape(path, '"')))

    # now we can write the segment into the file we opened
    res = idaapi.base2file(of, offset, ea, ea + size)
    idaapi.eclose(of)
    return res
示例#10
0
def map(ea, size, newea, **kwds):
    """Map `size` bytes of data from `ea` into a new segment at `newea`.

    The keyword `name` can be used to name the segment.
    """
    fpos, data = idaapi.get_fileregion_offset(ea), database.read(ea, size)
    if len(data) != size:
        raise E.ReadOrWriteError(
            "{:s}.map({:#x}, {:+#x}, {:#x}) : Unable to read {:#x} bytes from {:#x}."
            .format(__name__, ea, size, newea, size, ea))
    res = idaapi.mem2base(data, newea, fpos)
    if not res:
        raise E.DisassemblerError(
            "{:s}.map({:#x}, {:+#x}, {:#x}) : Unable to remap {:#x}:{:+#x} to {:#x}."
            .format(__name__, ea, size, newea, ea, size, newea))
    return new(newea, size, kwds.get("name', 'map_{:x}".format(ea)))
示例#11
0
    def add(cls, enum, name, value, **bitmask):
        """Add an enumeration member `name` with the specified `value` to the enumeration `enum`.

        If the int, `bitmask`, is specified then used it as the bitmask for the enumeration.
        """
        eid = by(enum)
        bmask = bitmask.get('bitmask', idaapi.BADADDR & mask(eid))

        res = interface.tuplename(name) if isinstance(name, tuple) else name
        ok = idaapi.add_enum_member(eid, res, value, bmask)

        err = {
            getattr(idaapi, n): n
            for n in ('ENUM_MEMBER_ERROR_NAME', 'ENUM_MEMBER_ERROR_VALUE',
                      'ENUM_MEMBER_ERROR_ENUM', 'ENUM_MEMBER_ERROR_MASK',
                      'ENUM_MEMBER_ERROR_ILLV')
        }
        if ok in err.viewkeys():
            raise E.DisassemblerError(
                "{:s}.add({:#x}, {!r}, {:#x}, bitmask={!r}) : Unable to add member to enumeration due to error {:s}({:d})."
                .format('.'.join((__name__, cls.__name__)), eid, name, value,
                        bitmask, err[ok], ok))
        return eid
def new(offset, size, name, **kwds):
    """Create a segment at `offset` with `size` and name it according to `name`.

    The keyword `bits` can be used to specify the bit size of the segment
    The keyword `comb` can be used to specify any flags (idaapi.sc*)
    The keyword `align` can be used to specify paragraph alignment (idaapi.sa*)
    The keyword `org` specifies the origin of the segment (must be paragraph aligned due to ida)
    """
    res = utils.string.to(name)

    # find the segment according to the name specified by the user
    seg = idaapi.get_segm_by_name(res)
    if seg is not None:
        raise E.DuplicateItemError(
            u"{:s}.new({:#x}, {:+#x}, \"{:s}\"{:s}) : A segment with the specified name (\"{:s}\") already exists."
            .format(
                __name__, offset, size, utils.string.escape(name, '"'),
                u", {:s}".format(utils.string.kwargs(kwds)) if kwds else '',
                utils.string.escape(name, '"')))

    # FIXME: use disassembler default bit length instead of 32
    bits = kwds.get(
        'bits',
        32 if idaapi.getseg(offset) is None else idaapi.getseg(offset).abits())

    ## create a selector with the requested origin
    if bits == 16:
        org = kwds.get('org', 0)
        if org & 0xf > 0:
            raise E.InvalidTypeOrValueError(
                u"{:s}.new({:#x}, {:+#x}, {!r}{:s}) : The specified origin ({:#x}) is not aligned to the size of a paragraph (0x10)."
                .format(
                    __name__, offset, size, name, u", {:s}".format(
                        utils.string.kwargs(kwds)) if kwds else '', org))

        para = offset // 16
        sel = idaapi.allocate_selector(para)
        idaapi.set_selector(sel,
                            (para - kwds.get('org', 0) // 16) & 0xffffffff)

    ## if the user specified a selector, then use it
    elif 'sel' in kwds or 'selector' in kwds:
        sel = kwds.get('sel', kwds.get('selector',
                                       idaapi.find_free_selector()))

    ## choose the paragraph size defined by the user
    elif 'para' in kwds or 'paragraphs' in kwds:
        para = kwds.get('paragraph', kwds.get('para', 1))
        sel = idaapi.setup_selector(para)

    ## find a selector that is 1 paragraph size,
    elif idaapi.get_selector_qty():
        sel = idaapi.find_selector(1)

    # otherwise find a free one and set it.
    else:
        sel = idaapi.find_free_selector()
        idaapi.set_selector(sel, 1)

    # populate the segment_t for versions of IDA prior to 7.0
    if idaapi.__version__ < 7.0:
        seg = idaapi.segment_t()
        seg.startEA, seg.endEA = offset, offset + size

    # now for versions of IDA 7.0 and newer
    else:
        seg = idaapi.segment_t()
        seg.start_ea, seg.end_ea = offset, offset + size

    # assign the rest of the necessary attributes
    seg.sel = sel
    seg.bitness = {16: 0, 32: 1, 64: 2}[bits]
    seg.comb = kwds.get('comb', idaapi.scPub)  # public
    seg.align = kwds.get('align', idaapi.saRelByte)  # paragraphs

    # now we can add our segment_t to the database
    res = utils.string.to(name)
    ok = idaapi.add_segm_ex(seg, res, "",
                            idaapi.ADDSEG_NOSREG | idaapi.ADDSEG_SPARSE)
    if not ok:
        ok = idaapi.del_selector(sel)
        if not ok:
            logging.warning(
                u"{:s}.new({:#x}, {:+#x}, {!r}{:s}) : Unable to delete the created selector ({:#x}) for the new segment."
                .format(
                    __name__, offset, size, name, u", {:s}".format(
                        utils.string.kwargs(kwds)) if kwds else '', sel))
        raise E.DisassemblerError(
            u"{:s}.new({:#x}, {:+#x}, {!r}{:s}) : Unable to add a new segment."
            .format(
                __name__, offset, size, name,
                u", {:s}".format(utils.string.kwargs(kwds)) if kwds else ''))
    return seg
示例#13
0
def new(offset, size, name, **kwds):
    """Create a segment at `offset` with `size` and name it according to `name`.

    The keyword `bits` can be used to specify the bit size of the segment
    The keyword `comb` can be used to specify any flags (idaapi.sc*)
    The keyword `align` can be used to specify paragraph alignment (idaapi.sa*)
    The keyword `org` specifies the origin of the segment (must be paragraph aligned due to ida)
    """
    seg = idaapi.get_segm_by_name(name)
    if seg is not None:
        raise NameError(
            "{:s}.new({:#x}, {:+#x}, {!r}{:s}) : A segment with the specified name ({!r}) already exists."
            .format(
                __name__, offset, size, name, ", {:s}".format(', '.join(
                    "{:s}={!r}".format(k, v)
                    for k, v in kwds.iteritems())) if kwds else '', name))

    bits = kwds.get(
        'bits', 32 if idaapi.getseg(offset) is None else idaapi.getseg(offset).
        abits())  # FIXME: use disassembler default bit length instead of 32

    ## create a selector with the requested origin
    if bits == 16:
        org = kwds.get('org', 0)
        if org & 0xf > 0:
            raise E.InvalidTypeOrValueError(
                "{:s}.new({:#x}, {:+#x}, {!r}{:s}) : The specified origin ({:#x}) is not aligned to the size of a paragraph (0x10)."
                .format(
                    __name__, offset, size, name, ", {:s}".format(', '.join(
                        "{:s}={!r}".format(k, v)
                        for k, v in kwds.iteritems())) if kwds else '', org))

        para = offset / 16
        sel = idaapi.allocate_selector(para)
        idaapi.set_selector(sel, (para - kwds.get('org', 0) / 16) & 0xffffffff)

    ## if the user specified a selector, then use it
    elif 'sel' in kwds or 'selector' in kwds:
        sel = kwds.get('sel', kwds.get('selector',
                                       idaapi.find_free_selector()))

    ## choose the paragraph size defined by the user
    elif 'para' in kwds or 'paragraphs' in kwds:
        para = kwds.get('paragraph', kwds.get('para', 1))
        sel = idaapi.setup_selector(res)

    ## find a selector that is 1 paragraph size,
    elif idaapi.get_selector_qty():
        sel = idaapi.find_selector(1)

    # otherwise find a free one and set it.
    else:
        sel = idaapi.find_free_selector()
        idaapi.set_selector(sel, 1)

    # create segment. ripped from idc
    seg = idaapi.segment_t()
    seg.startEA = offset
    seg.endEA = offset + size
    seg.sel = sel
    seg.bitness = {16: 0, 32: 1, 64: 2}[bits]
    seg.comb = kwds.get('comb', idaapi.scPub)  # public
    seg.align = kwds.get('align', idaapi.saRelByte)  # paragraphs

    ok = idaapi.add_segm_ex(seg, name, "",
                            idaapi.ADDSEG_NOSREG | idaapi.ADDSEG_SPARSE)
    if not ok:
        ok = idaapi.del_selector(sel)
        if not ok:
            logging.warn(
                "{:s}.new({:#x}, {:+#x}, {!r}{:s}) : Unable to delete the created selector ({:#x}) for the new segment."
                .format(
                    __name__, offset, size, name, ", {:s}".format(', '.join(
                        "{:s}={!r}".format(k, v)
                        for k, v in kwds.iteritems())) if kwds else '', sel))

        raise E.DisassemblerError(
            "{:s}.new({:#x}, {:+#x}, {!r}{:s}) : Unable to add a new segment.".
            format(
                __name__, offset, size, name, ", {:s}".format(', '.join(
                    "{:s}={!r}".format(k, v)
                    for k, v in kwds.iteritems())) if kwds else ''))
    return seg