Example #1
0
    def check(ea):
        if 'mov' not in db.disasm(ea) or 'offset' not in db.disasm(ea):
            return
        if ins.ops_type(ea) != ['phrase', 'immediate']:
            return
        if ins.op_value(ea, 0).offset != 0:
            return

        print(hex(ea), db.disasm(ea), ins.ops_type())
Example #2
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))
Example #3
0
def search_func(addr, funcname, curr_addr_list=None):
    """
    Given an address and function name, recursively look from the given address
    for calls to the given function name. Modifies the 'calls' function tag with
    the function name and True or False depending if the function contains the wanted
    function or not.
    """
    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 funcname in db.disasm(ea):
            curr_calls[funcname] = True
            fn.tag(addr, 'calls', curr_calls)
            return True

        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

        # 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_func(call, funcname=funcname, curr_addr_list=curr_addr_list)

    curr_calls[funcname] = False
    fn.tag(addr, 'calls', curr_calls)
    return False
Example #4
0
def get_commands():
    for f in db.xref.code(0x44c8f8):
        prev_instr = db.prev(f)
        d = db.disasm(prev_instr)
        try:
            with open('C:\\Windows\\Temp\\commands', 'a') as f:
                f.write(d.split('.')[1] + '\n')
        except:
            print(d)
Example #5
0
def tag_command_funcs(funcs):
    for f in funcs:
        print(f)
        inner_funcs = set()
        for ins in func.iterate(f):
            curr_ins = db.disasm(ins)
            if 't9' in curr_ins and 'la' in curr_ins:
                inner_funcs.add(curr_ins.split(', ')[1])

        print(inner_funcs)
Example #6
0
def get_request_commands(h):
    funcs = []
    for x in func.iterate(h):
        if 'strcmp' in db.disasm(x):
            for count in xrange(10):
                if 'addi' in db.disasm(db.next(x, count)):
                    try:
                        addr = db.next(x, count)
                        command = db.disasm(addr).split('"')[1]
                        break
                    except:
                        pass
            else:
                print("No addi instr found after strcmp at {}".format(hex(x)))
                continue

            for count in xrange(20):
                curr_addr = db.next(addr, count)
                curr_inst = db.disasm(curr_addr)
                if 'la' in curr_inst and 't9' in curr_inst:
                    command_func = db.disasm(curr_addr).split(', ')[1]
                    if command_func == 'strcmp':
                        continue

                    funcs.append(command_func)
                    break
            else:
                print("No la $t9 found after {}".format(db.disasm(addr)))

    return funcs
Example #7
0
def breakMallocs(addr):
    breaks = ''
    mallocs = findMallocs(addr)
    for m in mallocs:
        db.tag(
            m, 'break',
            '.printf "{} - {} - malloc(0x%x) - ",poi(esp);g {};.printf "0x%x\\n",@eax;g'
            .format(hex(m), db.disasm(m),
                    hex(db.next(m))[:-1]))
        # db.tag(m, 'break', '.printf "{} - {} - malloc(0x%x) - ",poi(esp);'.format(hex(m), db.disasm(m)))
        breaks += dump_breaks(m, stdout=False)
        db.tag(m, 'break', None)

    print('Writing breaks to F:\\bps')
    with open('F:\\bps', 'wb') as f:
        f.write(breaks)
Example #8
0
def findMallocs(addr):
    """
    Recurses down from a function and looks for malloc calls
    """
    mallocs = []
    for y in recurseDown(addr, 5):
        try:
            for x in func.iterate(y):
                dis = db.disasm(x)
                if 'call' in dis:
                    if 'malloc' in dis or 'JSFC_729' in dis:
                        mallocs.append(x)
        except LookupError:
            pass

    return mallocs
Example #9
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))
Example #10
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))
Example #11
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
Example #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=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))