Example #1
0
def find(args):
    """
    args - List of user arguments as strings
    (the command should not be included in the list as args[0])
    """
    if (not args):
        print_help()
        return

    if (args[0] == OPTION_HELP or args[0] == OPTION_HELP_SHORT):
        print_help()
        return

    parsed_args = parse_args(args)
    if (not parsed_args[0]):
        error(parsed_args[1])
    else:
        qtype = parsed_args[1]
        arg1 = parsed_args[2]
        arg2 = parsed_args[3]
        constraint = parsed_args[4]
        nbResults = parsed_args[5]
        clmax = parsed_args[6]
        optimizeLen = parsed_args[7]
        assertion = getBaseAssertion()
        # Search
        res = search(qtype,
                     arg1,
                     arg2,
                     constraint,
                     assertion,
                     n=nbResults,
                     clmax=clmax,
                     optimizeLen=optimizeLen)
        if (res):
            print_chains(res, "Built matching ROPChain(s)",
                         constraint.getBadBytes())
        else:
            res = search_not_chainable(qtype,
                                       arg1,
                                       arg2,
                                       constraint,
                                       assertion,
                                       n=nbResults,
                                       clmax=clmax)
            print_chains(res, "Possibly matching gadget(s)",
                         constraint.getBadBytes())
Example #2
0
def pwn(args):
    global OUTPUT, OUTPUT_CONSOLE, OUTPUT_PYTHON
    global EXPLOIT_LMAX
    
    
    if( not args ):
        print_help()
        return 
        
    # Check if gadgets have been loaded in the DB 
    if( not Database.gadgets ):
        error("Oops. You have to load gadgets before pwning ;) ")
        return 
        
    # Set default output format 
    OUTPUT = OUTPUT_CONSOLE
    clmax = EXPLOIT_LMAX
    offset = 0 
    
    seenOffset = False
    seenOutput = False
    seenLmax = False
    seenBadBytes = False
    seenVerbose = False
    seenOutfile = False
    seenPaddingByte = False
    seenPaddingLen = False

    constraint = Constraint()
    assertion = getBaseAssertion()
    subcommand = None
    outfile = None
    paddingByteStr = None 
    paddingLen = 0
    
    i = 0 
    while i < len(args):
        # Parse options     
        if( args[i][0] == '-' ):
            if( args[i] in [OPTION_BAD_BYTES, OPTION_BAD_BYTES_SHORT]):
                if( seenBadBytes ):
                    error("Error. '" + args[i] + "' option should be used only once")
                    return 
                if( i+1 >= len(args)):
                    error("Error. Missing bad bytes after option '"+args[i]+"'")
                    return 
                seenBadBytes = True
                (success, res) = parse_bad_bytes(args[i+1])
                if( not success ):
                    error(res)
                    return
                i = i+2
                constraint = constraint.add(BadBytes(res))
            elif( args[i] == OPTION_LMAX or args[i] == OPTION_LMAX_SHORT ):
                if( seenLmax ):
                    error("Error. '" + arg + "' option should be used only once.")
                    return 
                if( i+1 >= len(args)):
                    error("Error. Missing output format after option '"+arg+"'")
                    return 
                try:
                    clmax = int(args[i+1])
                    if( clmax < Arch.octets() ):
                        raise Exception()
                    # Convert number of bytes into number of ropchain elements
                    clmax /= Arch.octets()
                except:
                    error("Error. '" + args[i+1] +"' bytes is not valid")
                    return 
                i = i +2
                seenLmax = True
                       
            elif( args[i] in [OPTION_OUTPUT, OPTION_OUTPUT_SHORT]):
                if( seenOutput ):
                    error("Option '{}' should be used only once".format(args[i]))
                    return 
                if( i+1 >= len(args)):
                    error("Error. Missing output format after option '"+args[i]+"'")
                    return 
                if( args[i+1] in [OUTPUT_CONSOLE, OUTPUT_PYTHON]):
                    OUTPUT = args[i+1]
                    seenOutput = True
                    i += 2
                else:
                    error("Error. Unknown output format: {}".format(args[i+1]))
                    return 
            elif( args[i] in [OPTION_OUTFILE_SHORT, OPTION_OUTFILE] ):
                if( seenOutfile ):
                    error("Option '{}' should be used only once".format(args[i]))
                    return 
                if( i+1 >= len(args)):
                    error("Error. Missing file name after option '"+args[i]+"'")
                    return 
                seenOutfile = True
                outfile = args[i+1]
                i += 2
            elif( args[i] in [OPTION_PADDING_BYTE, OPTION_PADDING_BYTE_SHORT] ):
                if( seenPaddingByte ):
                    error("Option '{}' should be used only once".format(args[i]))
                    return 
                if( i+1 >= len(args)):
                    error("Error. Missing byte after option '"+args[i]+"'")
                    return 
                seenPaddingByte = True
                try:
                    paddingByte = int(args[i+1], 16)
                except:
                    error("Error. '{}' is not a valid byte".format(args[i+1]))
                    return 
                if( paddingByte > 0xff ):
                    error("Error. '{}' can't be stored in one byte".format(args[i+1]))
                    return
                paddingByteStr = "\\x"+format(paddingByte, "02x")
                i += 2
            elif( args[i] in [OPTION_PADDING_LEN, OPTION_PADDING_LEN_SHORT] ):
                if( seenPaddingLen ):
                    error("Option '{}' should be used only once".format(args[i]))
                    return 
                if( i+1 >= len(args)):
                    error("Error. Missing length after option '"+args[i]+"'")
                    return 
                seenPaddingLen = True
                try:
                    paddingLen = int(args[i+1], 10)
                except:
                    try:
                        paddingLen = int(args[i+1], 16)
                    except:
                        error("Error. '{}' is not a valid byte".format(args[i+1]))
                        return 
                if( paddingLen < 0 ):
                    error("Error. Padding length must be > 0")
                    return 
                i += 2
            elif( args[i] in [OPTION_OFFSET, OPTION_OFFSET_SHORT] ):
                if( seenOffset ):
                    error("Option '{}' should be used only once".format(args[i]))
                    return 
                if( i+1 >= len(args)):
                    error("Error. Missing offset after option '"+args[i]+"'")
                    return 
                seenOffset = True
                try:
                    offset = int(args[i+1], 10)
                except:
                    try:
                        offset = int(args[i+1], 16)
                    except:
                        error("Error. '{}' is not a valid offset".format(args[i+1]))
                        return 
                if( paddingLen < 0 ):
                    error("Error. Offset must be > 0")
                    return 
                i += 2
            elif( args[i] in [OPTION_HELP, OPTION_HELP_SHORT]):
                print_help()
                return 
            elif( args[i] in [OPTION_VERBOSE, OPTION_VERBOSE_SHORT]):
                seenVerbose = True
                i += 1
            else:
                error("Error. Unknown option '{}'".format(args[i]))
                return 
                
        # Parse a subcommand
        else:
            # Before parsing, check arguments 
            # Check arguments 
            if( seenPaddingByte and not seenPaddingLen ):
                error("Error. You have to specify padding length if you provide a padding byte. See the '-pl,--padding-length' option")
                return 
            # Parse and execute subcommand 
            verbose_mode(seenVerbose)
            payload = None
            
            ### set offset 
            if( not set_offset(offset)):
                error("Error. Your offset is too big :'(")
                return 
            try:
                ## Execute strategy
                if( args[i] == CMD_DELIVER_SHELLCODE ):
                    payload = dshell(args[i+1:], constraint, assertion, lmax=clmax)
                else:
                    error("Error. Unknown subcommand : '{}'".format(args[i]))
                    verbose_mode(False)
                    return 
            
                # Print result 
                verbose_mode(False)
                if( payload == "help"):
                    return 
                elif( not payload is None ):
                    print(string_bold("\n\tBuilt exploit - {} bytes\n".format(payload.len_bytes)))
                    # Normal output 
                    if( OUTPUT == OUTPUT_CONSOLE ):
                        payload_string = payload.strConsole(Arch.bits(), constraint.getBadBytes())
                    elif( OUTPUT == OUTPUT_PYTHON ):
                        payload_string = payload.strPython(Arch.bits(), constraint.getBadBytes(), \
                            noTab=seenOutfile, paddingByteStr=paddingByteStr, paddingLen=paddingLen)
                    # Output to file
                    if( outfile ):
                        try: 
                            f = open(outfile, "w")
                            f.write(remove_colors(payload_string))
                            f.close()
                            print(string_bold("\n\tWrote payload in file '{}'\n".format(outfile)))
                        except:
                            error("Error. Couldn't not write payload in file '{}'".format(outfile))
                    else:
                        print(payload_string)
                else:
                    error("Couldn't generate exploit")
            except Exception, e:
                reset_offset()
                raise sys.exc_info()[1], None, sys.exc_info()[2]
            
            ### reset offset 
            reset_offset()
            return 
Example #3
0
def syscall(args):
    global OUTPUT, OUTPUT_CONSOLE, OUTPUT_PYTHON
    # Parsing arguments
    if( not args):
        print_help()
        return
    OUTPUT = OUTPUT_CONSOLE
    funcName = None
    offset = 0
    i = 0
    seenOutput = False
    seenFunction = False
    seenBadBytes = False
    seenKeepRegs = False
    seenOffset = False
    
    constraint = Constraint()
    assertion = getBaseAssertion()
    while i < len(args):
        if( args[i] in [OPTION_LIST, OPTION_LIST_SHORT]):
            listSyscalls(args[1:])
            return 
        if( args[i] in [OPTION_BAD_BYTES, OPTION_BAD_BYTES_SHORT]):
            if( seenBadBytes ):
                error("Error. '" + args[i] + "' option should be used only once")
                return 
            if( i+1 >= len(args)):
                error("Error. Missing bad bytes after option '"+args[i]+"'")
                return 
            seenBadBytes = True
            (success, res) = parse_bad_bytes(args[i+1])
            if( not success ):
                error(res)
                return
            i = i+2
            constraint = constraint.add(BadBytes(res))
        elif( args[i] in [OPTION_KEEP_REGS, OPTION_KEEP_REGS_SHORT]):
            if( seenKeepRegs ):
                error("Error. '" + args[i] + "' option should be used only once")
                return 
            if( i+1 >= len(args)):
                error("Error. Missing register after option '"+args[i]+"'")
                return 
            seenKeepRegs = True
            (success, res) = parse_keep_regs(args[i+1])
            if( not success ):
                error(res)
                return
            i = i+2
            constraint = constraint.add(RegsNotModified(res))
        elif( args[i] == OPTION_OFFSET or args[i] == OPTION_OFFSET_SHORT ):
            if( seenOffset ):
                error("Error. '"+ args[i] + "' option should be used only once")
                return 
            if( i+1 >= len(args)):
                error("Error. Missing offset after option '"+args[i]+"'")
                return 
            try:
                offset = int(args[i+1])
                if( offset < 0 ):
                    raise Exception()
            except:
                try:
                    offset = int(args[i+1], 16)
                    if( offset < 0 ):
                        raise Exception()
                except: 
                    error("Error. '" + args[i+1] +"' is not a valid offset")
                    return 
            i += 2 
            seenOffset = True
        elif( args[i] in [OPTION_FUNCTION, OPTION_FUNCTION_SHORT] ):
            if( not loadedBinary() ):
                error("Error. You should load a binary before building ROPChains")
                return 
            elif( seenFunction ):
                error("Option '{}' should be used only once".format(args[i]))
                return  
            userInput = ''
            i +=1
            while( i < len(args) and args[i][0] != "-"):
                userInput += args[i]
                i += 1
            (funcName, funcArgs ) = parseFunction(userInput)
            if( not funcName):
                return 
            seenFunction = True
        elif( args[i] in [OPTION_OUTPUT, OPTION_OUTPUT_SHORT]):
            if( seenOutput ):
                error("Option '{}' should be used only once".format(args[i]))
                return 
            if( i+1 >= len(args)):
                error("Error. Missing output format after option '"+args[i]+"'")
                return 
            if( args[i+1] in [OUTPUT_CONSOLE, OUTPUT_PYTHON]):
                OUTPUT = args[i+1]
                seenOutput = True
                i += 2
            else:
                error("Error. Unknown output format: {}".format(args[i+1]))
                return 
        elif( args[i] in [OPTION_HELP, OPTION_HELP_SHORT]):
            print_help()
            return 
        else:
            error("Error. Unknown option '{}'".format(args[i]))
            return 
    
    if( not funcName ):
        error("Missing function to call")
    else:
        # Set offset 
        if ( not set_offset(offset) ):
            error("Error. Your offset is too big :'(")
            return 
        try:
            call(funcName, funcArgs, constraint, assertion)
        except Exception, e:
            reset_offset()
            import sys
            raise sys.exc_info()[1], None, sys.exc_info()[2]
        # Reset offset 
        reset_offset()
Example #4
0
def build_syscall_Linux(syscall,
                        arg_list,
                        arch_bits,
                        constraint=None,
                        assertion=None,
                        clmax=SYSCALL_LMAX,
                        optimizeLen=False):
    """
    arch_bits = 32 or 64 :) 
    """
    # Check args
    if (syscall.nb_args() != len(arg_list)):
        error("Error. Expected {} arguments, got {}".format(
            len(syscall.arg_types), len(arg_list)))
        return None
    # Check args length
    for i in range(0, len(arg_list)):
        if (not verifyArgType(arg_list[i], syscall.arg_types[i])):
            error("Argument error for '{}': expected '{}', got '{}'".format(
                arg_list[i], syscall.arg_types[i], type(arg_list[i])))
            return None
    # Check constraint and assertion
    if (constraint is None):
        constraint = Constraint()
    if (assertion is None):
        assertion = getBaseAssertion()

    # Check if we have the function !
    verbose("Trying to call {}() function directly".format(syscall.def_name))
    func_call = build_call(syscall.function(),
                           arg_list,
                           constraint,
                           assertion,
                           clmax=clmax,
                           optimizeLen=optimizeLen)
    if (not isinstance(func_call, str)):
        verbose("Success")
        return func_call
    else:
        if (not constraint.chainable.ret):
            verbose("Coudn't call {}(), try direct syscall".format(
                syscall.def_name))
        else:
            verbose("Couldn't call {}() and return to ROPChain".format(
                syscall.def_name))
            return None

    # Otherwise do syscall directly
    # Set the registers
    args = [(Arch.n2r(x[0]), x[1])
            for x in zip(syscall.arg_regs, arg_list) + syscall.syscall_arg_regs
            ]
    chain = popMultiple(args,
                        constraint,
                        assertion,
                        clmax - 1,
                        optimizeLen=optimizeLen)
    if (not chain):
        verbose("Failed to set registers for the mprotect syscall")
        return None
    # Int 0x80
    if (arch_bits == 32):
        syscall_gadgets = search(QueryType.INT80, None, None, constraint,
                                 assertion)
    # syscall
    elif (arch_bits == 64):
        syscall_gadgets = search(QueryType.SYSCALL, None, None, constraint,
                                 assertion)
    if (not syscall_gadgets):
        verbose("Failed to find an 'int 0x80' OR 'syscall' gadget")
        return None
    else:
        chain.addChain(syscall_gadgets[0])
    verbose("Success")
    return chain
Example #5
0
def call(args):
    global OUTPUT, OUTPUT_CONSOLE, OUTPUT_PYTHON
    # Parsing arguments
    if( not args):
        print_help()
        return
    OUTPUT = OUTPUT_CONSOLE
    funcName = None
    i = 0
    seenOutput = False
    seenFunction = False
    seenBadBytes = False
    seenKeepRegs = False
    seenShortest = False
    seenLmax = False
    seenOffset = False
    clmax = None
    offset = 0 
    
    constraint = Constraint()
    assertion = getBaseAssertion()
    while i < len(args):
        if( args[i] in [OPTION_LIST, OPTION_LIST_SHORT]):
            func_list = getAllFunctions()
            print_functions(func_list)
            return 
        if( args[i] in [OPTION_BAD_BYTES, OPTION_BAD_BYTES_SHORT]):
            if( seenBadBytes ):
                error("Error. '" + args[i] + "' option should be used only once")
                return 
            if( i+1 >= len(args)):
                error("Error. Missing bad bytes after option '"+args[i]+"'")
                return 
            seenBadBytes = True
            (success, res) = parse_bad_bytes(args[i+1])
            if( not success ):
                error(res)
                return
            i = i+2
            constraint = constraint.add(BadBytes(res))
        elif( args[i] in [OPTION_KEEP_REGS, OPTION_KEEP_REGS_SHORT]):
            if( seenKeepRegs ):
                error("Error. '" + args[i] + "' option should be used only once")
                return 
            if( i+1 >= len(args)):
                error("Error. Missing register after option '"+args[i]+"'")
                return 
            seenKeepRegs = True
            (success, res) = parse_keep_regs(args[i+1])
            if( not success ):
                error(res)
                return
            i = i+2
            constraint = constraint.add(RegsNotModified(res))
        elif( args[i] in [OPTION_CALL, OPTION_CALL_SHORT] ):
            if( not loadedBinary() ):
                error("Error. You should load a binary before building ROPChains")
                return 
            elif( seenFunction ):
                error("Option '{}' should be used only once".format(args[i]))
                return  
            userInput = ''
            i +=1
            while( i < len(args) and args[i][0] != "-"):
                userInput += args[i]
                i += 1
            (funcName, funcArgs ) = parseFunction(userInput)
            if( not funcName):
                return 
            seenFunction = True
        elif( args[i] in [OPTION_OUTPUT, OPTION_OUTPUT_SHORT]):
            if( seenOutput ):
                error("Option '{}' should be used only once".format(args[i]))
                return 
            if( i+1 >= len(args)):
                error("Error. Missing output format after option '"+args[i]+"'")
                return 
            if( args[i+1] in [OUTPUT_CONSOLE, OUTPUT_PYTHON]):
                OUTPUT = args[i+1]
                seenOutput = True
                i += 2
            else:
                error("Error. Unknown output format: {}".format(args[i+1]))
                return 
        elif( args[i] in [OPTION_SHORTEST, OPTION_SHORTEST_SHORT]):
            if( seenShortest ):
                error("Option '{}' should be used only once".format(args[i]))
                return 
            seenShortest = True
            i += 1
        elif( args[i] == OPTION_LMAX or args[i] == OPTION_LMAX_SHORT ):
            if( seenLmax ):
                error("Option '{}' should be used only once".format(args[i]))
                return 
            if( i+1 >= len(args)):
                error("Error. Missing length after option '"+args[i]+"'")
                return 
            try:
                clmax = int(args[i+1])
                if( clmax < Arch.octets() ):
                    raise Exception()
                # Convert number of bytes into number of ropchain elements
                clmax /= Arch.octets()
            except:
                error("Error. '" + args[i+1] +"' bytes is not valid")
                return 
            i += 2 
            seenLmax = True
        elif( args[i] == OPTION_OFFSET or args[i] == OPTION_OFFSET_SHORT ):
            if( seenOffset ):
                error("Option '{}' should be used only once".format(args[i]))
                return 
            if( i+1 >= len(args)):
                error("Error. Missing offset after option '"+args[i]+"'")
                return 
            try:
                offset = int(args[i+1])
                if( offset < 0 ):
                    raise Exception()
            except:
                try:
                    offset = int(args[i+1], 16)
                    if( offset < 0 ):
                        raise Exception()
                except: 
                    error("Error. '" + args[i+1] +"' is not a valid offset")
                    return 
            i += 2 
            seenOffset = True
        elif( args[i] in [OPTION_HELP, OPTION_HELP_SHORT]):
            print_help()
            return 
        else:
            error("Error. Unknown option '{}'".format(args[i]))
            return 
    
    if( not funcName ):
        error("Missing function to call")
    else:
        # Set offset 
        if( not set_offset(offset) ):
            error("Error. Your offset is too big :'(")
            return 
        try:
            res = build_call(funcName, funcArgs, constraint, assertion, clmax=clmax, optimizeLen=seenShortest)
            if( isinstance(res, str) ):
                error(res)
            else:
                print_chains([res], "Built matching ROPChain", constraint.getBadBytes())
        except Exception, e:
            reset_offset()
            raise sys.exc_info()[1], None, sys.exc_info()[2]
        # Reset offset 
        reset_offset()