示例#1
0
def update_config(args):
    """
    Update config with user supplied args
    """
    if (len(args) == 1 and args[0] == 'show'):
        print_config()
        return

    info_colored(string_bold("Updating configuration\n"))
    for arg in args:
        arg_list = arg.split('=')
        left = arg_list[0]
        if (len(arg_list) < 2):
            notify("Error. Missing right part in argument " + arg)
            return
        else:
            right = arg_list[1]
            if (left == "arch"):
                set_arch(right)
            elif (left == "ropgadget"):
                set_ropgadget(right)
            elif (left == "limit"):
                set_limit(right)
            else:
                notify("Ignored unknown parameter '" + left + "'")
示例#2
0
def remove_payload():
    print(string_bold('\n\t--------------------\n\tRemoving a payload\n\t--------------------\n'))
    
    arch_input = ''
    while( not arch_input in Analysis.supportedArchs ):
        sys.stdout.write('\t'+ROPGENERATOR_COLOR_ANSI+'> '+END_COLOR_ANSI+'Enter the payload architecture ({}):\n\t'.format\
            (','.join([string_special(s) for s in Analysis.supportedArchs])))
        arch_input = prompt(u"")
    
    show_shellcodes(arch_input)
    print("")
    
    choice = ''
    ok = False
    while( not ok ):
        sys.stdout.write('\t'+ROPGENERATOR_COLOR_ANSI+'> '+END_COLOR_ANSI+'Select a payload to remove:\n\t')
        choice_input = prompt(u"")
        try:
            choice = int(choice_input)
            ok = remove_shellcode(arch_input, choice)
        except:
            ok = False

    print("")
    notify('Payload removed')
示例#3
0
def select_payload():
    
    if( Database.gadgetDB ):
        arch_input = Analysis.ArchInfo.currentArch
        print("")
        notify('Detected architecture from loaded binary: ' + string_special(arch_input))
    else:
        print(string_bold('\n\tOops! You should load a binary before selecting a payload'))
        return 
    
    show_shellcodes(arch_input)
    print("")
    
    choice = ''
    ok = False
    while( not ok ):
        sys.stdout.write('\t'+ROPGENERATOR_COLOR_ANSI+'> '+END_COLOR_ANSI+'Select a payload number:\n\t')
        choice_input = prompt(u"")
        try:
            choice = int(choice_input)
            ok = select_shellcode(arch_input, choice)
        except:
            ok = False
        if( not ok ):
            print(string_special("\tError. Invalid payload number\n"))
    show_selected()
示例#4
0
def set_ropgadget(path):
    global DEFAULT_PATH_ROPGADGET
    global PATH_ROPGADGET
    if ((os.path.isfile(path) and path[:-3] == ".py")
            or path == DEFAULT_PATH_ROPGADGET or path == "ROPgadget"):
        PATH_ROPGADGET = path
        notify("New ropgadget command : " + path)
    else:
        notify("Error. '" + path + "' could not be found")
示例#5
0
def generate(filename):
    """
    Returns true if success, false otherwise 
    """
    global opcodes_file

    if (not os.path.isfile(filename)):
        print(
            string_bold(
                "\n\tError. Could not find file '{}'".format(filename)))
        return False

    binType = check_binaryType(filename)
    if (not binType):
        error_colored("Could not determine architecture for binary: " +
                      filename + "\n")
        return False
    else:
        Config.set_arch(binType, quiet=True)

    ropgadget = Config.PATH_ROPGADGET
    notify("Executing ROPgadget as: " + ropgadget)
    try:
        p = subprocess.Popen(
            [ropgadget, "--binary", filename, "--dump", "--all"],
            stdout=subprocess.PIPE)
    except Exception as e:
        error_colored("Could not execute ' " + ropgadget + " --binary " +
                      filename + " --dump '")
        print("\tError message is: " + str(e))
        print(
            "\n\t(Maybe check/update your config with the 'config' command, or make sure you have the last ROPgadget version installed)"
        )
        return False

    f = open(opcodes_file, "w")

    # Write gadgets
    first = True
    count = 0
    for l in p.stdout.readlines():
        if ("0x" in l):
            arr = l.split(' ')
            addr = arr[0]
            gadget = arr[-1]
            it = iter(gadget)
            gadget = ''.join(a + b for a, b in zip(it, it))
            f.write(addr + '#')
            f.write(gadget + '\n')
            count += 1
    f.close()

    notify("Finished : %d gadgets generated" % (count))

    return (count > 0)
示例#6
0
def set_arch(arch, quiet=False):
    global ARCH
    if (arch in Analysis.supportedArchs):
        ARCH = arch
        Analysis.setArch(arch)
        if (not quiet):
            notify("Now working under architecture: " + arch)
    else:
        if (not quiet):
            notify("Architecture '" + arch +
                   "' not supported. Available architectures: " +
                   ','.join(Analysis.supportedArchs))
示例#7
0
def set_limit(limit):
    global LIMIT
    if (isinstance(limit, int)):
        LIMIT = limit
    else:
        try:
            limit = int(limit, 10)
            LIMIT = limit
            notify("Now looking for up to {} gadgets by request".format(
                str(LIMIT)))
        except:
            notify("Error. 'limit' parameter should be a base 10 integer")
示例#8
0
def check_binaryType(filename):
    """
    Checks the binary type of the file
    Precondition: the file exists ! 
    """
    ELF32_strings = ["ELF 32-bit"]
    ELF64_strings = ["ELF 64-bit", "x86-64"]

    output = from_file(os.path.realpath(filename))
    if ([sub for sub in ELF32_strings if sub in output]):
        notify("ELF 32-bit detected")
        return "X86"
    elif ([sub for sub in ELF64_strings if sub in output]):
        notify("ELF 64-bit detected")
        return "X86-64"
    else:
        notify("Unknown binary type")
        return None
示例#9
0
def build_mprotect_datareuse(payload):
    """
    Build a ROPchain that does :
        - mprotect RWX to a static memory area
        - copy payload to this memory area
        - jmp to payload 
    """
    info_colored(string_bold('Building mprotect + datareuse exploit\n'))

    # Get the initial constraint
    constraint = Constraint().add(ConstraintType.BAD_BYTES,
                                  Context.bad_bytes())

    # Then get address of the bss
    notify('Getting .bss address')
    bss_addr = BinaryScanner.bss_address()
    if (not bss_addr):
        info("Could not find static .bss section to copy payload to")
        return []
    else:
        info("Found .bss at address: " + hex(bss_addr))

    # Then get the mprotect chain
    notify('Building mprotect ropchain to make .bss RWX')
    if (Analysis.ArchInfo.currentArch == "X86-64"):
        mprotect_chain = mprotect_X64(bss_addr, len(payload) + 1, 7)
    elif (Analysis.ArchInfo.currentArch == "X86"):
        mprotect_chain = mprotect_X86(bss_addr, len(payload) + 1, 7)
    else:
        info("mprotect chain for arch '{}' not supported yet".format(
            Analysis.ArchInfo.currentArch))
        return []
    if (not mprotect_chain):
        info("Could not build mprotect chain")
        return []
    mprotect_info = "Create RWX memory : calling mprotect({},{},{})".format(
        hex(bss_addr),
        len(payload) + 1, 7)

    # Then write shellcode in memory
    notify('Building data-reuse chain to copy payload into .bss')
    datareuse = search.str_to_mem(bss_addr,
                                  '.bss',
                                  payload,
                                  constraint.add(ConstraintType.CHAINABLE_RET,
                                                 []),
                                  hex_info=True)
    if (not datareuse):
        info("Could not build datareuse chain")
        return []
    datareuse_info = "Copy payload into custom RWX memory"

    notify('Building a chain to jump to .bss and execute payload')
    # Then jump to the payload
    ip_num = Analysis.regNamesTable[Analysis.ArchInfo.ip]
    jmp_payload = search.jmp_addr(bss_addr, constraint)
    if (not jmp_payload):
        info("Could not build jmp_payload chain")
        return []
    jmp_payload_info = "Jump to payload"
    # Concatenate to full exploit
    return [[mprotect_chain, mprotect_info], [datareuse, datareuse_info],
            [jmp_payload, jmp_payload_info]]
示例#10
0
def check_context():
    info_colored(string_bold('Checking exploit context\n'))
    notify('NX stack: ' + b2s(values[NX]))
    notify('ASLR: ' + b2s(values[NX]))
    notify('Forbidden bytes in exploit: ' +\
            ','.join([string_special(b) for b in values[BAD_BYTES]]))
示例#11
0
def generated_gadgets_to_DB():
    """
    Generates the list of the available gadgets for ROP 
    Usage : must be called after the gadgets opcodes have been stored into the opcodes_gadget array in Generated_opcodes.py file.
    Result : 
        No value returned. But the gadgets are stored in the gadgets[] array in Database module.
    """
    global sigint
    global current_gadget
    global old_stdout
    global old_stderr

    def sigint_handler(signal, frame):
        global sigint
        sigint = True

    # Read all gadgets that have been generated !
    f = open(opcodes_file, "r")
    asmGadgets = []
    for line in f:
        (addr, instr) = line[:-1].split('#')
        addr = int(addr, 16)
        instr = instr.decode("hex")
        asmGadgets.append((addr, instr))
    f.close()
    # Sort the gadgets according to their instructions
    asmGadgets.sort(key=lambda x: x[1])
    # Analyze them
    junk_file = open("/dev/null", "w")
    i = 0
    success = 0
    warnings = 0
    info_colored(
        string_bold("Working under architecture: ") +
        Analysis.ArchInfo.currentArch + '\n')
    info_colored(string_bold("Creating gadget database\n"))
    warnings_file = ROPGENERATOR_DIRECTORY + "warnings-logs"
    f = open(warnings_file, "w")
    original_sigint_handler = signal.getsignal(signal.SIGINT)
    signal.signal(signal.SIGINT, sigint_handler)
    startTime = datetime.now()
    for g in asmGadgets:
        if (sigint):
            break
        asm = g[1]
        addr = g[0]
        try:
            charging_bar(len(asmGadgets) - 1, i, 30)
            #print("Gadget : " + '\\x'.join(["%02x" % ord(c) for c in asm]) + "\n")
            sys.stdout = sys.stderr = junk_file
            signal.alarm(1)
            gadget = Gadget(i, addr, asm)
            signal.alarm(0)
            sys.stdout = old_stdout
            sys.stderr = old_stderr
            success += 1
            gadgetDB.append(gadget)

        except Exception as e:
            signal.alarm(0)
            sys.stdout = old_stdout
            sys.stderr = old_stderr
            if (not isinstance(e, GadgetException)):
                warnings = warnings + 1
                f.write("Unexpected error in : " +
                        '\\x'.join(["%02x" % ord(c) for c in asm]) +
                        "\nException type: " + str(type(e)) +
                        "\nException message: " + str(e) + '\n\n')

        i = i + 1

    # Trick to find syscalls
    for addr in find_syscalls():
        gadget = Gadget(i, addr, '\x0f\x05')
        gadgetDB.append(gadget)
        i = i + 1

    # Restoring the state
    f.close()
    junk_file.close()
    signal.signal(signal.SIGINT, original_sigint_handler)
    # This variable should be written before calculating spInc or simplifying conditions !!!
    Expr.nb_regs = Analysis.ssaRegCount - 1

    # Getting time
    cTime = datetime.now() - startTime
    # Printing summary information
    if (sigint):
        print("\n")
        error_colored(
            "SIGINT ended the analysis prematurely, gadget database might be incomplete\n"
        )
        sigint = False
    notify("Gadgets analyzed : " + str(i))
    notify("Successfully translated : " + str(success))
    notify("Computation time : " + str(cTime))
    if (warnings > 0):
        pass
示例#12
0
def check_binaryType(filename):
    """
    Checks the binary type of the file
    Precondition: the file exists ! 
    """
    INTEL_strings = ["x86", "x86-64", "X86", "X86-64", "Intel", "80386"]
    ELF32_strings = ["ELF 32-bit"]
    ELF64_strings = ["ELF 64-bit"]
    PE32_strings = ["PE32 "]
    PE64_strings = ["PE32+"]

    output = from_file(os.path.realpath(filename))
    if ([sub for sub in INTEL_strings if sub in output]):
        if ([sub for sub in ELF32_strings if sub in output]):
            notify("ELF 32-bits detected")
            Analysis.setFiletype("ELF")
            return "X86"
        elif ([sub for sub in ELF64_strings if sub in output]):
            notify("ELF 64-bits detected")
            Analysis.setFiletype("ELF")
            return "X86-64"
        elif ([sub for sub in PE32_strings if sub in output]):
            notify("PE 32-bits detected")
            Analysis.setFiletype("PE")
            return "X86"
        elif ([sub for sub in PE64_strings if sub in output]):
            notify("PE 64-bits detected")
            Analysis.setFiletype("PE")
            return "X86-64"
        else:
            notify("Unknown binary type")
            return None
    else:
        notify("Unknown architecture")
        return None