Beispiel #1
0
def select_shellcode(arch):
    """
    Returns shellcode pair (shellcode, description)
    """
    if (not shellcodes[arch]):
        error("No shellcodes available for architecture " + arch)
        return (None, None)

    list_shellcodes(arch)
    print("")

    choice = None
    ok = False
    sys.stdout.write('\t' + string_ropg('> ') + 'Select a shellcode:\n')
    while (not ok):
        choice_input = prompt(u"        > ")
        try:
            choice = int(choice_input)
            if (choice >= 1 and choice <= len(shellcodes[arch])):
                ok = True
            else:
                print(string_special("\tError. Invalid choice"))
        except:
            ok = False

    return shellcodes[arch][choice - 1]
Beispiel #2
0
def getGadgets(filename):
    """
    Returns a list of gadgets extracted from a file 
    Precondition: the file exists 
    
    Returns
    -------
    list of pairs (addr, asm) if succesful
    None if failure 
    """    
   
    ropgadget = "ROPgadget"
    notify("Executing ROPgadget as: " + ropgadget )
    try:
        p = subprocess.Popen([ropgadget,"--binary",filename,"--dump", "--all"],stdout=subprocess.PIPE)
    except Exception as e:
        error("Could not execute '" +ropgadget+ " --binary " + filename + " --dump --all'")
        print("\tError message is: " + str(e))
        print("\n\t(Maybe check/update your config with the 'config' command,\n\t or make sure you have the last ROPgadget version installed)")
        return None

    # Get the gadget list 
    # Pairs (address, raw_asm)
    first = True
    count = 0
    res = []
    for l in p.stdout.readlines():
        if("0x" in l):
            arr = l.split(' ')
            addr = arr[0]
            raw = b16decode(arr[-1].upper().strip())
            res.append((int(addr,16), raw))
            count += 1 
    notify("Finished : %d gadgets generated" % (count))
    return res
Beispiel #3
0
def write_shellcodes(filename, data):
    try:
        f = open(filename, 'w')
    except:
        error("Couldn't save shellcodes: file {} can't be opened".format(
            filename))
        return
    for (shellcode, info) in data:
        f.write(shellcode.encode('hex') + '\n' + info + '\n')
    f.close()
Beispiel #4
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())
Beispiel #5
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]
        assertion = Assertion().add(\
            RegsValidPtrRead([(Arch.spNum(),-5000, 10000)])).add(\
            RegsValidPtrWrite([(Arch.spNum(), -5000, 0)]))
        # Search
        res = search(qtype,
                     arg1,
                     arg2,
                     constraint,
                     assertion,
                     n=nbResults,
                     clmax=clmax)
        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())
Beispiel #6
0
def listSyscalls(args):
    if( not args ):
        systems = availableSystems
    else:
        systems = []
        for arg in args:
            if( arg in availableSystems ):
                systems.append(arg)
            else:
                error("Unknown system: '{}'".format(arg))
                return 
    
    for system in list(set(systems)):
        if( system == sysLinux32 ):
            Linux32.print_available()
        elif( system == sysLinux64 ):
            Linux64.print_available()
Beispiel #7
0
def _build_syscall(funcPointer,
                   args,
                   constraint,
                   assertion,
                   optimizeLen=False):
    if (len(args) == 0):
        return funcPointer(constraint, assertion, optimizeLen=optimizeLen)
    elif (len(args) == 1):
        return funcPointer(args[0],
                           constraint,
                           assertion,
                           optimizeLen=optimizeLen)
    elif (len(args) == 2):
        return funcPointer(args[0],
                           args[1],
                           constraint,
                           assertion,
                           optimizeLen=optimizeLen)
    elif (len(args) == 3):
        return funcPointer(args[0],
                           args[1],
                           args[2],
                           constraint,
                           assertion,
                           optimizeLen=optimizeLen)
    elif (len(args) == 4):
        return funcPointer(args[0],
                           args[1],
                           args[2],
                           args[3],
                           constraint,
                           assertion,
                           optimizeLen=optimizeLen)
    elif (len(args) == 5):
        return funcPointer(args[0],
                           args[1],
                           args[2],
                           args[3],
                           args[4],
                           constraint,
                           assertion,
                           optimizeLen=optimizeLen)
    else:
        error("{}-arguments calls not supported".format(len(args)))
        return []
Beispiel #8
0
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_PWN):
                pwn(args[1:])
            elif (command == CMD_SHELLCODE):
                shellcode(args[1:])
            elif (command == CMD_SYSCALL):
                syscall(args[1:])
            elif (command == CMD_CALL):
                call(args[1:])
            elif (command == CMD_EXIT):
                return False
            elif (command == CMD_HELP):
                print(helpStr)
            elif (command == CMD_MAIN):
                finish = True
            else:
                error("Unknown command '{}'".format(command))
            if (command != None):
                print('')
        except KeyboardInterrupt:
            pass
    return True
Beispiel #9
0
def main():
    print(string_ropg(string_bold(ASCII_art)))
    initLogs()
    finish = False
    promptSession = PromptSession(ANSI(u"(" + string_ropg(u'main') + u")> "))
    while (not finish):
        try:
            user_input = promptSession.prompt()
            args = user_input.split()
            argslen = len(args)
            if (argslen > 0):
                command = args[0]
            else:
                command = None
                continue

            if (command == CMD_LOAD):
                load(args[1:])
            elif (command == CMD_EXIT):
                finish = True
            elif (command == CMD_HELP):
                print(helpStr)
            elif (command == CMD_SEARCH):
                if (not Database.gadgets):
                    error(
                        "You have to load gadgets before entering semantic-mode"
                    )
                elif (not semantic_mode()):
                    finish = True
            elif (command == CMD_EXPLOIT):
                if (not exploit_mode()):
                    finish = True
            else:
                error("Unknown command '{}'".format(command))
            if (command != None):
                print('')

        except KeyboardInterrupt:
            pass
    closeLogs()
    save_shellcodes()
    exit(0)
Beispiel #10
0
 def strConsole(self, bits, badBytes=[]):
     res = ''
     for element in self.chain:
         if (not isinstance(element, Gadget)):
             element_str = string_special('0x' + format(
                 self.paddings[element][0], '0' + str(bits / 4) + 'x'))
             element_str += ' (' + self.paddings[element][1] + ')'
         else:
             valid_addr_str = validAddrStr(element, badBytes, bits)
             if (not valid_addr_str):
                 error(
                     "Error! ROP-Chain gadget with no valid address. THIS SHOULD NOT HAPPEND (please report the bug for fixes)"
                 )
                 return ''
             element_str = string_special(valid_addr_str) +\
                     " (" + string_bold(element.asmStr) + ")"
         if (res != ''):
             res += "\n\t" + element_str
         else:
             res += "\t" + element_str
     return res
Beispiel #11
0
def list_shellcodes(arch):
    global shellcodes

    if (arch not in Arch.available):
        error("Error. Architecture {} is not supported".format(arch))
        return
    if (not shellcodes[arch]):
        error("No shellcodes available for architecture " + arch)
        return

    print(
        banner([
            string_bold("Available shellcodes for arch " +
                        string_special(arch))
        ]))
    i = 0
    for shellcode in shellcodes[arch]:
        i = i + 1
        number = "({})".format(string_bold(str(i)))
        print("\n\t{} {}\n\t{} - {} bytes".format(number, shellcode[1], \
            string_special(short_shellcode(shellcode[0])), str(len(shellcode[0]))))
Beispiel #12
0
def call(funcName, parsedArgs, constraint, assertion):
    # Get target system
    if (Arch.currentBinType == Arch.BinaryType.X86_ELF):
        syscall = Linux32.available.get(funcName)
        system = sysLinux32
    elif (Arch.currentBinType == Arch.BinaryType.X64_ELF):
        syscall = Linux64.available.get(funcName)
        system = sysLinux64
    else:
        error("Binary type '{}' not supported yet".format(Arch.currentBinType))
        return

    if (not syscall):
        error("Syscall '{}' not supported for system '{}'".format(\
        funcName, system))
        return

    if (len(parsedArgs) != len(syscall.args)):
        error("Error. Wrong number of arguments")
        return

    # Build syscall
    res = _build_syscall(syscall.buildFunc, parsedArgs, constraint, assertion)
    # Print result
    if (not res):
        print(string_bold("\n\tNo matching ROPChain found"))
    else:
        print(string_bold("\n\tFound matching ROPChain\n"))
        badBytes = constraint.getBadBytes()
        if (OUTPUT == OUTPUT_CONSOLE):
            print(res.strConsole(Arch.bits(), badBytes))
        elif (OUTPUT == OUTPUT_PYTHON):
            print(res.strPython(Arch.bits(), badBytes))
Beispiel #13
0
def shellcode(args):
    # Parsing arguments
    if (not args):
        print_help()
        return
    if (args[0] in [OPTION_LIST, OPTION_LIST_SHORT]):
        func = list_shellcodes
    elif (args[0] in [OPTION_ADD, OPTION_ADD_SHORT]):
        func = add
    elif (args[0] in [OPTION_REMOVE, OPTION_REMOVE_SHORT]):
        func = remove
    elif (args[0] in [OPTION_HELP, OPTION_HELP_SHORT]):
        print_help()
        return
    else:
        error("Error. Unknown option '{}'".format(args[0]))
        return

    if (len(args) == 1):
        error("Architecture missing")
        print(string_bold("\tSupported architectures")+": "+\
            ','.join([string_special(arch) for arch in Arch.available]))
    elif (not args[1] in Arch.available):
        error("Architecture {} not supported".format(string_special(args[1])))
        print(string_bold("\tSupported architectures")+": "+\
            ','.join([string_special(arch) for arch in Arch.available]))
    else:
        func(args[1])
    return
Beispiel #14
0
def semantic_mode():
    """
    Returns
    -------
    True if ROPGenerator must continue
    False if ROPGenerator must be closed 
    """

    finish = False
    while (not finish):
        try:
            user_input = promptSession.prompt()
            args = user_input.split()
            argslen = len(args)
            if (argslen > 0):
                command = args[0]
            else:
                command = None
                continue

            if (command == CMD_FIND):
                find(args[1:])
            elif (command == CMD_EXIT):
                return False
            elif (command == CMD_HELP):
                print(helpStr)
            elif (command == CMD_MAIN):
                finish = True
            elif (command == CMD_REGS):
                list_regs()
            else:
                error("Unknown command '{}'".format(command))
            if (command != None):
                print('')
        except KeyboardInterrupt:
            pass
    return True
Beispiel #15
0
def remove(arch):
    if (not shellcodes[arch]):
        error("No shellcodes to remove for architecture " + arch)
        return

    list_shellcodes(arch)
    print("")

    choice = ''
    ok = False
    sys.stdout.write('\t' + string_ropg('> ') +
                     'Select a shellcode to remove:\n')
    while (not ok):
        choice_input = prompt(u"        > ")
        try:
            choice = int(choice_input)
            ok = remove_shellcode(arch, choice)
            if (not ok):
                print(string_special("\tError. Invalid choice"))
        except:
            ok = False

    print("")
    notify('Shellcode removed')
Beispiel #16
0
def build_mprotect64(addr, size, prot=7, constraint=None, assertion=None, clmax=SYSCALL_LMAX, optimizeLen=False):
    """
    Call mprotect from X86-64 arch
    Args must be on registers (rdi, rsi, rdx):
    Sizes are (unsigned long, size_t, unsigned long)
    rax must be 10 
    """
    # Check args
    if not isinstance(addr, int):
        error("Argument error. Expected integer, got " + str(type(addr)))
        return None
    elif not isinstance(size, int):
        error("Argument error. Expected integer, got " + str(type(size)))
        return None
    elif not isinstance(prot, int):
        error("Argument error. Expected integer, got " + str(type(prot)))
        return None
    
    if( constraint is None ):
        constraint = Constraint()
    if( assertion is None ):
        assertion = Assertion()
    
    # Check if we have the function !
    verbose("Trying to call mprotect() function directly")
    func_call = build_call('mprotect', [addr, size, prot], 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 mprotect(), try direct syscall")
        else:
            verbose("Couldn't call mprotect() and return to ROPChain")
            return None
    
    # Otherwise do the syscall by 'hand' 
    # Set the registers
    args = [[Arch.n2r('rdi'),addr],[Arch.n2r('rsi'), size],[Arch.n2r('rdx'),prot], [Arch.n2r('rax'),10]]
    chain = popMultiple(args, constraint, assertion, clmax-1, optimizeLen)
    if( not chain ):
        verbose("Failed to set registers for the mprotect syscall")
        return None
    # Syscall 
    syscalls = search(QueryType.SYSCALL, None, None, constraint, assertion)
    if( not syscalls ):
        verbose("Failed to find a syscall gadget")
        return None
    else:
        chain.addChain(syscalls[0])
    verbose("Success")
    return chain
Beispiel #17
0
def build_mprotect64(addr,
                     size,
                     prot=7,
                     constraint=None,
                     assertion=None,
                     clmax=None,
                     optimizeLen=False):
    """
    Call mprotect from X86-64 arch
    Args must be on registers (rdi, rsi, rdx):
    Sizes are (unsigned long, size_t, unsigned long)
    rax must be 10 
    """
    # Check args
    if not isinstance(addr, int):
        error("Argument error. Expected integer, got " + str(type(addr)))
        return None
    elif not isinstance(size, int):
        error("Argument error. Expected integer, got " + str(type(size)))
        return None
    elif not isinstance(prot, int):
        error("Argument error. Expected integer, got " + str(type(prot)))
        return None

    if (constraint is None):
        constraint = Constraint()
    if (assertion is None):
        assertion = Assertion()

    # Set the registers
    args = [[Arch.n2r('rdi'), addr], [Arch.n2r('rsi'), size],
            [Arch.n2r('rdx'), prot], [Arch.n2r('rax'), 10]]
    chain = popMultiple(args, constraint, assertion, clmax - 1, optimizeLen)
    if (not chain):
        verbose("Failed to set registers for the mprotect syscall")
        return None
    # Syscall
    syscalls = search(QueryType.SYSCALL, None, None, constraint, assertion)
    if (not syscalls):
        verbose("Failed to find a syscall gadget")
        return None
    else:
        chain.addChain(syscalls[0])
    verbose("Success")
    return chain
Beispiel #18
0
def build_mprotect32(addr, size, prot=7, constraint=None, assertion = None, clmax=None, optimizeLen=False):
    """
    Call mprotect from X86 arch
    Args must be on the stack:
    int mprotect(void *addr, size_t len, int prot)
    args must be in registers (ebx, ecx, edx)
    eax must be 0x7d = 125
    """
    # Check args
    if not isinstance(addr, int):
        error("Argument error. Expected integer, got " + str(type(addr)))
        return None
    elif not isinstance(size, int):
        error("Argument error. Expected integer, got " + str(type(size)))
        return None
    elif not isinstance(prot, int):
        error("Argument error. Expected integer, got " + str(type(prot)))
        return None
        
    if( constraint is None ):
        constraint = Constraint()
    if( assertion is None ):
        assertion = Assertion()
    
    # Set the registers
    args = [[Arch.n2r('eax'),0x7d],[Arch.n2r('ebx'), addr],[Arch.n2r('ecx'),size], [Arch.n2r('edx'),prot]]
    chain = popMultiple(args, constraint, assertion, clmax-1, optimizeLen)
    if( not chain ):
        verbose("Failed to set registers for the mprotect syscall")
        return None
    # Int 0x80
    int80_gadgets = search(QueryType.INT80, None, None, constraint, assertion)
    if( not int80_gadgets ):
        verbose("Failed to find an 'int 80' gadget")
        return None
    else:
        chain.addChain(int80_gadgets[0])
    verbose("Success")
    return chain
Beispiel #19
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()
Beispiel #20
0
                            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 
                
    # Test parsing result 
    if( subcommand is None ):
        error("Missing subcommand")
        return




Beispiel #21
0
def dshell(args, constraint, assertion, lmax):

    address = None
    limit = None
    seenAddress = False
    seenRange = False

    # Parse options
    i = 0
    while i < len(args):
        if (args[i][0] == '-'):
            if (args[i] in [OPTION_ADDRESS_SHORT, OPTION_ADDRESS]):
                if (seenAddress):
                    error("Error. '" + args[i] +
                          "' option should be used only once")
                    return None
                elif (seenRange):
                    error(
                        "Error. You can't specify a delivery address and range at the same time"
                    )
                    return None

                if (i + 1 >= len(args)):
                    error("Error. Missing address after option '" + args[i] +
                          "'")
                    return
                seenAddress = True
                try:
                    address = int(args[i + 1])
                except:
                    try:
                        address = int(args[i + 1], 16)
                    except:
                        error("Error. '" + args[i + 1] +
                              "' bytes is not valid")
                        return None
                i = i + 2
                seenAddress = True
            elif (args[i] in [OPTION_HELP, OPTION_HELP_SHORT]):
                print_help()
                return "help"
            elif (args[i] in [OPTION_RANGE, OPTION_RANGE_SHORT]):
                if (seenRange):
                    error("Error. '" + args[i] +
                          "' option should be used only once")
                    return None
                elif (seenAddress):
                    error(
                        "Error. You can't specify a delivery address and range at the same time"
                    )
                    return None

                if (i + 1 >= len(args)):
                    error("Error. Missing address range after option '" +
                          args[i] + "'")
                    return
                seenRange = True
                values = args[i + 1].split(',')
                if (len(values) < 2):
                    error("Error. Invalid address range")
                    return
                elif (len(values) > 2):
                    error("Error. Too many values after '{}' option".format(
                        args[i]))
                    return
                int_values = []
                # Convert addresses into int
                for value in values:
                    try:
                        address = int(value)
                    except:
                        try:
                            address = int(value, 16)
                        except:
                            error("Error. '" + value +
                                  "' isn't a valid address")
                            return None
                    if (address < 0):
                        error("Error. Addresses can't be negative")
                        return None
                    int_values.append(address)
                # Check consistency
                if (int_values[0] > int_values[1]):
                    error(
                        "Error. Invalid address range: lower address should be inferior to upper address"
                    )
                    return None
                # Ok
                (address, limit) = int_values
                i += 2
            else:
                error("Error. Unknown option '{}'".format(args[i]))
                return None
        else:
            error("Error. Invalid option '{}'".format(args[i]))
            return None

    # Select shellcode to deliver
    (shellcode, shellcode_info) = select_shellcode(Arch.currentArch.name)
    if (not shellcode):
        return None
    else:
        shellcode = str(shellcode)

    # Build the exploit
    print("")
    info("Building exploit: deliver-shellcode strategy\n\n")
    res = build_dshell(shellcode, constraint, assertion, address, limit, lmax)
    return res
Beispiel #22
0
def parseFunction(string):
    def seek(char, string):
        for i in range(0, len(string)):
            if string[i] == char:
                return (string[:i], i)
        return ([], -1)

    if (not string):
        error("Missing fuction to call")
        return (None, None)

    # COmpress the string
    string = "".join(string.split())

    # Get the function name
    (funcName, index) = seek("(", string)
    if (not funcName):
        error("Invalid function call")
        return (None, None)
    rest = string[index + 1:]
    args = []
    arg = ''
    i = 0
    end = False
    while (i < len(rest)):
        c = rest[i]
        # No args
        if (c == ")" and not args):
            end = True
            i += 1
        # String
        elif (c == '"' or c == "'"):
            (s, index) = seek(c, rest[i + 1:])
            if (s == 0):
                error("Error. Empty string argument ?")
                return (None, None)
            elif (not s):
                error("Missing closing {} for string".format(c))
                return (None, None)
            # Parse the string
            j = 0
            s = str(s)
            parsed_string = ""
            while (j < len(s)):
                if (s[j:j + 2] == "\\x"):
                    if (j + 3 < len(s)):
                        try:
                            char = int(s[j + 2:j + 4], 16)
                        except:
                            error("Invalid byte: '{}'".format(s[j:j + 4]))
                            return (None, None)
                    else:
                        error("Invalid byte: '{}'".format(s[j:j + 4]))
                        return (None, None)
                    parsed_string += chr(char)
                    j += 4
                else:
                    parsed_string += s[j]
                    j += 1
            args.append(str(parsed_string))

            i += index + 2
            if (i >= len(rest)):
                error("Error. Missing ')'")
                return (None, None)
            elif (rest[i] == ')'):
                end = True
                i += 1
            elif (rest[i] == ","):
                i += 1
            else:
                error("Error. Missing ',' or ')' after string")
                return (None, None)
        # Constant
        else:
            # Get the constant
            arg = ''
            ok = False
            for j in range(i, len(rest)):
                if (rest[j] == ")"):
                    end = True
                    ok = True
                    break
                elif (rest[j] == ','):
                    ok = True
                    break
                else:
                    arg += rest[j]
            if (not ok):
                error("Missing ')' after argument")
                return (None, None)
            if ((not arg) and args):
                error("Missing argument")
                return (None, None)
            # Convert to int
            try:
                value = int(arg)
            except:
                try:
                    value = int(arg, 16)
                except:
                    try:
                        value = int(arg, 2)
                    except:
                        error("Invalid operand: " + arg)
                        return (None, None)
            args.append(value)
            i = j + 1
        if (end):
            break

    if (not end):
        error("Error. Missing ')'")
        return (None, None)
    if (i < len(rest)):
        error("Error. Extra argument: {}".format(rest[i:]))
        return (None, None)

    # str() to set its type to str ;)
    return (str(funcName), args)
Beispiel #23
0
def load(args):
    global helpStr
    global loaded
    # Parse arguments and filename
    filename = None
    user_arch = None
    i = 0
    seenArch = False
    if (not args):
        print(helpStr)
        return

    while i < len(args):
        if (args[i] in [OPTION_ARCH, OPTION_ARCH_SHORT]):
            if (seenArch):
                error("Option {} can be used only one time"\
                .format(args[i]))
                return
            seenArch = True
            if (i + 1 == len(args)):
                error("Missing argument after {}.\n\tType 'load -h' for help"\
                .format(args[i]))
                return
            elif (args[i + 1] == Arch.ArchX86.name):
                user_arch = Arch.ArchX86
            elif (args[i + 1] == Arch.ArchX64.name):
                user_arch = Arch.ArchX64
            else:
                error("Unknown architecture: {}".format(args[i + 1]))
                return
            i += 2
        elif (args[i] in [OPTION_HELP, OPTION_HELP_SHORT]):
            print(helpStr)
            return
        else:
            filename = args[i]
            break
    if (not filename):
        error("Missing filename.\n\tType 'load help' for help")
        return

    # Test if the file exists
    if (not os.path.isfile(filename)):
        error("Error. Could not find file '{}'".format(filename))
        return

    print('')
    info(string_bold("Extracting gadgets from file") + " '" + filename + "'\n")

    # Cleaning the data structures
    initDB()
    Arch.reinit()

    # Get architecture and OS info
    arch = getPlatformInfo(filename)
    if (arch == user_arch == None):
        error("Error. Could not determine architecture")
        return
    elif (arch and user_arch and (arch != user_arch)):
        error("Error. Conflicting architectures")
        print("\tUser supplied: " + user_arch.name)
        print("\tFound: " + arch.name)
        return
    elif (arch):
        Arch.currentArch = arch
    else:
        Arch.currentArch = user_arch

    # Init the binary scanner
    initScanner(filename)

    # Extract the gadget list
    gadgetList = getGadgets(filename)
    if (not gadgetList):
        return

    # Build the gadget database
    # (we mix the list so that charging bar
    # appears to grow steadily )

    r = random()
    shuffle(gadgetList, lambda: r)

    build(gadgetList)
    # Init engine
    initEngine()
    loaded = True
Beispiel #24
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()
Beispiel #25
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
Beispiel #26
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

    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
Beispiel #27
0
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)
Beispiel #28
0
def build_mprotect32(addr,
                     size,
                     prot=7,
                     constraint=None,
                     assertion=None,
                     clmax=SYSCALL_LMAX,
                     optimizeLen=False):
    """
    Call mprotect from X86 arch
    Args must be on the stack:
    int mprotect(void *addr, size_t len, int prot)
    args must be in registers (ebx, ecx, edx)
    eax must be 0x7d = 125
    """
    # Check args
    if not isinstance(addr, int):
        error("Argument error. Expected integer, got " + str(type(addr)))
        return None
    elif not isinstance(size, int):
        error("Argument error. Expected integer, got " + str(type(size)))
        return None
    elif not isinstance(prot, int):
        error("Argument error. Expected integer, got " + str(type(prot)))
        return None

    if (constraint is None):
        constraint = Constraint()
    if (assertion is None):
        assertion = Assertion()

    # Check if we have the function !
    verbose("Trying to call mprotect() function directly")
    func_call = build_call('mprotect', [addr, size, prot],
                           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 mprotect(), try direct syscall")
        else:
            verbose("Couldn't call mprotect() and return to ROPChain")
            return None

    # Otherwise do syscall directly
    # Set the registers
    args = [[Arch.n2r('eax'), 0x7d], [Arch.n2r('ebx'), addr],
            [Arch.n2r('ecx'), size], [Arch.n2r('edx'), prot]]
    chain = popMultiple(args, constraint, assertion, clmax - 1, optimizeLen)
    if (not chain):
        verbose("Failed to set registers for the mprotect syscall")
        return None
    # Int 0x80
    int80_gadgets = search(QueryType.INT80, None, None, constraint, assertion)
    if (not int80_gadgets):
        verbose("Failed to find an 'int 80' gadget")
        return None
    else:
        chain.addChain(int80_gadgets[0])
    verbose("Success")
    return chain
Beispiel #29
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
    
    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
Beispiel #30
0
def load(args):
    global helpStr
    global loaded
    # Parse arguments and filename
    filename = None
    user_arch = None
    i = 0
    seenArch = False
    seenRopgadget = False
    ropgadget_options = ''
    if (not args):
        print(helpStr)
        return

    while i < len(args):
        if (args[i] in [OPTION_ARCH, OPTION_ARCH_SHORT]):
            if (seenArch):
                error("Option {} can be used only one time"\
                .format(args[i]))
                return
            seenArch = True
            if (i + 1 == len(args)):
                error("Missing argument after {}.\n\tType 'load -h' for help"\
                .format(args[i]))
                return
            elif (args[i + 1] == Arch.ArchX86.name):
                user_arch = Arch.ArchX86
            elif (args[i + 1] == Arch.ArchX64.name):
                user_arch = Arch.ArchX64
            else:
                error("Unknown architecture: {}".format(args[i + 1]))
                return
            i += 2
        elif (args[i]
              in [OPTION_ROPGADGET_OPTIONS, OPTION_ROPGADGET_OPTIONS_SHORT]):
            if (seenRopgadget):
                error("Option {} can be used only one time"\
                .format(args[i]))
                return
            seenRopgadget = True
            ropgadget_options = ''
            if (i + 1 == len(args)):
                error("Missing argument after {}.\n\tType 'load -h' for help"\
                .format(args[i]))
                return
            j = i + 1
            # Read the argments
            if (args[j][0] != "'"):
                error("ROPgadget options must be given between '' ")
                return
            if (args[j][-1] == "'" and len(args[j]) != 1):
                ropgadget_options += args[j][1:-1]
            else:
                ropgadget_options += args[j][1:]
                j += 1
                closed_ok = False
                while (j < len(args)):
                    if (args[j][0] != "'"):
                        if (args[j][-1] == "'"):
                            ropgadget_options += " " + args[j][0:-1]
                            closed_ok = True
                            break
                        elif ("'" in args[j]):
                            error(
                                "ROPgadget options: You must leave a space after the closing '"
                            )
                            return
                        else:
                            ropgadget_options += " " + args[j]
                    else:
                        if (len(args[j]) > 1):
                            error(
                                "ROPgadget options: You must leave a space after the closing \'"
                            )
                            return
                        else:
                            closed_ok = True
                            break
                    j += 1
                if (not closed_ok):
                    error("ROPgadget options: missing closing \'")
                    return
            i = j + 1

        elif (args[i] in [OPTION_HELP, OPTION_HELP_SHORT]):
            print(helpStr)
            return
        else:
            filename = args[i]
            break
    if (not filename):
        error("Missing filename.\n\tType 'load help' for help")
        return

    # Test if the file exists
    if (not os.path.isfile(filename)):
        error("Error. Could not find file '{}'".format(filename))
        return

    print('')
    info(string_bold("Extracting gadgets from file") + " '" + filename + "'\n")

    # Cleaning the data structures
    initDB()
    Arch.reinit()

    # Get architecture and OS info
    arch = getPlatformInfo(filename)
    if (arch == user_arch == None):
        error("Error. Could not determine architecture")
        return
    elif (arch and user_arch and (arch != user_arch)):
        error("Error. Conflicting architectures")
        print("\tUser supplied: " + user_arch.name)
        print("\tFound: " + arch.name)
        return
    elif (arch):
        Arch.setArch(arch)
    else:
        Arch.setArch(user_arch)

    # Init the binary scanner
    initScanner(filename)

    # Extract the gadget list
    gadgetList = getGadgets(filename, ropgadget_options)
    if (not gadgetList):
        return

    # Build the gadget database
    # (we mix the list so that charging bar
    # appears to grow steadily )

    r = random()
    shuffle(gadgetList, lambda: r)

    build(gadgetList)
    # Init engine
    initEngine()
    loaded = True