示例#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 load(args):

    if (len(args) > 0):
        filename = args[0]
        msg = string_bold(
            "Extracting gadgets from file") + " '" + filename + "'"
        if (len(args) > 1):
            msg += " (Ignoring extra arguments '"
            msg += ', '.join(args[1:])
            msg += "')"
        info_colored(msg + '\n')
    else:
        print(
            string_bold("\n\tMissing argument.\n\tType 'load help' for help"))

    # Cleaning the data structures
    Gadget.reinit()
    Database.reinit()
    Analysis.reinit()
    SearchHelper.reinit()

    if (generate_opcodes.generate(filename)):
        BinaryScanner.set_binary(filename)
        Database.generated_gadgets_to_DB()
        Database.simplifyGadgets()
        Database.gadgetLookUp.fill()
示例#3
0
def build_REG_write_to_memory():
    global record_REG_write_to_memory
    global built_REG_write_to_memory

    if (built_REG_write_to_memory):
        return

    # Initialization for printing charging bar
    chargingBarSize = Analysis.ssaRegCount
    chargingBarStr = " " * chargingBarSize
    info_colored(
        string_bold("Performing additionnal analysis") +
        ": writing registers on stack\n")
    sys.stdout.write("\tProgression [")
    sys.stdout.write(chargingBarStr)
    sys.stdout.write("]\r\tProgression [")
    sys.stdout.flush()

    # Initializing the dictionnaries
    for reg in range(0, Analysis.ssaRegCount):
        record_REG_write_to_memory[reg] = dict()
        for reg2 in range(0, Analysis.ssaRegCount):
            record_REG_write_to_memory[reg][reg2] = dict()

    # Filling the dictionnaries :

    db = Database.gadgetLookUp[GadgetType.REGtoMEM]
    for reg in range(0, Analysis.ssaRegCount):
        # Printing the charging bar
        sys.stdout.write("|")
        sys.stdout.flush()

        for i in range(0, len(db.addr_list)):
            addr = db.addr_list[i]
            # We want to store only addresses of type REG +-/* CST
            (isInc, inc) = addr.isRegIncrement(addr)
            if (isInc):
                add_REG_write_to_memory(reg, reg_list[0], offset, [
                    g for g in db.written_values[i]
                    if Database.gadgetDB[g].hasNormalRet()
                    and Database.gadgetDB[g].isValidSpInc()
                ])

    sys.stdout.write("\r" + " " * 70 + "\r")
    built_REG_write_to_memory = True
示例#4
0
def simplifyGadgets():
    """
    Apply some simplifications on the gadget dependencies
    """
    chargingBarSize = 30
    chargingBarStr = " " * chargingBarSize
    i = 0
    info_colored(string_bold("Processing gadgets\n"))
    for gadget in gadgetDB:
        charging_bar(len(gadgetDB) - 1, i, 30)
        gadget.getDependencies().simplifyConditions()
        i = i + 1

    # Second pass analysis once all gadgets are collected
    for gadget in gadgetDB:
        gadget.calculateSpInc()
        gadget.calculateRet()
        gadget.calculatePreConstraint()
示例#5
0
def load_config():
    global ARCH
    global PATH_ROPGADGET
    global LIMIT
    # Check if the ROPGenerator director exists
    if (not os.path.isdir(ROPGENERATOR_DIRECTORY)):
        try:
            os.system('mkdir ' + ROPGENERATOR_DIRECTORY)
        except:
            pass
    try:
        f = open(ROPGENERATOR_CONFIG_FILE, "r")
        ARCH = f.readline()[:-1]
        PATH_ROPGADGET = f.readline()[:-1]
        LIMIT = int(f.readline()[:-1], 10)
        f.close()
        #info_colored("Loaded configuration\n")
    except:
        info_colored(
            "Couldn't load custom configuration, using the default one\n")
        default_config()
    Analysis.setArch(ARCH)
示例#6
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]]
示例#7
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]]))
示例#8
0
def main(time_mesure=False):

    if (time_mesure):
        pr = cProfile.Profile()
        pr.enable()

    style = Style.from_dict({
        'prompt': '#00FF00',
    })

    message = [
        (u'class:prompt', u'>>> '),
    ]

    #try:
    # Launching ROPGenerator
    write_colored(ASCII_art)
    Config.load_config()
    Logs.init()
    session = PromptSession()
    quit = False
    while (not quit):
        try:
            user_input = session.prompt(message, style=style)
            args = user_input.split()
            argslen = len(args)
            if (argslen > 0):
                command = args[0]
            else:
                command = None

            if (command == None):
                pass
            elif (command == CMD_HELP):
                print(
                    string_bold(
                        "\n\t-----------------------------------------------------------\n\tROPGenerator commands"
                    ))
                print(
                    string_special(
                        "\t(For more information about a command type '<command> help')"
                    ))
                print(
                    string_bold(
                        "\t-----------------------------------------------------------\n"
                    ))
                print('\t' + string_bold(CMD_LOAD) +
                      ': \t\tload usable gadgets from a binary file')
                print('\t' + string_bold(CMD_FIND) +
                      ': \t\tsemantic search for gadgets/ropchains')
                print('\t' + string_bold(CMD_PAYLOAD) +
                      ': \tmanage payloads to use in your exploit')
                print('\t' + string_bold(CMD_EXPLOIT) + ':\tbuild an exploit')
                print(
                    '\t' + string_bold(CMD_REGISTERS) +
                    ': \tprint available registers for the current architecture'
                )
                print('\t' + string_bold(CMD_CONFIG) +
                      ': \tconfigure ROPGenerator')
                print('\t' + string_bold(CMD_HELP) +
                      ': \t\tprint available commands')
                print('\t' + string_bold(CMD_EXIT) + ': \t\texit ROPGenerator')
            elif (command == CMD_FIND):
                if (argslen > 1):
                    if (args[1] == CMD_HELP):
                        SearchEngine.print_help()
                    else:
                        SearchEngine.set_user_input(user_input[len(CMD_FIND):])
                        SearchEngine.find_gadgets(args[1:])
                else:
                    SearchEngine.print_help()
                    #print("Missing arguments. Type 'find help' for help")
            elif (command == CMD_EXPLOIT):
                if (argslen > 1):
                    if (args[1] == CMD_HELP):
                        Exploit.print_help()
                    else:
                        Exploit.exploit(args[1:])
                else:
                    Exploit.print_help()

            elif (command == CMD_PAYLOAD):
                if (argslen > 1):
                    if (args[1] == CMD_HELP):
                        Payload.print_help()
                    else:
                        Payload.payload(args[1:])
                else:
                    Payload.print_help()
                    #print("Missing arguments. Type 'payload help' for help")
            elif (command == CMD_LOAD):
                if (argslen > 1):
                    if (args[1] == CMD_HELP):
                        Load.print_help()
                    else:
                        Load.load(args[1:])
                else:
                    Load.print_help()
                    #print("Missing arguments. Type 'load help' for help")

            elif (command == CMD_REGISTERS):
                pretty_print_registers()
            elif (command == CMD_CONFIG):
                if (argslen > 1):
                    if (args[1] == CMD_HELP):
                        Config.print_help()
                    else:
                        Config.update_config(args[1:])
                else:
                    Config.print_help()
                    #print("Missing arguments. Type 'config help' for help")
            elif (command == CMD_CONTEXT):
                if (argslen > 1):
                    if (args[1] == CMD_HELP):
                        Context.print_help()
                    else:
                        Context.context(args[1:])
                else:
                    Context.print_help()

            elif (command == CMD_EXIT):
                quit = True
                Config.save_config()
                Payload.save_payloads()
            else:
                print(string_bold("\n\tUnknown command '" + command+\
                    "'. Type 'help' for available commands"))
            # New line
            if (command != None):
                print("")
        except KeyboardInterrupt:
            pass

    info_colored(string_bold("Closing ROPGenerator...\n"))

    #except KeyboardInterrupt:
    #    pass
    #except Exception as e:
    #    print("")
    #    error_colored("ROPGenerator failed unexpectedly\n")
    #    print(e)

    if (time_mesure):
        pr.disable()
        s = pstats.Stats(pr).sort_stats('tottime')
        s.print_stats(0.02)

    exit(0)
示例#9
0
    def fill(self):
        def filter_cond(condition):
            if (condition.isTrue()):
                return None
            else:
                return condition

        # Initialize the data structures !
        self.types[GadgetType.CSTtoMEM] = cstToMemLookUp()
        self.types[GadgetType.REGEXPRtoMEM] = exprToMemLookUp()
        self.types[GadgetType.MEMEXPRtoMEM] = exprToMemLookUp()
        for reg_num in Analysis.revertRegNamesTable.keys():
            self.types[GadgetType.CSTtoREG][reg_num] = cstLookUp()
            self.types[GadgetType.REGEXPRtoREG][reg_num] = exprLookUp(reg_num)
            self.types[GadgetType.MEMEXPRtoREG][reg_num] = exprLookUp(reg_num)

        # Initialize the printed charging bar
        chargingBarSize = 30
        chargingBarStr = " " * chargingBarSize
        info_colored(string_bold("Sorting gadgets semantics\n"))
        # Update the gadgetLookUp table
        for i in range(0, len(gadgetDB)):
            charging_bar(len(gadgetDB) - 1, i, 30)
            gadget = gadgetDB[i]
            # Check for special gadgets (int 0x80 and syscall
            if (gadget.sort == GadgetSort.INT80):
                self.list_int80.append(i)
                continue
            elif (gadget.sort == GadgetSort.SYSCALL):
                self.list_syscall.append(i)
                continue
            # For XXXtoREG
            for reg, deps in gadget.getDependencies().regDep.iteritems():
                for dep in deps:
                    # For REGEXPRtoREG
                    if (isinstance(dep[0], Expr.SSAExpr)):
                        self.types[GadgetType.REGEXPRtoREG][
                            reg.num].add_gadget(dep[0].reg.num,
                                                0,
                                                i,
                                                condition=filter_cond(dep[1]))
                    elif (isinstance(dep[0], Expr.Op)):
                        (isInc, num, inc) = dep[0].isRegIncrement(-1)
                        if (isInc):
                            self.types[GadgetType.REGEXPRtoREG][
                                reg.num].add_gadget(num,
                                                    inc,
                                                    i,
                                                    condition=filter_cond(
                                                        dep[1]))
                    # For CSTtoREG
                    elif (isinstance(dep[0], Expr.ConstExpr)):
                        self.types[GadgetType.CSTtoREG][reg.num].add_gadget(
                            dep[0].value, i, condition=filter_cond(dep[1]))
                    # For MEMEXPRtoREG
                    elif (isinstance(dep[0], Expr.MEMExpr)):
                        if (isinstance(dep[0].addr, Expr.SSAExpr)):
                            self.types[GadgetType.MEMEXPRtoREG][
                                reg.num].add_gadget(dep[0].addr.reg.num,
                                                    0,
                                                    i,
                                                    condition=filter_cond(
                                                        dep[1]))
                        elif (isinstance(dep[0].addr, Expr.Op)):
                            (isInc, num, inc) = dep[0].addr.isRegIncrement(-1)
                            if (isInc):
                                self.types[GadgetType.MEMEXPRtoREG][
                                    reg.num].add_gadget(num,
                                                        inc,
                                                        i,
                                                        condition=filter_cond(
                                                            dep[1]))
                    # If we found a true dependency, no need to check others
                    #if( dep[1].isTrue()):
                    #    break

            # For XXXtoMEM
            for addr, deps in gadget.getDependencies().memDep.iteritems():
                addr_reg = None
                addr_cst = None
                # Check if the address is of type REG + CST
                if (isinstance(addr, Expr.SSAExpr)):
                    addr_reg = addr.reg.num
                    addr_cst = 0
                elif (isinstance(addr, Expr.Op)):
                    (isInc, addr_reg, addr_cst) = addr.isRegIncrement(-1)
                    if (not isInc):
                        continue
                else:
                    continue

                # Going through dependencies
                for dep in deps:
                    # Check for integrity of the database
                    if (not isinstance(dep[0], Expr.Expr)):
                        raise Exception(
                            "Invalid dependency in fillGadgetLookUp(): " +
                            str(dep[0]))

                    # For REGEXPRtoMEM
                    if (isinstance(dep[0], Expr.SSAExpr)):

                        self.types[GadgetType.REGEXPRtoMEM].add_gadget(addr_reg, \
                            addr_cst, dep[0].reg.num, 0, i,condition=filter_cond(dep[1]))
                    elif (isinstance(dep[0], Expr.Op)):
                        (isInc, num, inc) = dep[0].isRegIncrement(-1)
                        if (isInc):
                            self.types[GadgetType.REGEXPRtoMEM].add_gadget(addr_reg,\
                             addr_cst, num, inc, i,condition=filter_cond(dep[1]))

                    # For CSTtoMEM
                    elif (isinstance(dep[0], Expr.ConstExpr)):
                        self.types[GadgetType.CSTtoMEM].add_gadget(addr_reg, \
                        addr_cst, dep[0].value, i,condition=filter_cond(dep[1]))
                    # For MEMEXPRtoMEM
                    elif (isinstance(dep[0], Expr.MEMExpr)):
                        if (isinstance(dep[0].addr, Expr.SSAExpr)):
                            self.types[GadgetType.MEMEXPRtoMEM].add_gadget(addr_reg,\
                             addr_cst, dep[0].addr.reg.num, 0, i,condition=filter_cond(dep[1]))
                        elif (isinstance(dep[0].addr, Expr.Op)):
                            (isInc, num, inc) = dep[0].addr.isRegIncrement(-1)
                            if (isInc):
                                self.types[GadgetType.MEMEXPRtoMEM].add_gadget(addr_reg,\
                                 addr_cst, num, inc, i,condition=filter_cond(dep[1]))
                    # If we found a true dependency, no need to check others
                    #if( dep[1].isTrue()):
                    #    break

        # Clean the charging bar
        sys.stdout.write("\r" + " " * 70 + "\r")
示例#10
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