Esempio n. 1
0
def guessrange(ea):
    '''Try really hard to get boundaries of the block at specified address'''
    start, end = function.getRange(ea)
    if function.contains(start, ea) and not (ea >= start and ea < end):
        return (idc.GetFchunkAttr(ea, idc.FUNCATTR_START),
                idc.GetFchunkAttr(ea, idc.FUNCATTR_END))
    return start, end
Esempio n. 2
0
def sourcechain(fn, *args, **kwds):
    #    sentinel = kwds.get('types', set(('imm','phrase','addr','void')))
    sentinel = kwds.get('types', set(('imm', 'addr', 'void')))

    result = {}
    for ea, opi in source(*args):
        if not function.contains(fn, ea): continue
        opt = tuple(ins.op_type(ea, i) for i in opi)
        for i, t in zip(opi, opt):
            if t in sentinel:
                result.setdefault(ea, set()).add(i)
            elif t in ('reg', ):
                result.setdefault(ea, set()).add(i)
                r = ins.op_value(ea, i)
                for a, b in sourcechain(fn, ea, r):
                    map(result.setdefault(a, set()).add, b)
            elif t in ('phrase', ):
                result.setdefault(ea, set()).add(i)
                _, (r1, r2, _) = ins.op_value(ea, i)
                for a, b in sourcechain(
                        fn, ea, *tuple(r for r in (r1, r2) if r is not None)):
                    map(result.setdefault(a, set()).add, b)
            elif t in (
                    'imm',
                    'addr',
            ):
                result.setdefault(ea, set()).add(i)
            else:
                raise ValueError, (t, ea, i)
            continue
        continue
    return [(ea, result[ea]) for ea in sorted(result.keys())]
Esempio n. 3
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))
Esempio n. 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)'%(internal.declaration.demangle(function.name(function.byAddress(fn))), ','.join(result))
Esempio n. 5
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))
Esempio n. 6
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))
Esempio n. 7
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))
Esempio n. 8
0
def guessrange(ea):
    '''Try really hard to get boundaries of the block at specified address'''
    start,end = function.getRange(ea)
    if function.contains(start, ea) and not (ea >= start and ea < end):
        return (idc.GetFchunkAttr(ea, idc.FUNCATTR_START), idc.GetFchunkAttr(ea, idc.FUNCATTR_END))
    return start,end