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 seenOutput = False seenLmax = False seenBadBytes = False seenVerbose = False seenOutfile = False seenPaddingByte = False seenPaddingLen = False constraint = Constraint() assertion = Assertion() 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_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 subcommand verbose_mode(seenVerbose) payload = None 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 verbose_mode(False) # Print result 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") return # Test parsing result if( subcommand is None ): error("Missing subcommand") return
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 seenOutput = False seenLmax = False seenBadBytes = False seenVerbose = False constraint = Constraint() assertion = Assertion() subcommand = None 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_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: verbose_mode(seenVerbose) payload = None 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 verbose_mode(False) # Print result if (payload): print( string_bold("\n\tBuilt exploit - {} bytes\n".format( payload.len_bytes))) if (OUTPUT == OUTPUT_CONSOLE): print( payload.strConsole(Arch.bits(), constraint.getBadBytes())) elif (OUTPUT == OUTPUT_PYTHON): print( payload.strPython(Arch.bits(), constraint.getBadBytes())) else: error("Couldn't generate exploit") return # Test parsing result if (subcommand is None): error("Missing subcommand") return
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()
def syscall(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 constraint = Constraint() assertion = Assertion() 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] 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: call(funcName, funcArgs, constraint, assertion)
def parse_args(args): """ Parse the user supplied arguments to the 'find' function Returns either a tuple (True, GadgetType, x, y, constraint, nb_res, clmax ) Or if not supported or invalid arguments, returns a tuple (False, msg) ---> See parse_user_request() specification for the list of possible tuples and values/types of x and y """ global OUTPUT seenExpr = False seenBadBytes = False seenKeepRegs = False seenOutput = False seenNbResults = False seenLmax = False i = 0 # Argument counter constraint = Constraint() nbResults = 1 # Default 1 result clmax = LMAX # Max length OUTPUT = OUTPUT_CONSOLE while (i < len(args)): arg = args[i] # Look for options if (arg[0] == '-' and arg[1] != '>'): if (seenExpr): return (False, "Error. Options must come before the search request") # bad bytes option if (arg == OPTION_BAD_BYTES or arg == OPTION_BAD_BYTES_SHORT): if (seenBadBytes): return (False, "Error. '" + arg + "' option should be used only once") if (i + 1 >= len(args)): return (False, "Error. Missing bad bytes after option '" + arg + "'") seenBadBytes = True (success, res) = parse_bad_bytes(args[i + 1]) if (not success): return (False, res) i = i + 1 constraint = constraint.add(BadBytes(res)) # Keep regs option elif (arg == OPTION_KEEP_REGS or arg == OPTION_KEEP_REGS_SHORT): if (seenKeepRegs): return (False, "Error. '" + arg + "' option should be used only once.") if (i + 1 >= len(args)): return (False, "Error. Missing registers after option '" + arg + "'") seenKeepRegs = True (success, res) = parse_keep_regs(args[i + 1]) if (not success): return (False, res) i = i + 1 constraint = constraint.add(RegsNotModified(res)) # Output option elif (arg == OPTION_OUTPUT or arg == OPTION_OUTPUT_SHORT): if (seenOutput): return (False, "Error. '" + arg + "' option should be used only once.") if (i + 1 >= len(args)): return (False, "Error. Missing output format after option '" + arg + "'") if (args[i + 1] in [OUTPUT_CONSOLE, OUTPUT_PYTHON]): OUTPUT = args[i + 1] seenOutput = True i = i + 1 else: return (False, "Error. '" + args[i + 1] + "' output format is not supported") # Nb of results option elif (arg == OPTION_NB_RESULTS or arg == OPTION_NB_RESULTS_SHORT): if (seenNbResults): return (False, "Error. '" + arg + "' option should be used only once.") if (i + 1 >= len(args)): return (False, "Error. Missing output format after option '" + arg + "'") try: nbResults = int(args[i + 1]) if (nbResults <= 0): raise Exception() except: return (False, "Error. '" + args[i + 1] + "' is not a valid number") i = i + 1 seenNbResults = True elif (arg == OPTION_LMAX or arg == OPTION_LMAX_SHORT): if (seenLmax): return (False, "Error. '" + arg + "' option should be used only once.") if (i + 1 >= len(args)): return (False, "Error. Missing output format after option '" + arg + "'") 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: return (False, "Error. '" + args[i + 1] + "' bytes is not valid") i = i + 1 seenLmax = True # Otherwise Ignore else: return (False, "Error. Unknown option: '{}' ".format(arg)) # If not option it should be a request expr=expr else: if (seenExpr): return (False, "Error. Unexpected extra expression: '" + ' '.join(args[i:]) + "'") else: seenExpr = True parsed_query = parse_query(''.join(args[i:])) if (not parsed_query[0]): return (False, parsed_query[1]) else: i = len(args) i = i + 1 if (not seenExpr): return (False, "Error. Missing specification of gadget to find") else: return parsed_query + (constraint, nbResults, clmax)
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()