コード例 #1
0
def find6b(h):
    for f in func.down(h):
        for ea in func.iterate(f):
            for opnum in ins.ops_count(ea):
                if ins.op_type(ea, opnum) == 'phrase' and ins.op(
                        ea, opnum).offset == 0x6b:
                    print(db.disasm(ea))
コード例 #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())]
コード例 #3
0
def search_dyn_calls(addr, curr_addr_list=None, parents=None):
    dyn_call = namedtuple('dyn_call', ['call', 'parents'])
    hex = '{:x}'.format

    # print(hex(addr), curr_addr_list)
    if curr_addr_list == None:
        curr_addr_list = [addr]

    if parents == None:
        parents = []

    calls = []

    #print("Addr: {}".format(addr))
    for ea in fn.iterate(addr):
        if not ins.isCall(ea):
            continue

        call = ins.op_value(ea, 0)

        # Don't cycle ourselves
        if call == addr:
            # print("Ignoring recursive loop on function: {}".format(hex(addr)))
            continue

        # Don't call functions we are currently looking into
        if call in curr_addr_list:
            continue
        """
        .text:3F6E66AD 0B4                 call    ds:memmove
        Python>x = ins.op_value(h(), 0)
        Python>print(x.base)
        None
        .text:3F6E6208 008                 call    dword ptr [eax]
        Python>x.base
        <instruction.register.eax(0,dt_dword) 'eax' 0:+32>
        """
        # we want non int/long for calls
        if isinstance(call,
                      (int, long)) and not ins.op_type(ea, 0) in ('phrase'):
            # Only now call the function once
            curr_addr_list.append(call)
            new_parents = copy.deepcopy(parents)
            new_parents.append(ea)
            calls.extend(
                search_dyn_call(call,
                                curr_addr_list=curr_addr_list,
                                parents=new_parents))
        elif isinstance(
                call, ins.intelop.OffsetBaseIndexScale) and call.base == None:
            # Ignore 'call ds:memmove' or 'call ds:atoi'
            # print("OffsetBase", call.offset, hex(ea)[2:-1], db.disasm(ea), parents)
            pass
        else:
            calls.append(dyn_call(ea, parents))

    return calls
コード例 #4
0
 def uses_register(ea, regs):
     res = [(_instruction.op_type(ea, x), _instruction.op_value(ea, x),
             _instruction.op_state(ea, x))
            for x in xrange(_instruction.ops_count(ea))
            if _instruction.op_type(ea, x) in ('opt_reg', 'opt_phrase')]
     match = lambda r, regs: itertools.imap(
         _instruction.reg_t.byName(r).related,
         itertools.imap(_instruction.reg_t.byName, regs))
     for t, p, st in res:
         if t == 'opt_reg' and any(match(
                 p, regs)) and ('w' in st if write else True):
             return True
         if t == 'opt_phrase' and not write:
             _, (base, index, _) = p
             if (base and any(match(base, regs))) or (index and any(
                     match(index, regs))):
                 return True
         continue
     return False
コード例 #5
0
ファイル: tools.py プロジェクト: perfectswpuboy1/ida-minsc
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 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))
コード例 #7
0
def search_malloc(addr, funcname='malloc', curr_addr_list=None):
    # print(hex(addr), curr_addr_list)
    if curr_addr_list == None:
        curr_addr_list = [addr]

    print("Addr: {}".format(addr))
    curr_calls = fn.tag(addr).get('calls', {})
    for ea in fn.iterate(addr):
        if not ins.isCall(ea):
            continue

        if ins.op_type(0) == 'reg':
            """
            Handle this case - malloc(100)
            mov ebp, ds:malloc
            push 100
            call ebp
            """

        if funcname in db.disasm(ea):
            # Push before malloc "should" be within 20 instructions
            """
            Handle this case - malloc(100)
            push 100
            mov eax, 10
            mov ebx, 20
            call malloc
            """
            search_addr = db.prev(ea)
            for _ in range(20):
                if ins.mnem(search_addr) == 'push':
                    break
                search_addr = db.prev(search_addr)

            print("FOUND PUSH FOR MALLOC: {}".format(hex(search_addr)))
            malloc_value = ins.op_value(search_addr, 0)
            if isinstance(malloc_value, (int, long)):
                curr_calls[funcname] = malloc_value
            else:
                curr_calls[funcname] = 'variable'

            fn.tag(addr, 'calls', curr_calls)
            return True

        call = ins.op_value(ea, 0)

        # Don't cycle ourselves
        if call == addr:
            print("Ignoring recursive loop on function: {}".format(hex(addr)))
            continue

        # Try to know if the call operand is a valid address
        # Bail if not..
        try:
            print(hex(call))
        except:
            continue

        # Check if this function has been analyzed already
        # and return the result
        # Cannot return False, because that will exit the loop and not
        # continue to iterate over the rest of the instrutions in the function
        call_cache = fn.tag(call).get('calls', {})
        print("Call cache: {}".format(call_cache))
        if funcname in call_cache:
            if call_cache[funcname]:
                curr_calls[funcname] = call_cache[funcname]
                fn.tag(addr, 'calls', curr_calls)
                return True

        # Don't call functions we are currently looking into
        if call in curr_addr_list:
            continue

        # Only now ca
        curr_addr_list.append(call)
        search_malloc(call, funcname=funcname, curr_addr_list=curr_addr_list)

    curr_calls[funcname] = False
    fn.tag(addr, 'calls', curr_calls)
    return False
コード例 #8
0
ファイル: tools.py プロジェクト: arizvisa/idascripts
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))