示例#1
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
示例#2
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
示例#3
0
def blocks(start, end):
    '''Returns each block between the specified range of instructions'''
    block = start
    for ea in iterate(start, end):
        nextea = next(ea)

        if _instruction.isCall(ea):
            continue

        if _instruction.isReturn(ea):
            yield block, nextea
            block = ea

        elif cxdown(ea):
            yield block, nextea
            block = nextea

        elif cxup(ea) and block != ea:
            yield block, ea
            block = ea
        continue
    return
示例#4
0
def _search_func(addr, func, curr_addr_list=None):
    if curr_addr_list == None:
        curr_addr_list = [addr]

    for ea in fn.iterate(addr):

        func(ea)

        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..
        if not isinstance(call, (int, long)):
            continue
        """
        try:
            x = hex(call)
        except:
            continue
        """

        # 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, func, curr_addr_list=curr_addr_list)
示例#5
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
示例#6
0
 def nextbranch(cls, ea=None, count=1):
     ea = ui.current.address() if ea is None else ea
     res = cls.walk(
         ea, cls.next,
         lambda n: _instruction.isCall(n) and not _instruction.isBranch(n))
     return cls.nextbranch(cls.next(res), count - 1) if count > 1 else res
示例#7
0
 def prevcall(cls, ea=None, count=1):
     ea = ui.current.address() if ea is None else ea
     res = cls.walk(cls.prev(ea), cls.prev,
                    lambda n: not _instruction.isCall(n))
     return cls.prevcall(res, count - 1) if count > 1 else res