Beispiel #1
0
def makecall(ea):
    if not function.contains(ea, ea):
        return None

    # scan down until we find a call that references something
    chunk, = ((l,r) for l,r in function.chunks(ea) if l <= ea <= r)
    result = []
    while (len(result) < 1) and ea < chunk[1]:
        # FIXME: it's probably not good to just scan for a call
        if not instruction(ea).startswith('call '):
            ea = next(ea)
            continue
        result = cxdown(ea)

    if len(result) != 1:
        raise ValueError('Invalid code reference: %x %s'% (ea,repr(result)))
    fn, = result

    result = []
    for offset,name,size in function.getArguments(fn):
        left,_ = function.stackwindow(ea, offset+config.bits()/8)
        # FIXME: if left is not an assignment or a push, find last assignment
        result.append((name,left))

    result = ['%s=%s'%(name,_instruction.op_repr(ea,0)) for name,ea in result]
    return '%s(%s)'%(internal.declaration.demangle(function.name(function.byAddress(fn))), ','.join(result))
Beispiel #2
0
def del_func(pfn):
    global State
    if State != state.ready: return

    # convert all contents into globals
    for l, r in function.chunks(pfn):
        for ea in database.address.iterate(l, r):
            for k in database.tag(ea):
                internal.comment.contents.dec(
                    ea, k, target=interface.range.start(pfn))
                internal.comment.globals.inc(ea, k)
                logging.debug(
                    u"{:s}.del_func({:#x}) : Exchanging (increasing) refcount for global tag {!s} and (decreasing) refcount for contents tag {!s}."
                    .format(__name__, interface.range.start(pfn),
                            utils.string.repr(k), utils.string.repr(k)))
            continue
        continue

    # remove all function tags
    for k in function.tag(interface.range.start(pfn)):
        internal.comment.globals.dec(interface.range.start(pfn), k)
        logging.debug(
            u"{:s}.del_func({:#x}) : Removing (global) tag {!s} from function."
            .format(__name__, interface.range.start(pfn),
                    utils.string.repr(k)))
    return
Beispiel #3
0
def __process_functions():
    p = ui.progress()
    globals = internal.comment.globals.address()

    funcs = list(database.functions())
    p.update(current=0, max=len(funcs), title="Pre-building tagcache...")
    p.open()
    for i, fn in enumerate(funcs):
        chunks = list(function.chunks(fn))

        text = functools.partial("{:x} : Processing function {:d} of {:d} : ({:d} chunk{:s})".format, fn, i, len(funcs))
        p.update(current=i)

        contents = set(internal.comment.contents.address(fn))
        for ci, (l, r) in enumerate(chunks):
            p.update(text=text(len(chunks), 's' if len(chunks) != 1 else ''), tooltip="Chunk #{:d} : {:x} - {:x}".format(ci, l, r))
            for ea in database.iterate(l, r):
                # FIXME: no need to iterate really since we should have
                #        all of the addresses
                for k, v in database.tag(ea).iteritems():
                    if ea in globals: internal.comment.globals.dec(ea, k)
                    if ea not in contents: internal.comment.contents.inc(ea, k, target=fn)
                continue
            continue
        continue
    p.close()
Beispiel #4
0
def makecall(ea):
    if not function.contains(ea, ea):
        return None

    # scan down until we find a call that references something
    chunk, = ((l, r) for l, r in function.chunks(ea) if l <= ea <= r)
    result = []
    while (len(result) < 1) and ea < chunk[1]:
        # FIXME: it's probably not good to just scan for a call
        if not instruction(ea).startswith('call '):
            ea = next(ea)
            continue
        result = cxdown(ea)

    if len(result) != 1:
        raise ValueError('Invalid code reference: %x %s' % (ea, repr(result)))
    fn, = result

    result = []
    for offset, name, size in function.getArguments(fn):
        left, _ = function.stackwindow(ea, offset + config.bits() / 8)
        # FIXME: if left is not an assignment or a push, find last assignment
        result.append((name, left))

    result = [
        '%s=%s' % (name, _instruction.op_repr(ea, 0)) for name, ea in result
    ]
    return '%s(%s)' % (_declaration.demangle(
        function.name(function.byAddress(fn))), ','.join(result))
Beispiel #5
0
def __process_functions(percentage=0.10):
    p = ui.Progress()
    globals = set(internal.comment.globals.address())

    total = 0

    funcs = list(database.functions())
    p.update(current=0, max=len(funcs), title=u"Pre-building tagcache...")
    p.open()
    six.print_(u"Pre-building tagcache for {:d} functions.".format(len(funcs)))
    for i, fn in enumerate(funcs):
        chunks = list(function.chunks(fn))

        text = functools.partial(u"Processing function {:#x} ({chunks:d} chunk{plural:s}) -> {:d} of {:d}".format, fn, i + 1, len(funcs))
        p.update(current=i)
        ui.navigation.procedure(fn)
        if i % (int(len(funcs) * percentage) or 1) == 0:
            six.print_(u"Processing function {:#x} -> {:d} of {:d} ({:.02f}%)".format(fn, i+1, len(funcs), i / float(len(funcs)) * 100.0))

        contents = set(internal.comment.contents.address(fn))
        for ci, (l, r) in enumerate(chunks):
            p.update(text=text(chunks=len(chunks), plural='' if len(chunks) == 1 else 's'), tooltip="Chunk #{:d} : {:#x} - {:#x}".format(ci, l, r))
            ui.navigation.analyze(l)
            for ea in database.address.iterate(l, r):
                # FIXME: no need to iterate really since we should have
                #        all of the addresses
                for k, v in six.iteritems(database.tag(ea)):
                    if ea in globals: internal.comment.globals.dec(ea, k)
                    if ea not in contents: internal.comment.contents.inc(ea, k, target=fn)
                    total += 1
                continue
            continue
        continue
    six.print_(u"Successfully built tag-cache composed of {:d} tag{:s}.".format(total, '' if total == 1 else 's'))
    p.close()
Beispiel #6
0
def locationToAddress(loc):
    '''Convert the function location `loc` back into an address.'''

    ## if location is a tuple, then convert it to an address
    if isinstance(loc, tuple):
        f, cid, ofs = loc
        base, _ = next(b for i, b in enumerate(func.chunks(f)) if i == cid)
        return base + ofs

    ## otherwise, it's already an address
    return loc
Beispiel #7
0
def locationToAddress(loc):
    '''Convert the function location `loc` back into an address.'''

    ## if location is a tuple, then convert it to an address
    if isinstance(loc, tuple):
        f, cid, ofs = loc
        base, _ = next(b for i, b in enumerate(func.chunks(f)) if i == cid)
        return base + ofs

    ## otherwise, it's already an address
    return loc
Beispiel #8
0
def addressToLocation(ea, chunks=None):
    """Convert the address `ea` to a `(function, id, offset)`.

    The fields `id` and `offset` represent the chunk index and the
    offset into the chunk for the function at `ea`. If the list
    `chunks` is specified as a parameter, then use it as a tuple
    of ranges in order to calculate the correct address.
    """
    F, chunks = func.by(ea), chunks or [ch for ch in func.chunks(ea)]
    cid, base = next((i, l) for i, (l, r) in enumerate(chunks) if l <= ea < r)
    return func.top(F), cid, ea - base
Beispiel #9
0
def addressToLocation(ea, chunks=None):
    """Convert the address `ea` to a `(function, id, offset)`.

    The fields `id` and `offset` represent the chunk index and the
    offset into the chunk for the function at `ea`. If the list
    `chunks` is specified as a parameter, then use it as a tuple
    of ranges in order to calculate the correct address.
    """
    F, chunks = func.by(ea), chunks or [ch for ch in func.chunks(ea)]
    cid, base = next((i, l) for i, (l, r) in enumerate(chunks) if l <= ea < r)
    return func.top(F), cid, ea - base
Beispiel #10
0
def add_func(pfn):
    global State
    if State != state.ready: return
    # convert all globals into contents
    for (l,r) in function.chunks(pfn):
        for ea in database.iterate(l, r):
            for k in database.tag(ea):
                internal.comment.globals.dec(ea, k)
                internal.comment.contents.inc(ea, k, target=pfn.startEA)
            continue
        continue
    return
Beispiel #11
0
def add_func(pfn):
    global State
    if State != state.ready: return
    # convert all globals into contents
    for l, r in function.chunks(pfn):
        for ea in database.address.iterate(l, r):
            for k in database.tag(ea):
                internal.comment.globals.dec(ea, k)
                internal.comment.contents.inc(ea, k, target=pfn.startEA)
                logging.debug("{:s}.add_func({:#x}) : Decreasing refcount for global tag {!r} and increasing refcount for contents tag {!r}".format(__name__, pfn.startEA, k, k))
            continue
        continue
    return
Beispiel #12
0
def makecall(ea=None, target=None):
    """Output the function call at `ea` and its arguments with the address they originated from.

    If `target` is specified, then assume that the instruction is
    calling `target` instead of the target address that the call
    is referencing.
    """
    ea = current.address() if ea is None else ea
    if not func.contains(ea, ea):
        return None

    if database.config.bits() != 32:
        raise RuntimeError("{:s}.makecall({!r}, {!r}) : Unable to determine arguments for {:s} due to {:d}-bit calling convention.".format(__name__, ea, target, database.disasm(ea), database.config.bits()))

    if target is None:
        # scan down until we find a call that references something
        chunk, = ((l, r) for l, r in func.chunks(ea) if l <= ea <= r)
        result = []
        while (len(result) < 1) and ea < chunk[1]:
            # FIXME: it's probably not good to just scan for a call
            if not database.instruction(ea).startswith('call '):
                ea = database.next(ea)
                continue
            result = database.cxdown(ea)
            if len(result) == 0: raise TypeError("{:s}.makecall({!r}, {!r}) : Unable to determine number of arguments.".format(__name__, ea, target))

        if len(result) != 1:
            raise ValueError("{:s}.makecall({!r}, {!r}) : An invalid number of targets was returned for the call at {:#x}. The call targets that were returned are {!r}.".format(__name__, ea, result))
        fn, = result
    else:
        fn = target

    try:
        result = []
        for offset, name, size in func.arguments(fn):
            left = database.address.prevstack(ea, offset + database.config.bits() // 8)
            # FIXME: if left is not an assignment or a push, find last assignment
            result.append((name, left))
    except internal.exceptions.OutOfBoundsError:
        raise internal.exceptions.OutOfBoundserror("{:s}.makecall({!r}, {!r}) : Unable to get arguments for target function.".format(__name__, ea, target))

    # FIXME: replace these crazy list comprehensions with something more comprehensible.
#    result = ["{:s}={:s}".format(name, instruction.op_repr(ea, 0)) for name, ea in result]
    result = ["({:#x}){:s}={:s}".format(ea, name, ':'.join(instruction.op_repr(database.address.prevreg(ea, instruction.op_value(ea, 0), write=True), n) for n in instruction.opsi_read(database.address.prevreg(ea, instruction.op_value(ea, 0), write=True))) if instruction.op_type(ea, 0) == 'reg' else instruction.op_repr(ea, 0)) for name, ea in result]

    try:
        return "{:s}({:s})".format(internal.declaration.demangle(func.name(func.by_address(fn))), ','.join(result))
    except:
        pass
    return "{:s}({:s})".format(internal.declaration.demangle(database.name(fn)), ','.join(result))
Beispiel #13
0
def makecall(ea=None, target=None):
    """Output the function call at `ea` and its arguments with the address they originated from.

    If `target` is specified, then assume that the instruction is
    calling `target` instead of the target address that the call
    is referencing.
    """
    ea = current.address() if ea is None else ea
    if not func.contains(ea, ea):
        return None

    if database.config.bits() != 32:
        raise RuntimeError("{:s}.makecall({!r}, {!r}) : Unable to determine arguments for {:s} due to {:d}-bit calling convention.".format(__name__, ea, target, database.disasm(ea), database.config.bits()))

    if target is None:
        # scan down until we find a call that references something
        chunk, = ((l, r) for l, r in func.chunks(ea) if l <= ea <= r)
        result = []
        while (len(result) < 1) and ea < chunk[1]:
            # FIXME: it's probably not good to just scan for a call
            if not database.instruction(ea).startswith('call '):
                ea = database.next(ea)
                continue
            result = database.cxdown(ea)
            if len(result) == 0: raise TypeError("{:s}.makecall({!r}, {!r}) : Unable to determine number of arguments.".format(__name__, ea, target))

        if len(result) != 1:
            raise ValueError("{:s}.makecall({!r}, {!r}) : An invalid number of targets was returned for the call at {:#x}. The call targets that were returned are {!r}.".format(__name__, ea, result))
        fn, = result
    else:
        fn = target

    try:
        result = []
        for offset, name, size in func.arguments(fn):
            left = database.address.prevstack(ea, offset+database.config.bits()/8)
            # FIXME: if left is not an assignment or a push, find last assignment
            result.append((name, left))
    except internal.exceptions.OutOfBoundsError:
        raise internal.exceptions.OutOfBoundserror("{:s}.makecall({!r}, {!r}) : Unable to get arguments for target function.".format(__name__, ea, target))

    # FIXME: replace these crazy list comprehensions with something more comprehensible.
#    result = ["{:s}={:s}".format(name, instruction.op_repr(ea, 0)) for name, ea in result]
    result = ["({:#x}){:s}={:s}".format(ea, name, ':'.join(instruction.op_repr(database.address.prevreg(ea, instruction.op_value(ea, 0), write=1), n) for n in instruction.ops_read(database.address.prevreg(ea, instruction.op_value(ea, 0), write=1))) if instruction.op_type(ea, 0) == 'reg' else instruction.op_repr(ea, 0)) for name, ea in result]

    try:
        return "{:s}({:s})".format(internal.declaration.demangle(func.name(func.by_address(fn))), ','.join(result))
    except:
        pass
    return "{:s}({:s})".format(internal.declaration.demangle(database.name(fn)), ','.join(result))
Beispiel #14
0
def del_func(pfn):
    global State
    if State != state.ready: return
    # convert all contents into globals
    for (l,r) in function.chunks(pfn):
        for ea in database.iterate(l, r):
            for k in database.tag(ea):
                internal.comment.contents.dec(ea, k, target=pfn.startEA)
                internal.comment.globals.inc(ea, k)
            continue
        continue

    # remove all function tags
    for k in function.tag(pfn.startEA):
        internal.comment.globals.dec(pfn.startEA, k)
    return
Beispiel #15
0
    def contents(location=False):
        """Iterate through the contents tags for all the functions within the database.

        Each iteration yields a tuple of the format `(location, tags)` where
        `location` can be either an address or a chunk identifier and offset
        depending on whether `location` was specified as true or not.
        """
        global read

        # Iterate through each function in the database
        for ea in db.functions():

            # it's faster to precalculate the chunks here
            F, chunks = func.by(ea), [ch for ch in func.chunks(ea)]

            # Iterate through the function's contents yielding each tag
            for ea, res in read.content(ea):
                loc = addressToLocation(ea, chunks=chunks) if location else ea
                yield loc, res
            continue
        return
Beispiel #16
0
    def contents(location=False):
        """Iterate through the contents tags for all the functions within the database.

        Each iteration yields a tuple of the format `(location, tags)` where
        `location` can be either an address or a chunk identifier and offset
        depending on whether `location` was specified as true or not.
        """
        global read

        # Iterate through each function in the database
        for ea in db.functions():

            # it's faster to precalculate the chunks here
            F, chunks = func.by(ea), [ch for ch in func.chunks(ea)]

            # Iterate through the function's contents yielding each tag
            for ea, res in read.content(ea):
                loc = addressToLocation(ea, chunks=chunks) if location else ea
                yield loc, res
            continue
        return
Beispiel #17
0
        SetDelayed = pyml.function("SetDelayed")
        Set = pyml.function("Set")
        List = pyml.function("List")
        Hold = pyml.function("Hold")
        RuleDelayed = pyml.function("RuleDelayed")
        Rule = pyml.function("Rule")

        call = pyml.function("call")
        symcall = pyml.function("symcall")
        
        rules = []
        max = len(database.functions())
        for i,ea in enumerate(database.functions()):
            result = []
            for l,r in function.chunks(ea):
                for x in database.iterate(l,r):
                    address,size,insn = x,idc.ItemSize(x),idc.GetDisasm(x)
                    insn = re.sub(" +", " ", insn)
                    insn = insn.replace("short", "")
                    insn = insn.replace("dword", "")
                    insn = insn.replace("offset", "")
                    insn = insn.replace("large", "")
                    insn = insn.replace("ptr", "")
                    insn = insn.replace("[", "")
                    insn = insn.replace("]", "")
                    if " " in insn:
                        insn = insn.replace(" ", "|", 1)
                        insn = insn.replace(",", "|")
                        insn = insn.replace(" ", "")
                    fn = insn.split("|")
Beispiel #18
0
def makecall(ea=None, target=None):
    ea = current.address() if ea is None else ea
    if not function.contains(ea, ea):
        return None

    if database.config.bits() != 32:
        raise RuntimeError(
            "{:s}.makecall({!r},{!r}) : Unable to determine arguments for {:s} due to {:d}-bit calling convention."
            .format(__name__, ea, target, database.disasm(ea),
                    database.config.bits()))

    if target is None:
        # scan down until we find a call that references something
        chunk, = ((l, r) for l, r in function.chunks(ea) if l <= ea <= r)
        result = []
        while (len(result) < 1) and ea < chunk[1]:
            # FIXME: it's probably not good to just scan for a call
            if not database.instruction(ea).startswith('call '):
                ea = database.next(ea)
                continue
            result = database.cxdown(ea)
            if len(result) == 0:
                raise TypeError(
                    "{:s}.makecall({!r},{!r}) : Unable to determine number of arguments"
                    .format(__name__, ea, target))

        if len(result) != 1:
            raise ValueError(
                "{:s}.makecall({!r},{!r}) : Too many targets for call at {:x} : {!r}"
                .format(__name__, ea, result))
        fn, = result
    else:
        fn = target

    try:
        result = []
        for offset, name, size in function.arguments(fn):
            left, _ = function.stack_window(
                ea, offset + database.config.bits() / 8)
            # FIXME: if left is not an assignment or a push, find last assignment
            result.append((name, left))
    except LookupError:
        raise LookupError(
            "{:s}.makecall({!r},{!r}) : Unable to get arguments for target function"
            .format(__name__, ea, target))

    # FIXME: replace these crazy list comprehensions with something more comprehensible.


#    result = ["{:s}={:s}".format(name,ins.op_repr(ea, 0)) for name,ea in result]
    result = [
        "({:x}){:s}={:s}".format(
            ea, name, ':'.join(
                ins.op_repr(
                    database.address.prevreg(ea, ins.op_value(ea, 0), write=1),
                    n)
                for n in ins.ops_read(
                    database.address.prevreg(ea, ins.op_value(ea, 0), write=1))
            ) if ins.op_type(ea, 0) == 'reg' else ins.op_repr(ea, 0))
        for name, ea in result
    ]

    try:
        return "{:s}({:s})".format(
            internal.declaration.demangle(
                function.name(function.by_address(fn))), ','.join(result))
    except:
        pass
    return "{:s}({:s})".format(
        internal.declaration.demangle(database.name(fn)), ','.join(result))