Example #1
0
def popMultiple(args,
                constraint=None,
                assertion=None,
                clmax=None,
                optimizeLen=False):
    """
    args is a list of pairs (reg, value)
    reg is a reg UID
    value is an int
    Creates a chain that pops values into regs
    """
    if (clmax <= 0):
        return None

    if (constraint is None):
        constr = Constraint()
    else:
        constr = constraint
    if (assertion is None):
        a = Assertion()
    else:
        a = assertion

    perms = itertools.permutations(args)
    for perm in perms:
        clmax_tmp = clmax
        res = ROPChain()
        constr_tmp = constr
        for arg in perm:
            if (optimizeLen):
                pop = search_optimize_len(QueryType.CSTtoREG,
                                          arg[0],
                                          arg[1],
                                          constr_tmp,
                                          a,
                                          n=1,
                                          clmax=clmax_tmp)
            else:
                pop = search(QueryType.CSTtoREG,
                             arg[0],
                             arg[1],
                             constr_tmp,
                             a,
                             n=1,
                             clmax=clmax_tmp)
            if (not pop):
                break
            else:
                clmax_tmp -= len(pop[0])
                # If Reached max length, exit
                if (clmax_tmp < 0):
                    pop = None
                    break
                else:
                    res.addChain(pop[0])
                    constr_tmp = constr_tmp.add(RegsNotModified([arg[0]]))
        if (pop):
            return res
    return None
Example #2
0
def STRtoMEM_write(string,
                   addr,
                   constraint,
                   assertion,
                   limit=None,
                   lmax=STR_TO_MEM_LMAX,
                   addr_str=None,
                   hex_info=False):
    """
    WRITE STRATEGY
    Copy the string using mem(XXX) <- YYY gadgets 
    """
    if (not addr_str):
        addr_str = hex(addr)

    # We decompose the string in substrings to be copied
    substrings_addr = find_best_valid_writes(addr, string, constraint, limit)
    if (substrings_addr is None):
        return (None, None)

    # Build chain
    res = ROPChain()
    offset = 0
    for (substring_addr, substring_val) in substrings_addr:
        substring_info = "(" + string_bold("Substring in int") + hex(
            substring_val) + ")"
        write_chain = store_constant_address(QueryType.CSTtoMEM,
                                             substring_addr,
                                             substring_val,
                                             constraint,
                                             assertion,
                                             clmax=lmax - len(res),
                                             optimizeLen=True)
        if (write_chain):
            res.addChain(write_chain)
        else:
            verbose("Coudln't find suitable memory write ropchain")
            return (None, None)
    return (substrings_addr[0][0], res)
Example #3
0
def build_call(funcName, funcArgs, constraint, assertion):
    # Find the address of the fonction
    (funcName2, funcAddr) = getFunctionAddress(funcName)
    if (funcName2 is None):
        return "Couldn't find function '{}' in the binary".format(funcName)

    # Check if bad bytes in function address
    if (not constraint.badBytes.verifyAddress(funcAddr)):
        return "'{}' address ({}) contains bad bytes".format(
            funcName2,
            string_special('0x' + format(funcAddr, '0' +
                                         str(Arch.octets() * 2) + 'x')))

    # Find a gadget for the fake return address
    offset = len(
        funcArgs) * 8 - 8  # Because we do +8 at the beginning of the loop
    skip_args_chains = []
    i = 4
    while (i > 0 and (not skip_args_chains)):
        offset += 8
        skip_args_chains = search(QueryType.MEMtoREG, Arch.ipNum(), \
                    (Arch.spNum(),offset), constraint, assertion, n=1)
        i -= 1

    if (not skip_args_chains):
        return "Couldn't build ROP-Chain"
    skip_args_chain = skip_args_chains[0]

    # Build the ropchain with the arguments
    args_chain = ROPChain()
    arg_n = len(funcArgs)
    for arg in reversed(funcArgs):
        if (isinstance(arg, int)):
            args_chain.addPadding(arg,
                                  comment="Arg{}: {}".format(
                                      arg_n, string_ropg(hex(arg))))
            arg_n -= 1
        else:
            return "Type of argument '{}' not supported yet :'(".format(arg)

    # Build call chain (function address + fake return address)
    call_chain = ROPChain()
    call_chain.addPadding(funcAddr, comment=string_ropg(funcName2))
    skip_args_addr = int(
        validAddrStr(skip_args_chain.chain[0], constraint.getBadBytes(),
                     Arch.bits()), 16)
    call_chain.addPadding(skip_args_addr,
                          comment="Address of: " +
                          string_bold(str(skip_args_chain.chain[0])))

    return call_chain.addChain(args_chain)
Example #4
0
def build_call_linux86(funcName, funcArgs, constraint, assertion, clmax=None, optimizeLen=False):
    # Find the address of the fonction 
    (funcName2, funcAddr) = getFunctionAddress(funcName)
    if( funcName2 is None ):
        return "Couldn't find function '{}' in the binary".format(funcName)
    
    # Check if bad bytes in function address 
    if( not constraint.badBytes.verifyAddress(funcAddr) ):
        return "'{}' address ({}) contains bad bytes".format(funcName2, string_special('0x'+format(funcAddr, '0'+str(Arch.octets()*2)+'x')))
    
    # Check if lmax too small
    if( (1 + len(funcArgs) + (lambda x: 1 if len(x)>0 else 0)(funcArgs)) > clmax ):
        return "Not enough bytes to call function '{}'".format(funcName)
    
    # Find a gadget for the fake return address
    if( funcArgs ):
        offset = (len(funcArgs)-1)*Arch.octets() # Because we do +octets() at the beginning of the loop
        skip_args_chains = []
        i = 4 # Try 4 more maximum 
        while( i > 0 and (not skip_args_chains)):
            offset += Arch.octets() 
            skip_args_chains = search(QueryType.MEMtoREG, Arch.ipNum(), \
                        (Arch.spNum(),offset), constraint, assertion, n=1, optimizeLen=optimizeLen)
            i -= 1
            
        if( not skip_args_chains ):
            return "Couldn't build ROP-Chain"
        skip_args_chain = skip_args_chains[0]
    else:
        # No arguments 
        skip_args_chain = None
    
    # Build the ropchain with the arguments 
    args_chain = ROPChain()
    arg_n = len(funcArgs)
    for arg in reversed(funcArgs):
        if( isinstance(arg, int) ):
            args_chain.addPadding(arg, comment="Arg{}: {}".format(arg_n, string_ropg(hex(arg))))
            arg_n -= 1
        else:
            return "Type of argument '{}' not supported yet :'(".format(arg)
    
    # Build call chain (function address + fake return address)
    call_chain = ROPChain()
    call_chain.addPadding(funcAddr, comment=string_ropg(funcName2))
    if( funcArgs ):
        skip_args_addr = int( validAddrStr(skip_args_chain.chain[0], constraint.getBadBytes(), Arch.bits())  ,16)
        call_chain.addPadding(skip_args_addr, comment="Address of: "+string_bold(str(skip_args_chain.chain[0])))
    
    return call_chain.addChain(args_chain)
Example #5
0
def STRtoMEM_strcpy(string,
                    addr,
                    constraint,
                    assertion,
                    limit=None,
                    lmax=STR_TO_MEM_LMAX,
                    addr_str=None,
                    hex_info=False):
    """
    STRCPY STRATEGY
    Copy the string using strcpy function 
    """
    if (not addr_str):
        addr_str = hex(addr)

    # Getting strcpy function
    (func_name, func_addr) = getFunctionAddress('strcpy')
    if (not func_addr):
        verbose('Could not find strcpy function')
        return (None, None)
    elif (not constraint.badBytes.verifyAddress(func_addr)):
        verbose("strcpy address ({}) contains bad bytes".format(
            hex(func_addr)))
        return (None, None)

    # We decompose the string in substrings to be copied
    substrings_addr = findBytes(string,
                                badBytes=constraint.getBadBytes(),
                                add_null=True)
    if (not substrings_addr):
        return (None, None)

    # Find delivery address
    substr_lengthes = [len(substr[1]) - 1
                       for substr in substrings_addr]  # -1 becasue strcpy
    substr_lengthes[-1] += 1
    if (not limit is None):
        custom_stack = find_closest_base_fake_stack_address(
            addr, limit, substr_lengthes, constraint)
        if (custom_stack is None):
            verbose("Couldn't write string in memory because of bad bytes")
            return (None, None)
    else:
        custom_stack = find_closest_base_fake_stack_address(
            addr, addr + sum(substr_lengthes), substr_lengthes, constraint)
        if (custom_stack is None):
            verbose("Couldn't write string in memory because of bad bytes")
            return (None, None)
    if (custom_stack != addr):
        addr_str = hex(custom_stack)

    # Build chain
    res = ROPChain()
    offset = 0
    saved_custom_stack = custom_stack
    for (substring_addr, substring_str) in substrings_addr:
        if (hex_info):
            substring_info = '\\x' + '\\x'.join(
                ["%02x" % ord(c) for c in substring_str])
        else:
            substring_info = substring_str
        commentStack = "Arg2: " + string_ropg("{} + {}".format(
            addr_str, offset))
        commentSubStr = "Arg1: " + string_ropg(substring_info)
        func_call = build_call(func_name, [substring_addr, custom_stack],
                               constraint,
                               assertion, [commentSubStr, commentStack],
                               optimizeLen=True)
        if (isinstance(func_call, str)):
            verbose("strcpy: " + func_call)
            return (None, None)
        else:
            res.addChain(func_call)
            if (len(res) > lmax):
                return (None, None)
        # Adjust
        # -1 Because strcpy has a null byte :/
        # Except when we INTEND to write a null byte
        if (substring_str == '\x00'):
            dec = 0
        else:
            dec = 1
        custom_stack = custom_stack + len(substring_str) - dec
        offset = offset + len(substring_str) - dec

    return (saved_custom_stack, res)
Example #6
0
def popMultiple(args,
                constraint=None,
                assertion=None,
                clmax=None,
                addr=None,
                limit=None,
                optimizeLen=False):
    """
    args is a list of pairs (reg, value) 
        OR a list of triples (reg, value, comment)
    reg is a reg UID
    value is an int OR a string
    addr and limit are used to put strings if args contains strings 
    Creates a chain that pops values into regs
    """
    if (clmax is None):
        clmax = POP_MULTIPLE_LMAX_PER_REG * len(args)
    elif (clmax <= 0):
        return None
    for arg in args:
        if (isinstance(arg, str)):
            clmax += STR_TO_MEM_LMAX

    if (constraint is None):
        constr = Constraint()
    else:
        constr = constraint
    if (assertion is None):
        a = Assertion()
    else:
        a = assertion

    # Get address
    #Find address for the payload
    if (not addr):
        # Get the .bss address
        addr = getSectionAddress('.bss')
        if (not addr):
            return None

    perms = itertools.permutations(args)
    for perm in perms:
        clmax_tmp = clmax
        res = ROPChain()
        constr_tmp = constr
        tmp_addr = addr
        chains = None
        for arg in perm:
            if (len(arg) == 3):
                comment = arg[2]
            else:
                comment = None
            if (isinstance(arg[1], int)):
                chains = search(QueryType.CSTtoREG,
                                arg[0],
                                arg[1],
                                constr_tmp,
                                a,
                                n=1,
                                clmax=clmax_tmp,
                                CSTtoREG_comment=comment,
                                optimizeLen=optimizeLen)
            elif (isinstance(arg[1], str)):
                (address, str_to_mem) = STRtoMEM(arg[1],
                                                 tmp_addr,
                                                 constr_tmp,
                                                 a,
                                                 limit=limit,
                                                 lmax=clmax_tmp,
                                                 addr_str=comment,
                                                 hex_info=True,
                                                 optimizeLen=optimizeLen)
                if (not str_to_mem):
                    break
                tmp_addr = address + len(arg)
                pop = search(QueryType.CSTtoREG,
                             arg[0],
                             address,
                             constr_tmp,
                             a,
                             n=1,
                             clmax=clmax_tmp - len(str_to_mem),
                             optimizeLen=optimizeLen)
                if (not pop):
                    break
                chains = [str_to_mem.addChain(pop[0])]
            else:
                raise Exception(
                    "UNknown argument type in popMultiple: '{}'".format(
                        type(arg)))

            if (not chains):
                break
            else:
                clmax_tmp -= len(chains[0])
                # If Reached max length, exit
                if (clmax_tmp < 0):
                    chains = None
                    break
                else:
                    res.addChain(chains[0])
                    constr_tmp = constr_tmp.add(RegsNotModified([arg[0]]))
        if (chains):
            return res
    return None
Example #7
0
def STRtoMEM_memcpy(string,
                    addr,
                    constraint,
                    assertion,
                    limit=None,
                    lmax=STR_TO_MEM_LMAX,
                    addr_str=None,
                    hex_info=False):
    """
    MEMCPY STRATEGY
    Copy the string using memcpy function 
    """
    if (not addr_str):
        addr_str = hex(addr)

    # Getting strcpy function
    (func_name, func_addr) = getFunctionAddress('memcpy')
    if (not func_addr):
        verbose('Could not find memcpy function')
        return (None, None)
    elif (not constraint.badBytes.verifyAddress(func_addr)):
        verbose("memcpy address ({}) contains bad bytes".format(
            hex(func_addr)))
        return (None, None)

    # We decompose the string in substrings to be copied
    substrings_addr = findBytes(string, badBytes=constraint.getBadBytes())
    if (not substrings_addr):
        return (None, None)

    # Find delivery address
    substr_lengthes = [len(substr[1]) for substr in substrings_addr]
    if (not limit is None):
        custom_stack = find_closest_base_fake_stack_address(
            addr, limit, substr_lengthes, constraint)
        if (custom_stack is None):
            verbose("Couldn't write string in memory because of bad bytes")
            return (None, None)
    else:
        custom_stack = find_closest_base_fake_stack_address(
            addr, addr + sum(substr_lengthes), substr_lengthes, constraint)
        if (custom_stack is None):
            verbose("Couldn't write string in memory because of bad bytes")
            return (None, None)
    if (custom_stack != addr):
        addr_str = hex(custom_stack)

    # Build chain
    res = ROPChain()
    offset = 0
    saved_custom_stack = custom_stack
    for (substring_addr, substring_str) in substrings_addr:
        if (hex_info):
            substring_info = "'" + '\\x' + '\\x'.join(
                ["%02x" % ord(c) for c in substring_str]) + "'"
        else:
            substring_info = "'" + substring_str + "'"
        comment3 = "Arg3: " + string_ropg(str(len(substring_str)))
        comment2 = "Arg2: " + string_ropg(substring_info)
        comment1 = "Arg1: " + string_ropg("{} + {}".format(addr_str, offset))

        func_call = build_call(func_name, [custom_stack, substring_addr, len(substring_str)],\
                    constraint, assertion, [comment1, comment2, comment3], optimizeLen=True)

        if (isinstance(func_call, str)):
            verbose("memcpy: " + func_call)
            return (None, None)

        res.addChain(func_call)
        if (len(res) > lmax):
            return (None, None)

        # Adjust
        custom_stack = custom_stack + len(substring_str)
        offset = offset + len(substring_str)

    return (saved_custom_stack, res)