def list_syscalls(args): local_available_archs = [ArchType.ARCH_X86, ArchType.ARCH_X64] # Parse args systems = [] archs = [] for arg in args: if (arg in Systems.available_systems_str()): systems.append(Systems.str_to_target_system(arg)) elif (is_supported_arch_str(arg)): archs.append(str_to_arch_type(arg)) else: error("Unknown system/arch: '{}'".format(arg)) return if ((not systems)): systems = Systems.available_systems() if (not archs): archs = available_archs_type() # Remove duplicates systems = list(set(systems)) archs = list(set(archs)) # Print for system in systems: for arch in archs: if (system == Systems.TargetSystem.Linux and arch == ArchType.ARCH_X86): available = LinuxX86.available_syscalls() print(str_bold("\n\n\tSupported Linux X86 syscalls")) print_syscalls_list(available) elif (system == Systems.TargetSystem.Linux and arch == ArchType.ARCH_X64): available = LinuxX64.available_syscalls() print(str_bold("\n\n\tSupported Linux X64 syscalls")) print_syscalls_list(available)
def exploit_mode(): """ Returns ------- True if ROPGenerator must continue False if ROPGenerator must be closed """ finish = False while( not finish ): try: # Get command user_input = promptSession.prompt() args = user_input.split() argslen = len(args) if( argslen > 0 ): command = args[0] else: command = None continue # Execute command if( command == CMD_SHELLCODE ): shellcode(args[1:]) elif( command == CMD_SYSCALL ): syscall(args[1:]) elif( command == CMD_FUNCTION ): function(args[1:]) elif( command == CMD_EXIT ): return False elif( command == CMD_HELP ): print(helpStr) elif( command == CMD_MAIN ): finish = True elif( command == CMD_DSHELL ): deliver_shellcode(args[1:]) else: error("Unknown command '{}'".format(command)) if( command != None ): print('') except KeyboardInterrupt: pass return True
def deliver_shellcode(args): global OUTPUT, OUTPUT_CONSOLE, OUTPUT_PYTHON if (not args): print_help() return OUTPUT = OUTPUT_CONSOLE offset = 0 i = 0 seenOutput = False seenBadBytes = False seenKeepRegs = False seenShortest = False seenLmax = False seenOffset = False seenRw = False bad_bytes = [] keep_regs = [] lmax = get_default_lmax() * 6 # 6 is an arbitrary value here lower_valid_write_addr = 0 higher_valid_write_addr = 0 verbose = False # Parsing arguments # First argument must be the target OS if (len(args) == 0): error("Missing arguments") return system = Systems.str_to_target_system(args[0]) if (system is None): error("Unsupported system '" + args[0] + "'") print( str_bold("\tSupported systems") + ": " + ', '.join( [str_special(s) for s in Systems.available_systems_str()])) return # Then parse the options args = args[1:] while i < len(args): arg = args[i] if (args[i] in [OPTION_BAD_BYTES, OPTION_BAD_BYTES_SHORT]): if (seenBadBytes): error("'" + arg + "' option should be used only once.") return if (i + 1 >= len(args)): error("Missing bad bytes after option '" + arg + "'") return seenBadBytes = True (success, bad_bytes) = parse_bad_bytes(args[i + 1]) if (not success): error(bad_bytes) return i = i + 1 elif (args[i] in [OPTION_KEEP_REGS, OPTION_KEEP_REGS_SHORT]): if (seenKeepRegs): error("'" + arg + "' option should be used only once.") return if (i + 1 >= len(args)): error("Missing registers after option '" + arg + "'") return seenKeepRegs = True (success, keep_regs) = parse_keep_regs(args[i + 1]) if (not success): error(keep_regs) return i = i + 1 elif (args[i] == OPTION_OFFSET or args[i] == OPTION_OFFSET_SHORT): if (seenOffset): error("'" + arg + "' option should be used only once.") return if (i + 1 >= len(args)): error("Missing output format after option '" + arg + "'") return (success, offset) = parse_offset(args[i + 1]) if (not success): error(offset) return i = i + 1 seenOffset = True elif (args[i] in [OPTION_RW_MEMORY, OPTION_RW_MEMORY_SHORT]): if (seenRw): error("'" + arg + "' option should be used only once.") return if (i + 1 >= len(args)): error("Missing address range after option '" + arg + "'") return seenRw = True (success, addr_range) = parse_range(args[i + 1]) if (not success): error(addr_range) return (lower_valid_write_addr, higher_valid_write_addr) = addr_range i = i + 1 elif (args[i] in [OPTION_SHORTEST, OPTION_SHORTEST_SHORT]): if (seenShortest): error("'" + arg + "' option should be used only once.") return seenShortest = True elif (args[i] == OPTION_LMAX or args[i] == OPTION_LMAX_SHORT): if (seenLmax): error("'" + arg + "' option should be used only once.") return if (i + 1 >= len(args)): error("Missing length after option '" + arg + "'") return (success, lmax) = parse_lmax(args[i + 1]) if (not success): error(lmax) return i = i + 1 seenLmax = True elif (args[i] in [OPTION_OUTPUT, OPTION_OUTPUT_SHORT]): if (seenOutput): error("'" + arg + "' option should be used only once.") return if (i + 1 >= len(args)): error("Missing output format after option '" + arg + "'") return if (args[i + 1] in [OUTPUT_CONSOLE, OUTPUT_PYTHON]): OUTPUT = args[i + 1] seenOutput = True i = i + 1 else: error("'" + args[i + 1] + "' output format is not supported") return elif (args[i] in [OPTION_VERBOSE, OPTION_VERBOSE_SHORT]): verbose = True elif (args[i] in [OPTION_HELP, OPTION_HELP_SHORT]): print_help() return else: error("Error. Unknown option '{}'".format(args[i])) return i += 1 # Check if the user loaded some binaries if (not loaded_binary()): error("You should load a binary before building ROPChains") return # Check for valid writable memory to copy strings if (lower_valid_write_addr == 0): (lower_valid_write_addr, higher_valid_write_addr) = get_readwrite_memory() # Select shellcode (shellcode, description) = select_shellcode(curr_arch_type()) if (shellcode is None): return # Set offset set_gadgets_offset(offset) set_binary_offset(offset) # Set verbose set_io_verbose(verbose) # Build the ropchain print('') info("Building exploit: Alloc-Copy-Execute strategy \n\n") params = SearchParametersBinding( keep_regs, bad_bytes, lmax, seenShortest, lower_valid_write_addr=lower_valid_write_addr, higher_valid_write_addr=higher_valid_write_addr) res = deliver_shellcode_build(shellcode, params, system) # Print result if (res is None): error("No matching ROPChain found") elif (isinstance(res, str)): error(res) else: print('') if (OUTPUT == OUTPUT_CONSOLE): print(res.to_str_console(curr_arch_octets(), bad_bytes)) elif (OUTPUT == OUTPUT_PYTHON): print(res.to_str_python(curr_arch_octets(), bad_bytes)) # Reset offset set_gadgets_offset(0) set_binary_offset(0) # Reset verbose set_io_verbose(False)
def syscall(args): global OUTPUT, OUTPUT_CONSOLE, OUTPUT_PYTHON if (not args): print_help() return OUTPUT = OUTPUT_CONSOLE funcName = None offset = 0 i = 0 seenOutput = False seenFunction = False seenBadBytes = False seenKeepRegs = False seenShortest = False seenLmax = False seenOffset = False seenRw = False bad_bytes = [] keep_regs = [] lmax = get_default_lmax() additionnal_lmax = 0 lower_valid_write_addr = 0 higher_valid_write_addr = 0 # Parsing arguments while i < len(args): arg = args[i] if (args[i] in [OPTION_LIST, OPTION_LIST_SHORT]): list_syscalls(args[1:]) return if (args[i] in [OPTION_BAD_BYTES, OPTION_BAD_BYTES_SHORT]): if (seenBadBytes): error("'" + arg + "' option should be used only once.") return if (i + 1 >= len(args)): error("Missing bad bytes after option '" + arg + "'") return seenBadBytes = True (success, bad_bytes) = parse_bad_bytes(args[i + 1]) if (not success): error(bad_bytes) return i = i + 1 elif (args[i] in [OPTION_KEEP_REGS, OPTION_KEEP_REGS_SHORT]): if (seenKeepRegs): error("'" + arg + "' option should be used only once.") return if (i + 1 >= len(args)): error("Missing registers after option '" + arg + "'") return seenKeepRegs = True (success, keep_regs) = parse_keep_regs(args[i + 1]) if (not success): error(keep_regs) return i = i + 1 elif (args[i] == OPTION_OFFSET or args[i] == OPTION_OFFSET_SHORT): if (seenOffset): error("'" + arg + "' option should be used only once.") return if (i + 1 >= len(args)): error("Missing output format after option '" + arg + "'") return (success, offset) = parse_offset(args[i + 1]) if (not success): error(offset) return i = i + 1 seenOffset = True elif (args[i] in [OPTION_RW_MEMORY, OPTION_RW_MEMORY_SHORT]): if (seenRw): error("'" + arg + "' option should be used only once.") return if (i + 1 >= len(args)): error("Missing address range after option '" + arg + "'") return seenRw = True (success, addr_range) = parse_range(args[i + 1]) if (not success): error(addr_range) return (lower_valid_write_addr, higher_valid_write_addr) = addr_range i = i + 1 elif (args[i] in [OPTION_SHORTEST, OPTION_SHORTEST_SHORT]): if (seenShortest): error("'" + arg + "' option should be used only once.") return seenShortest = True elif (args[i] == OPTION_LMAX or args[i] == OPTION_LMAX_SHORT): if (seenLmax): error("'" + arg + "' option should be used only once.") return if (i + 1 >= len(args)): error("Missing length after option '" + arg + "'") return (success, lmax) = parse_lmax(args[i + 1]) if (not success): error(lmax) return i = i + 1 seenLmax = True elif (args[i] in [OPTION_FUNCTION, OPTION_FUNCTION_SHORT]): if (not loaded_binary()): error("You should load a binary before building ROPChains") return elif (seenFunction): error("Option '{}' should be used only once".format(args[i])) return # Get system if (i + 1 >= len(args)): error("Missing argument after option '" + arg + "'") return system = Systems.str_to_target_system(args[i + 1]) if (system is None): error("Unsupported system '" + args[i + 1] + "'") print( str_bold("\tSupported systems") + ": " + ', '.join([ str_special(s) for s in Systems.available_systems_str() ])) return i += 1 # Get function userInput = '' while (i + 1 < len(args) and args[i + 1][0] != "-"): userInput += args[i + 1] i += 1 (funcName, funcArgs) = parse_function(userInput) if (not funcName): error(funcArgs) return seenFunction = True # Get additionnal lmax if string arguments for funcArg in funcArgs: if (isinstance(funcArg, str)): additionnal_lmax += len(funcArg) * curr_arch_octets( ) * 6 # 6 arbitrary max gadgets to copy one byte :/ elif (args[i] in [OPTION_OUTPUT, OPTION_OUTPUT_SHORT]): if (seenOutput): error("'" + arg + "' option should be used only once.") return if (i + 1 >= len(args)): error("Missing output format after option '" + arg + "'") return if (args[i + 1] in [OUTPUT_CONSOLE, OUTPUT_PYTHON]): OUTPUT = args[i + 1] seenOutput = True i = i + 1 else: error("'" + args[i + 1] + "' output format is not supported") return elif (args[i] in [OPTION_HELP, OPTION_HELP_SHORT]): print_help() return else: error("Error. Unknown option '{}'".format(args[i])) return i += 1 # Do the search if (not funcName): error("Missing function to call") return else: # Set offset set_gadgets_offset(offset) set_binary_offset(offset) # Check for valid writable memory to copy strings (!DO IT AFTER SETTING OFFSET) if (lower_valid_write_addr == 0): (lower_valid_write_addr, higher_valid_write_addr) = get_readwrite_memory() # If no max len specified, adjust it for string arguments if (not seenLmax): lmax += additionnal_lmax # Make syscall params = SearchParametersBinding( keep_regs, bad_bytes, lmax, seenShortest, lower_valid_write_addr=lower_valid_write_addr, higher_valid_write_addr=higher_valid_write_addr) res = build_syscall(funcName, funcArgs, params, system) # Print result if (res is None): error("No matching ROPChain found") elif (isinstance(res, str)): error(res) else: print('') if (OUTPUT == OUTPUT_CONSOLE): print(res.to_str_console(curr_arch_octets(), bad_bytes)) elif (OUTPUT == OUTPUT_PYTHON): print( res.to_str_python(curr_arch_octets(), bad_bytes, True, False)) # Reset offset set_gadgets_offset(0) set_binary_offset(0)