Ejemplo n.º 1
0
def add(arch):

    print(banner([string_bold('Adding a new shellcode')]))

    shellcode = ''
    ok = False
    while (not ok):
        sys.stdout.write('\t' + string_ropg('> ') +
                         'Enter your shellcode as a string in hex format:\n')
        shellcode_input = prompt(u"        > ")
        try:
            shellcode = shellcode_input.replace('\\x', '').decode('hex')
            ok = True
        except:
            ok = False
        if (not ok):
            print(
                string_special(
                    "\tError. Your input is in wrong format or invalid"))

    sys.stdout.write('\t' + string_ropg('> ') +
                     'Enter short shellcode name/description:\n')
    info = ""
    while (not info):
        info = prompt(u"        > ")
    info = filter(lambda x: x in set(string.printable), info)
    add_shellcode(arch, shellcode, info)
Ejemplo n.º 2
0
def build_call(funcName, funcArgs, constraint, assertion):
    # Find the address of the fonction
    (funcName2, funcAddr) = getFunctionAddress(funcName)
    if (funcName2 is None):
        return "Couldn't find function '{}' in the binary".format(funcName)

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

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

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

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

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

    return call_chain.addChain(args_chain)
Ejemplo n.º 3
0
def build_call_linux86(funcName, funcArgs, constraint, assertion, clmax=None, optimizeLen=False):
    # Find the address of the fonction 
    (funcName2, funcAddr) = getFunctionAddress(funcName)
    if( funcName2 is None ):
        return "Couldn't find function '{}' in the binary".format(funcName)
    
    # Check if bad bytes in function address 
    if( not constraint.badBytes.verifyAddress(funcAddr) ):
        return "'{}' address ({}) contains bad bytes".format(funcName2, string_special('0x'+format(funcAddr, '0'+str(Arch.octets()*2)+'x')))
    
    # Check if lmax too small
    if( (1 + len(funcArgs) + (lambda x: 1 if len(x)>0 else 0)(funcArgs)) > clmax ):
        return "Not enough bytes to call function '{}'".format(funcName)
    
    # Find a gadget for the fake return address
    if( funcArgs ):
        offset = (len(funcArgs)-1)*Arch.octets() # Because we do +octets() at the beginning of the loop
        skip_args_chains = []
        i = 4 # Try 4 more maximum 
        while( i > 0 and (not skip_args_chains)):
            offset += Arch.octets() 
            skip_args_chains = search(QueryType.MEMtoREG, Arch.ipNum(), \
                        (Arch.spNum(),offset), constraint, assertion, n=1, optimizeLen=optimizeLen)
            i -= 1
            
        if( not skip_args_chains ):
            return "Couldn't build ROP-Chain"
        skip_args_chain = skip_args_chains[0]
    else:
        # No arguments 
        skip_args_chain = None
    
    # Build the ropchain with the arguments 
    args_chain = ROPChain()
    arg_n = len(funcArgs)
    for arg in reversed(funcArgs):
        if( isinstance(arg, int) ):
            args_chain.addPadding(arg, comment="Arg{}: {}".format(arg_n, string_ropg(hex(arg))))
            arg_n -= 1
        else:
            return "Type of argument '{}' not supported yet :'(".format(arg)
    
    # Build call chain (function address + fake return address)
    call_chain = ROPChain()
    call_chain.addPadding(funcAddr, comment=string_ropg(funcName2))
    if( funcArgs ):
        skip_args_addr = int( validAddrStr(skip_args_chain.chain[0], constraint.getBadBytes(), Arch.bits())  ,16)
        call_chain.addPadding(skip_args_addr, comment="Address of: "+string_bold(str(skip_args_chain.chain[0])))
    
    return call_chain.addChain(args_chain)
Ejemplo n.º 4
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]
Ejemplo n.º 5
0
def build_call_linux64(funcName, funcArgs, constraint, assertion, clmax=None, optimizeLen=False):
    # Arguments registers 
    # (Args should go in these registers for x64)
    argsRegsNames = ['rdi','rsi','rdx','rcx', 'r8', 'r9']
    argsRegs = [Arch.n2r(name) for name in argsRegsNames]
    # Find the address of the fonction 
    (funcName2, funcAddr) = getFunctionAddress(funcName)
    if( funcName2 is None ):
        return "Couldn't find function '{}' in the binary".format(funcName)
    
    # Check if bad bytes in function address 
    if( not constraint.badBytes.verifyAddress(funcAddr) ):
        return "'{}' address ({}) contains bad bytes".format(funcName2, string_special('0x'+format(funcAddr, '0'+str(Arch.octets()*2)+'x')))
    
    # Check how many arguments 
    if( len(funcArgs) > 6 ):
        return "Doesn't support function call with more than 6 arguments with Linux X64 calling convention :("
        
    # Find a gadget for the fake return address
    if( funcArgs ):
        # Build the ropchain with the arguments
        args_chain = popMultiple(map(lambda x,y:(x,)+y,  argsRegs[:len(funcArgs)], funcArgs), constraint, assertion, clmax=clmax, optimizeLen=optimizeLen)
        if( not args_chain):
            return "Couldn't load arguments in registers"
    else:
        # No arguments 
        args_chain = ROPChain()
    
    # Build call chain (function address + fake return address)
    return args_chain.addPadding(funcAddr, comment=string_ropg(funcName2))
Ejemplo n.º 6
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)
Ejemplo n.º 7
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')
Ejemplo n.º 8
0
def STRtoMEM_memcpy(string,
                    addr,
                    constraint,
                    assertion,
                    lmax=STR_TO_MEM_LMAX,
                    addr_str=None,
                    hex_info=False):
    """
    MEMCPY STRATEGY
    Copy the string using memcpy function 
    """
    if (not addr_str):
        addr_str = "0x" + format(addr, '0' + str(Arch.octets() * 2) + 'x')

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

    # We decompose the string in substrings to be copied
    substrings_addr = findBytes(string, badBytes=constraint.getBadBytes())
    if (not substrings_addr):
        return None
    elif (len(substrings_addr) * 5 > lmax):
        verbose(
            "Memcpy: ROP-Chain too long (length: {}, available bytes: {}) ".
            format(
                len(substrings_addr) * 5 * Arch.octets(),
                lmax * Arch.octets()))
        return None

    # Get a pop-pop-pop-ret gadget
    pppr_chains = _basic(QueryType.MEMtoREG,
                         Arch.ipNum(), [Arch.spNum(), 3 * Arch.octets()],
                         constraint.add(
                             StackPointerIncrement(4 * Arch.octets())),
                         assertion,
                         clmax=1,
                         noPadding=True)
    if (not pppr_chains):
        verbose("Memcpy: Could not find suitable pop-pop-pop-ret gadget")
        return None
    pppr_gadget = pppr_chains[0].chain[0]  # Get the first gadget

    # Build chain
    res = ROPChain()
    offset = 0
    custom_stack = addr
    for (substring_addr, substring_str) in substrings_addr:
        if (hex_info):
            substring_info = "'" + '\\x' + '\\x'.join(
                ["%02x" % ord(c) for c in substring_str]) + "'"
        else:
            substring_info = "'" + substring_str + "'"

        res.addPadding(func_addr, comment=string_ropg(func_name))
        res.addGadget(pppr_gadget)
        res.addPadding(len(substring_str),
                       comment="Arg3: " + string_ropg(str(len(substring_str))))
        res.addPadding(substring_addr,
                       comment="Arg2: " + string_ropg(substring_info))
        res.addPadding(custom_stack,
                       comment="Arg1: " +
                       string_ropg("{} + {}".format(addr_str, offset)))

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

    return res
Ejemplo n.º 9
0
def STRtoMEM_strcpy(string,
                    addr,
                    constraint,
                    assertion,
                    limit=None,
                    lmax=STR_TO_MEM_LMAX,
                    addr_str=None,
                    hex_info=False):
    """
    STRCPY STRATEGY
    Copy the string using strcpy function 
    """
    if (not addr_str):
        addr_str = hex(addr)

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

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

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

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

    return (saved_custom_stack, res)
Ejemplo n.º 10
0
def STRtoMEM_memcpy(string,
                    addr,
                    constraint,
                    assertion,
                    limit=None,
                    lmax=STR_TO_MEM_LMAX,
                    addr_str=None,
                    hex_info=False):
    """
    MEMCPY STRATEGY
    Copy the string using memcpy function 
    """
    if (not addr_str):
        addr_str = hex(addr)

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

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

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

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

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

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

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

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

    return (saved_custom_stack, res)