Пример #1
0
def below(ea, includeSegment=False):
    '''Display all the functions that the function at /ea/ can call'''
    tryhard = lambda ea: "{:s}+{:x}".format(database.name(function.top(
        ea)), ea - function.top(ea)) if function.within(
            ea) else "+{:x}".format(ea) if database.name(
                ea) is None else database.name(ea)
    return '\n'.join(
        ':'.join((segment.name(ea),
                  tryhard(ea)) if includeSegment else (tryhard(ea), ))
        for ea in function.down(ea))
Пример #2
0
    def enter(self, pc, options):
        options['database'].address(pc)['name'] = database.name(pc)
       
        xrefs_to = database.cxup(pc)    
        func_top = pc    
       
        for x in xrefs_to:
            xref_top = function.top(x)
            context = options['database'].c(xref_top) 
            context.address(x).edge((func_top, func_top)) 

        return
Пример #3
0
def prototype(key=None):
    '''Returns the full prototype of the function identified by fn.'''
    rt,ea = __addressOfRtOrSt(ui.current.address() if key is None else key)
    funcname = database.name(ea)
    try:
        res = internal.declaration.function(ea)
        idx = res.find('(')
        result = res[:idx] + ' ' + funcname + res[idx:]

    except ValueError:
        if not funcname.startswith('?'): raise
        result = internal.declaration.demangle(funcname)
    return result
Пример #4
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))
Пример #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=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))
Пример #6
0
 def _collectcall(addr, result):
     process = set()
     for f in func.down(addr):
         if any(f in coll for coll in (result, sentinel)):
             continue
         if not func.within(f):
             logging.warn(
                 "{:s}.collectcall({:#x}, {!r}) : Adding non-function address {:#x} ({:s})."
                 .format(__name__, ea, sentinel, f, database.name(f)))
             result.add(f)
             continue
         process.add(f)
     for addr in process:
         result |= _collectcall(addr, result | process)
     return result
Пример #7
0
def name(key=None, name=None):
    '''Returns the name of the function or import identified by key.'''
    rt,ea = __addressOfRtOrSt(ui.current.address() if key is None else key)
    if rt:   
        if name is None:
            res = idaapi.get_name(-1, ea)
            return internal.declaration.extract.fullname(internal.declaration.demangle(res)) if res.startswith('?') else res
        # FIXME: shuffle the new name into the prototype and then re-mangle it
        return database.name(ea, name)

    if name is None:
        res = idaapi.get_func_name(ea)
        if not res: res = idaapi.get_name(-1, ea)
        if not res: res = idaapi.get_true_name(ea, ea)
        return internal.declaration.extract.fullname(internal.declaration.demangle(res)) if res.startswith('?') else res
        #return internal.declaration.extract.name(internal.declaration.demangle(res)) if res.startswith('?') else res
    return idaapi.set_name(ea, name, idaapi.SN_PUBLIC)
Пример #8
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))
Пример #9
0
def below(ea):
    '''Display all the functions that the function at /ea/ can call'''
    tryhard = lambda x: '%s+%x'%(database.name(function.top(x)),x-function.top(x)) if function.within(x) else hex(x) if database.name(x) is None else database.name(x)
    return '\n'.join(map(tryhard,function.down(ea)))
Пример #10
0
def above(ea):
    '''Display all the callers of the function at /ea/'''
    tryhard = lambda x: '%s+%x'%(database.name(function.top(x)),x-function.top(x)) if function.within(x) else hex(x) if database.name(x) is None else database.name(x)
    return '\n'.join(map(tryhard,function.up(ea)))
Пример #11
0
 def _collectcall(addr, result):
     process = set()
     for f in func.down(addr):
         if any(f in coll for coll in (result, sentinel)):
             continue
         if not func.within(f):
             logging.warn("{:s}.collectcall({:#x}, {!r}) : Adding non-function address {:#x} ({:s}).".format(__name__, ea, sentinel, f, database.name(f)))
             result.add(f)
             continue
         process.add(f)
     for addr in process:
         result |= _collectcall(addr, result | process)
     return result
Пример #12
0
def below(ea):
    '''Display all the functions that the function at /ea/ can call'''
    tryhard = lambda x: '%s+%x' % (database.name(function.top(
        x)), x - function.top(x)) if function.within(x) else hex(
            x) if database.name(x) is None else database.name(x)
    return '\n'.join(map(tryhard, function.down(ea)))
Пример #13
0
def above(ea):
    '''Display all the callers of the function at /ea/'''
    tryhard = lambda x: '%s+%x' % (database.name(function.top(
        x)), x - function.top(x)) if function.within(x) else hex(
            x) if database.name(x) is None else database.name(x)
    return '\n'.join(map(tryhard, function.up(ea)))