예제 #1
0
def show_shellcode():
    print(string_bold('\n\t-------------------------------'))
    print(string_bold("\tSelected shellcode - arch " + string_special(arch)))
    print(string_bold('\t-------------------------------'))
    (shellcode, info) = selected(arch)
    print("\n\t{}\n\n{} - {} bytes".format( info, \
            string_special(pack_shellcode(shellcode)), str(len(shellcode))))
예제 #2
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
예제 #3
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))
예제 #4
0
def print_chains(chainList, msg, badBytes=[]):
    global OUTPUT
    sep = "------------------"
    if( chainList):
        print(string_bold('\n\t'+msg))
        if( OUTPUT == OUTPUT_CONSOLE ):
            print("\n"+chainList[0].strConsole(Arch.currentArch.bits, badBytes))
        elif( OUTPUT == OUTPUT_PYTHON ):
            print('\n' + chainList[0].strPython(Arch.currentArch.bits, badBytes))
        for chain in chainList[1:]:
            if( OUTPUT == OUTPUT_CONSOLE ):
                print('\t'+sep + "\n"+ chain.strConsole(Arch.currentArch.bits, badBytes))
            elif( OUTPUT == OUTPUT_PYTHON ):
                print('\t'+sep + '\n' + chain.strPython(Arch.currentArch.bits, badBytes))
    else:
        print(string_bold("\n\tNo matching ROPChain found"))
예제 #5
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)
예제 #6
0
 def __str__(self):
     res = self.ret + " " + string_bold(self.name)
     res += "("
     res += ', '.join(
         [a[0] + " " + string_special(a[1]) for a in self.args])
     res += ")"
     return res
예제 #7
0
    def strPython(self, bits, badBytes=[], init=True, noTab=False):
        if (noTab):
            tab = ''
        else:
            tab = '\t'

        # Getting endianness to pack values
        if (bits == 32):
            endianness_str = "'<I'"
        elif (bits == 64):
            endianness_str = "'<Q'"
        else:
            raise Exception("{}-bits architecture not supported".format(bits))
        pack_str = "p += pack(" + endianness_str + ","
        res = ''
        if (init):
            res += tab + "from struct import pack\n"
            res += tab + "p = ''"
        for element in self.chain:
            if (not isinstance(element, Gadget)):
                padding_str = pack_str
                padding_str += string_special(
                    '0x' + format(self.paddings[element][0], '0' +
                                  str(bits / 4) + 'x')) + ")"
                padding_str += " # " + self.paddings[element][1]
                res += "\n" + tab + padding_str
            else:
                res += "\n"+tab+pack_str+string_special(validAddrStr(element, badBytes, bits)) +\
                        ") # " + string_bold(element.asmStr)
        return res
예제 #8
0
def _CSTtoREG_pop(reg,
                  cst,
                  constraint,
                  assertion,
                  n=1,
                  clmax=LMAX,
                  comment=None):
    """
    Returns a payload that puts cst into register reg by poping it from the stack
    """
    # Test clmax
    if (clmax <= 0):
        return []
    # Test n
    if (n < 1):
        return []
    # Check if the cst is incompatible with the constraint
    if (not constraint.badBytes.verifyAddress(cst)):
        return []

    if (not comment):
        comment = "Constant: " + string_bold("0x{:x}".format(cst))

    # Direct pop from the stack
    res = []
    if (reg == Arch.ipNum()):
        constraint2 = constraint.remove([CstrTypeID.CHAINABLE])
    else:
        constraint2 = constraint.add(Chainable(ret=True))
    possible = DBPossiblePopOffsets(reg, constraint2, assertion)
    for offset in sorted(filter(lambda x: x >= 0, possible.keys())):
        # If offsets are too big to fit in the lmax just break
        if (offset > clmax * Arch.octets()):
            break
        # Get possible gadgets
        possible_gadgets = [g for g in possible[offset]\
            if g.spInc >= Arch.octets() \
            and g.spInc - Arch.octets() > offset \
            and (g.spInc/Arch.octets()-1) <= clmax] # Test if padding is too much for clmax
        # Pad the gadgets
        padding = constraint.getValidPadding(Arch.octets())
        for gadget in possible_gadgets:
            chain = ROPChain([gadget])
            for i in range(0, gadget.spInc - Arch.octets(), Arch.octets()):
                if (i == offset):
                    chain.addPadding(cst, comment)
                else:
                    chain.addPadding(padding)
            if (len(chain) <= clmax):
                res.append(chain)
            if (len(res) >= n):
                return res
    return res
예제 #9
0
def list_regs():
    """
    List available registers 
    """
    print(banner([string_bold("Available registers")]))
    for reg in sorted(Arch.regNameToNum.keys()):
        if (reg == Arch.currentArch.ip):
            print("\t" + string_special(reg) + " - instruction pointer")
        elif (reg == Arch.currentArch.sp):
            print("\t" + string_special(reg) + " - stack pointer")
        else:
            print("\t" + string_special(reg))
예제 #10
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]))))
예제 #11
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)
예제 #12
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)
예제 #13
0
def print_functions(func_list):
    """
    func_list - list of pairs (str, int) = (funcName, funcAddress)
    """
    space = 28
    print(banner([string_bold("Available functions")]))
    print("\tFunction" + " " * (space - 8) + "Address")
    print("\t------------------------------------")
    for (funcName, funcAddr) in sorted(func_list, key=lambda x: x[0]):
        space2 = space - len(funcName)
        if (space2 < 0):
            space2 = 2
        print("\t" + string_special(funcName) + " " * space2 + hex(funcAddr))
    print("")
예제 #14
0
def initEngine():
    global INIT_LMAX, INIT_MAXDEPTH
    global global_impossible_REGtoREG
    global baseAssertion

    # Init global variables
    baseAssertion = Assertion().add(\
            RegsValidPtrRead([(Arch.spNum(),-5000, 10000)]), copy=False).add(\
            RegsValidPtrWrite([(Arch.spNum(), -5000, 0)]), copy=False)

    info(string_bold("Initializing Semantic Engine\n"))

    # Init helper for REGtoREG
    global_impossible_REGtoREG = SearchEnvironment(INIT_LMAX, Constraint(),
                                                   baseAssertion,
                                                   INIT_MAXDEPTH)
    init_impossible_REGtoREG(global_impossible_REGtoREG)
예제 #15
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)
예제 #16
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
예제 #17
0
def STRtoMEM_write(string,
                   addr,
                   constraint,
                   assertion,
                   limit=None,
                   lmax=STR_TO_MEM_LMAX,
                   addr_str=None,
                   hex_info=False):
    """
    WRITE STRATEGY
    Copy the string using mem(XXX) <- YYY gadgets 
    """
    if (not addr_str):
        addr_str = hex(addr)

    # We decompose the string in substrings to be copied
    substrings_addr = find_best_valid_writes(addr, string, constraint, limit)
    if (substrings_addr is None):
        return (None, None)

    # Build chain
    res = ROPChain()
    offset = 0
    for (substring_addr, substring_val) in substrings_addr:
        substring_info = "(" + string_bold("Substring in int") + hex(
            substring_val) + ")"
        write_chain = store_constant_address(QueryType.CSTtoMEM,
                                             substring_addr,
                                             substring_val,
                                             constraint,
                                             assertion,
                                             clmax=lmax - len(res),
                                             optimizeLen=True)
        if (write_chain):
            res.addChain(write_chain)
        else:
            verbose("Coudln't find suitable memory write ropchain")
            return (None, None)
    return (substrings_addr[0][0], res)
예제 #18
0
╚═╝  ╚═╝ ╚═════╝ ╚═╝     ════════════════════ v1.2          
  

"""

# Definitions of commands
CMD_HELP = "help"
CMD_LOAD = "load"
CMD_CONFIG = "config"
CMD_EXIT = "exit"

CMD_SEARCH = "semantic"
CMD_EXPLOIT = "exploit"

helpStr = banner([
    string_bold('Main Commands'),
    string_special('(For more info about a command type <cmd -h>)')
])
helpStr += '\n\t' + string_bold(
    CMD_LOAD) + ': \t\tload gadgets from a binary file'
helpStr += '\n\n\t' + string_semantic(string_bold(CMD_SEARCH)) + \
    ': \tEnter semantic-mode (Search for'+'\n\t\t\tgadgets and ROPChains)'
helpStr += '\n\n\t' + string_exploit(string_bold(CMD_EXPLOIT)) + \
    ': \tEnter exploit-mode (Automated exploit'+'\n\t\t\tgeneration features)'
helpStr += '\n\n\t' + string_bold(CMD_HELP) + ': \t\tprint available commands'
helpStr += '\n\t' + string_bold(CMD_EXIT) + ': \t\texit ROPGenerator'


def main():
    print(string_ropg(string_bold(ASCII_art)))
    initLogs()
예제 #19
0
from ropgenerator.exploit.Pwn import pwn
from ropgenerator.IO import string_exploit, string_bold, string_special, banner, error

import sys

# Definitions of commands
CMD_HELP = "help"
CMD_SHELLCODE = "shellcode"
CMD_SYSCALL = "syscall"
CMD_PWN = "pwn"
CMD_CALL = "call"
CMD_MAIN = "main"
CMD_EXIT = "exit"

helpStr = banner([
    string_bold('Exploit-Mode Commands'),
    string_special('(For more info about a command type <cmd -h>)')
])
helpStr += '\n\t' + string_bold(CMD_PWN) + ': \t\tbuild an exploit'
helpStr += '\n\t' + string_bold(CMD_SYSCALL) + ': \tcall a system function'
helpStr += '\n\t' + string_bold(CMD_CALL) + ':\t\tcall a regular function'
helpStr += '\n\t' + string_bold(CMD_SHELLCODE) + ': \tmanage shellcodes'

helpStr += '\n\n\t' + string_bold(CMD_HELP) + ': \t\tshow this help'
helpStr += '\n\t' + string_bold(CMD_MAIN) + ': \t\treturn to the main menu'
helpStr += '\n\t' + string_bold(CMD_EXIT) + ': \t\texit ROPGenerator'

promptSession = PromptSession(ANSI(u"(" + string_exploit(u'exploit') + u")> "))


def exploit_mode():
예제 #20
0
################################
#  DELIVER-SHELLCODE COMMAND   #
################################

# Options
OPTION_ADDRESS = '--address'
OPTION_ADDRESS_SHORT = "-a"

OPTION_RANGE = "--address-range"
OPTION_RANGE_SHORT = "-r"

OPTION_HELP = '--help'
OPTION_HELP_SHORT = '-h'


CMD_DSHELL_HELP =  banner([string_bold("'deliver-shellcode' command"),\
                    string_special("(Deliver a shellcode & Execute it)")])
CMD_DSHELL_HELP += "\n\n\t"+string_bold("Description:")+\
"\n\t\tThis method tries to create an executable memory area"+\
"\n\t\t, then copy a given shellcode into this area, and then"+\
"\n\t\t jump to execute this shellcode"

CMD_DSHELL_HELP += "\n\n\t" + string_bold("Options") + ":"
CMD_DSHELL_HELP += "\n\n\t\t" + string_special(
    OPTION_ADDRESS_SHORT) + "," + string_special(
        OPTION_ADDRESS) + " <int>\t Address where to deliver shellcode"
CMD_DSHELL_HELP += "\n\n\t\t" + string_special(
    OPTION_RANGE_SHORT
) + "," + string_special(
    OPTION_RANGE
) + " \t Memory space that can be used to\n\t\t\t<addr>,<addr>\t deliver the shellcode"
예제 #21
0
def _adjust_ret(qtype, arg1, arg2, env, n):
    """
    Search with basic but adjust the bad returns they have 
    """
    global LMAX
    ID = StrategyType.ADJUST_RET

    ## Test for special cases
    # Test lmax
    if (env.getLmax() <= 0):
        return FailRecord(lmax=True)
    # Limit number of calls to ...
    elif (env.nbCalls(ID) >= 2):
        return FailRecord()
    # Test for ip
    # Reason: can not adjust ip if ip is the
    # target of the query :/
    elif (arg1 == Arch.ipNum()):
        return FailRecord()

    # Set env
    env.addCall(ID)
    saved_adjust_ret = env.getImpossible_adjust_ret().copy()

    ########################################
    res = []
    res_fail = FailRecord()
    padding = env.getConstraint().getValidPadding(Arch.octets())
    # Get possible gadgets
    constraint = env.getConstraint()
    env.setConstraint(constraint.add(Chainable(jmp=True, call=True)))
    possible = _basic(qtype, arg1, arg2, env, 10 * n)
    env.setConstraint(constraint)

    if (not possible):
        res_fail.merge(possible)
        possible = []

    # Try to adjust them
    for chain in possible:
        g = chain.chain[0]
        ret_reg = g.retValue.reg.num
        # Check if we already know that ret_reg can't be adjusted
        if (env.checkImpossible_adjust_ret(ret_reg)):
            continue
        #Check if ret_reg not modified within the gadget
        elif (ret_reg in g.modifiedRegs()):
            continue
        # Check if stack is preserved
        elif (g.spInc is None):
            continue

        # Find adjustment
        if (g.spInc < 0):
            offset = -1 * g.spInc
            padding_length = 0
        else:
            padding_length = g.spInc / Arch.octets()
            if (g.retType == RetType.JMP):
                offset = 0
            else:
                offset = Arch.octets()
        if (isinstance(arg1, int)):
            arg1_reg = arg1
        else:
            arg1_reg = arg1[0]

        # Get adjustment gadgets
        env.setConstraint(constraint.add(RegsNotModified([arg1_reg])))
        saved_lmax = env.getLmax()
        env.setLmax(LMAX)
        adjust_gadgets = _search(QueryType.MEMtoREG, Arch.ipNum(), \
                (Arch.spNum(),offset), env, n=1)
        env.setConstraint(constraint)
        env.setLmax(saved_lmax)

        if (not adjust_gadgets):
            res_fail.merge(adjust_gadgets)
            continue
        else:
            adjust_addr = int(validAddrStr(adjust_gadgets[0].chain[0],\
                    constraint.getBadBytes(), Arch.bits()),  16)

        # Find gadgets to put the gadget address in the jmp/call register
        if (isinstance(arg2, int)):
            arg2_reg = arg2
        else:
            arg2_reg = arg2[0]

        env.setConstraint(constraint.add(RegsNotModified([arg2_reg])))
        env.subLmax(1 + padding_length)
        env.pushComment(
            StrategyType.CSTtoREG_POP,
            "Address of " + string_bold(str(adjust_gadgets[0].chain[0])))
        adjust = _search(QueryType.CSTtoREG, ret_reg, adjust_addr, env, n=1)
        env.popComment(StrategyType.CSTtoREG_POP)
        env.addLmax(1 + padding_length)
        env.setConstraint(constraint)
        if (adjust):
            res.append(adjust[0].addGadget(g).addPadding(padding,
                                                         n=padding_length))
            if (len(res) >= n):
                break
        else:
            # Update the search record to say that reg_ret cannot be adjusted
            env.addImpossible_adjust_ret(ret_reg)
            res_fail.merge(adjust)
    ########################################
    # Restore env
    env.impossible_adjust_ret = saved_adjust_ret
    env.removeCall(ID)
    return res if res else res_fail
예제 #22
0
def _CSTtoREG_pop(reg, cst, env, n=1):
    """
    Returns a payload that puts cst into register reg by poping it from the stack
    """
    ID = StrategyType.CSTtoREG_POP

    ## Test for special cases
    # Test lmax
    if (env.getLmax() <= 0):
        return FailRecord(lmax=True)
    # Limit number of calls to ...
    elif (env.nbCalls(ID) >= 99):
        return FailRecord()
    # Check if the cst is in badBytes
    elif (not env.getConstraint().badBytes.verifyAddress(cst)):
        return FailRecord()

    # Set env
    env.addCall(ID)
    # Get comment
    if (env.hasComment(ID)):
        envHadComment = True
        comment = env.popComment(ID)
    else:
        envHadComment = False
        comment = "Constant: " + string_bold("0x{:x}".format(cst))

    ########################
    # Direct pop from the stack
    res = []
    res_fail = FailRecord()
    # Adapt constraint if ip <- cst
    if (reg != Arch.ipNum()):
        constraint2 = env.getConstraint().add(Chainable(ret=True))
    else:
        constraint2 = env.getConstraint()

    possible = DBPossiblePopOffsets(reg, constraint2, env.getAssertion())
    for offset in sorted(filter(lambda x: x >= 0, possible.keys())):
        # If offsets are too big to fit in the lmax just break
        if (offset > env.getLmax() * Arch.octets()):
            break
        # Get possible gadgets
        possible_gadgets = [g for g in possible[offset]\
            if g.spInc >= Arch.octets() \
            and g.spInc - Arch.octets() > offset \
            and (g.spInc/Arch.octets()-1) <= env.getLmax()] # Test if padding is too much for clmax
        # Pad the gadgets
        padding = env.getConstraint().getValidPadding(Arch.octets())
        for gadget in possible_gadgets:
            chain = ROPChain([gadget])
            for i in range(0, gadget.spInc - Arch.octets(), Arch.octets()):
                if (i == offset):
                    chain.addPadding(cst, comment)
                else:
                    chain.addPadding(padding)
            if (len(chain) <= env.getLmax()):
                res.append(chain)
            if (len(res) >= n):
                break
        if (len(res) >= n):
            break
    #########################

    # Restore env
    env.removeCall(ID)
    if (envHadComment):
        env.pushComment(ID, comment)

    return res if res else res_fail
예제 #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
예제 #24
0
from ropgenerator.exploit.Scanner import initScanner
import ropgenerator.Architecture as Arch
from ropgenerator.IO import string_bold, info, string_special, banner, notify, error
from magic import from_file
from base64 import b16decode
from random import shuffle, random, randrange, Random

# Command options
OPTION_ARCH = '--arch'
OPTION_ARCH_SHORT = '-a'
OPTION_HELP = '--help'
OPTION_HELP_SHORT = '-h'

# Help for the load command
helpStr = banner([
    string_bold("'load' command"),
    string_special("(Load gadgets from a binary file)")
])
helpStr += "\n\n\t" + string_bold("Usage") + ":\tload [OPTIONS] <filename>"
helpStr += "\n\n\t" + string_bold("Options") + ":"
helpStr += "\n\t\t"+string_special(OPTION_ARCH_SHORT)+","+string_special(OPTION_ARCH)+\
" <arch>"+"\tmanualy specify architecture.\n\t\t\t\t\tAvailable: 'X86', 'X64'"
helpStr += "\n\n\t" + string_bold(
    "Examples"
) + ":\n\t\tload /bin/ls\t\t(load gadgets from /bin/ls program)\n\t\tload ../test/vuln_prog\t(load gadgets from own binary)"


def print_help():
    print(helpStr)

예제 #25
0
def print_available():
    global available
    print(string_bold("\n\n\tSupported Linux 32-bits syscalls"))
    for name,syscall in available.iteritems():
        print("\n\t"+string_payload(name)+":  "+str(syscall))
예제 #26
0
OPTION_LMAX = '--max-length'
OPTION_LMAX_SHORT = '-m'

OPTION_VERBOSE = "--verbose"
OPTION_VERBOSE_SHORT = "-v"

OPTION_OUTFILE = '--output-file'
OPTION_OUTFILE_SHORT = '-o'

OPTION_PADDING_BYTE = '--padding-byte'
OPTION_PADDING_BYTE_SHORT = '-pb'

OPTION_PADDING_LEN = '--padding-len'
OPTION_PADDING_LEN_SHORT = '-pl'

CMD_PWN_HELP =  banner([string_bold("'pwn' command"),\
                    string_special("(Generate full exploits)")])
CMD_PWN_HELP += "\n\n\t"+string_bold("Usage:")+\
"\n\t\tpwn [OPTIONS] <subcommand> [SUBCOMMAND_OPTIONS]"

CMD_PWN_HELP += "\n\n\t"+string_bold("Subcommands")+":"
CMD_PWN_HELP += "\n\t(For more info use 'pwn <subcommand> -h')"
CMD_PWN_HELP += "\n\n\t\t"+string_special(CMD_DELIVER_SHELLCODE)+"\t Inject a shellcode an execute it"

CMD_PWN_HELP += "\n\n\t"+string_bold("Options")+":"
CMD_PWN_HELP += "\n\n\t\t"+string_special(OPTION_BAD_BYTES_SHORT)+","+string_special(OPTION_BAD_BYTES)+" <bytes>\t Bad bytes for payload.\n\t\t\t\t\t Expected format is a list of bytes \n\t\t\t\t\t separated by comas (e.g '-b 0A,0B,2F')"
CMD_PWN_HELP += "\n\n\t\t"+string_special(OPTION_LMAX_SHORT)+","+string_special(OPTION_LMAX)+" <int>\t Max length of the ROPChain in bytes"
CMD_PWN_HELP += "\n\n\t\t"+string_special(OPTION_PADDING_BYTE_SHORT)+","+string_special(OPTION_PADDING_BYTE)+" <byte> Byte for payload padding"
CMD_PWN_HELP += "\n\n\t\t"+string_special(OPTION_PADDING_LEN_SHORT)+","+string_special(OPTION_PADDING_LEN)+" <int>\t Length of payload padding"
CMD_PWN_HELP += "\n\n\t\t"+string_special(OPTION_OUTPUT_SHORT)+","+\
    string_special(OPTION_OUTPUT)+\
예제 #27
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
예제 #28
0
def build(pair_list):
    """
    Takes a list of pairs (addr, raw_asm) corresponding to 
    gagets (their address and their intructions as a byte string)
    Fills the 'gadgets' and 'db' global structures ;) 
    """
    def sigint_handler(signal, frame):
        global sigint
        sigint = True

    def timeout_handler(signum, frame):
        global sigalarm
        sigalarm = True
        signal.alarm(0)
        raise TimeOutException('Timeout')

    global gadgets, db, sigint
    gadgets = []
    raw_to_gadget = dict()
    sigint = False
    original_sigint_handler = signal.getsignal(signal.SIGINT)
    signal.signal(signal.SIGINT, sigint_handler)
    signal.signal(signal.SIGALRM, timeout_handler)

    info(string_bold("Creating gadget database\n"))
    startTime = datetime.now()
    success = i = 0
    # Create the gadgets list
    for (addr, raw) in pair_list:
        charging_bar(len(pair_list) - 1, i, 30)
        if (sigint):
            break
        if (raw in raw_to_gadget):
            gadgets[raw_to_gadget[raw]].addrList.append(addr)
            success += 1
        else:
            try:
                signal.alarm(1)
                gadget = Gadget([addr], raw)
                signal.alarm(0)
                success += 1
                gadgets.append(gadget)
                raw_to_gadget[raw] = len(gadgets) - 1
            except (GadgetException, TimeOutException) as e:
                signal.alarm(0)
                if (isinstance(e, GadgetException)):
                    log("Gadget ({}) :  ".format('\\x'+'\\x'\
                    .join("{:02x}".format(ord(c)) for c in raw)) + str(e))
        i += 1
    # Find syscalls
    # TODO

    # Getting time
    cTime = datetime.now() - startTime
    signal.signal(signal.SIGINT, original_sigint_handler)

    if (sigint):
        print("\n")
        fatal(
            "SIGINT ended the analysis prematurely, gadget database might be incomplete\n"
        )
        sigint = False
    notify("Gadgets analyzed : " + str(len(pair_list)))
    notify("Successfully translated : " + str(success))
    notify("Computation time : " + str(cTime))

    # Create the database
    db = Database(gadgets)
예제 #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
예제 #30
0
OPTION_KEEP_REGS = '--keep-regs'
OPTION_KEEP_REGS_SHORT = '-k'

OPTION_LIST = "--list"
OPTION_LIST_SHORT = "-l"

OPTION_FUNCTION = "--call"
OPTION_FUNCTION_SHORT = "-c" 

OPTION_OFFSET="--offset"
OPTION_OFFSET_SHORT = "-off"

OPTION_HELP = "--help"
OPTION_HELP_SHORT = "-h"

CMD_SYSCALL_HELP =  banner([string_bold("'syscall' command"),\
                    string_special("(Call system functions with ROPChains)")])
CMD_SYSCALL_HELP += "\n\n\t"+string_bold("Usage:")+\
"\n\t\tsyscall [OPTIONS]"
CMD_SYSCALL_HELP += "\n\n\t"+string_bold("Options")+":"
CMD_SYSCALL_HELP += "\n\t\t"+string_special(OPTION_FUNCTION_SHORT)+","+\
    string_special(OPTION_FUNCTION)+" <function>\t Call a system function"
CMD_SYSCALL_HELP += "\n\n\t\t"+string_special(OPTION_BAD_BYTES_SHORT)+","+string_special(OPTION_BAD_BYTES)+" <bytes>\t Bad bytes for payload.\n\t\t\t\t\t Expected format is a list of bytes \n\t\t\t\t\t separated by comas (e.g '-b 0A,0B,2F')"
CMD_SYSCALL_HELP += "\n\n\t\t"+string_special(OPTION_KEEP_REGS_SHORT)+","+string_special(OPTION_KEEP_REGS)+" <regs>\t Registers that shouldn't be modified.\n\t\t\t\t\t Expected format is a list of registers \n\t\t\t\t\t separated by comas (e.g '-k edi,eax')"
CMD_SYSCALL_HELP += "\n\n\t\t"+string_special(OPTION_OFFSET_SHORT)+","+\
    string_special(OPTION_OFFSET)+" <int>\t Offset to add to gadget addresses"   
    
CMD_SYSCALL_HELP += "\n\n\t\t"+string_special(OPTION_LIST_SHORT)+","+\
    string_special(OPTION_LIST)+" [<system>]\t List supported functions"
CMD_SYSCALL_HELP += "\n\n\t\t"+string_special(OPTION_OUTPUT_SHORT)+","+\
    string_special(OPTION_OUTPUT)+\