Exemple #1
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)
Exemple #2
0
def dshell(args, constraint, assertion, lmax):

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

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

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

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

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

    # Build the exploit
    print("")
    info("Building exploit: deliver-shellcode strategy\n\n")
    res = build_dshell(shellcode, constraint, assertion, address, limit, lmax)
    return res
Exemple #3
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
Exemple #4
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)
Exemple #5
0
    def __init__(self, gadgets=[]):
        # List of gadgets
        self.gadgets = gadgets

        # Different query types
        self.types = dict()
        self.types[QueryType.CSTtoREG] = dict()
        self.types[QueryType.REGtoREG] = dict()
        self.types[QueryType.MEMtoREG] = dict()
        self.types[QueryType.CSTtoMEM] = MEMDict()
        self.types[QueryType.REGtoMEM] = MEMDict()
        self.types[QueryType.MEMtoMEM] = MEMDict()
        self.types[QueryType.SYSCALL] = []
        self.types[QueryType.INT80] = []

        # Initialize them
        for r in range(0, Arch.ssaRegCount):
            self.types[QueryType.CSTtoREG][r] = CSTList()
            self.types[QueryType.REGtoREG][r] = REGList()
            self.types[QueryType.MEMtoREG][r] = MEMList()

        if (gadgets):
            info(string_bold("Sorting gadgets semantics\n"))

        # Fill them
        for i in range(0, len(gadgets)):
            charging_bar(len(gadgets) - 1, i, 30)
            gadget = gadgets[i]
            # Check for special gadgets (int 0x80 and syscall
            if (gadget.type == GadgetType.INT80):
                self.types[QueryType.INT80].append(i)
                continue
            elif (gadget.type == GadgetType.SYSCALL):
                self.types[QueryType.SYSCALL].append(i)
                continue
            # For XXXtoREG
            for reg, pairs in gadget.semantics.registers.iteritems():
                # Check if it is the final semantic for the register
                if (reg.ind < gadget.graph.lastMod[reg.num]):
                    # If not, skip this SSA register
                    continue
                for p in pairs:
                    # For REGtoREG
                    if (isinstance(p.expr, SSAExpr)):
                        self.types[QueryType.REGtoREG][reg.num].add(
                            p.expr.reg.num, 0, i, p.cond)
                    elif (isinstance(p.expr, OpExpr)):
                        (isInc, num, inc) = p.expr.isRegIncrement(-1)
                        if (isInc):
                            self.types[QueryType.REGtoREG][reg.num].add(
                                num, inc, i, p.cond)
                    # For CSTtoREG
                    elif (isinstance(p.expr, ConstExpr)):
                        self.types[QueryType.CSTtoREG][reg.num].add(
                            p.expr.value, i, p.cond)
                    # For MEMtoREG
                    elif (isinstance(p.expr, MEMExpr)):
                        if (isinstance(p.expr.addr, SSAExpr)):
                            self.types[QueryType.MEMtoREG][reg.num].add(
                                p.expr.addr.reg.num, 0, i, p.cond)
                        elif (isinstance(p.expr.addr, OpExpr)):
                            (isInc, num, inc) = p.expr.addr.isRegIncrement(-1)
                            if (isInc):
                                self.types[QueryType.MEMtoREG][reg.num].add(
                                    num, inc, i, p.cond)
            # For XXXtoMEM
            for addr, pairs in gadget.semantics.memory.iteritems():
                addr_reg = None
                addr_cst = None

                # Check if the address is of type REG + CST
                if (isinstance(addr, SSAExpr)):
                    addr_reg = addr.reg.num
                    addr_cst = 0
                elif (isinstance(addr, OpExpr)):
                    (isInc, addr_reg, addr_cst) = addr.isRegIncrement(-1)
                    if (not isInc):
                        continue
                else:
                    continue
                # Going through spairs
                for p in pairs:
                    # Check for integrity of the database
                    if (not isinstance(p.expr, Expr)):
                        raise Exception(
                            "Invalid dependency in fillGadgetLookUp(): " +
                            str(p.expr))
                    # For REGtoMEM
                    if (isinstance(p.expr, SSAExpr)):
                        self.types[QueryType.REGtoMEM].addExpr(addr_reg, \
                            addr_cst, p.expr.reg.num, 0, i, p.cond)
                    elif (isinstance(p.expr, OpExpr)):
                        (isInc, num, inc) = p.expr.isRegIncrement(-1)
                        if (isInc):
                            self.types[QueryType.REGtoMEM].addExpr(addr_reg,\
                             addr_cst, num, inc, i, p.cond)
                    # For CSTtoMEM
                    elif (isinstance(p.expr, ConstExpr)):
                        self.types[QueryType.CSTtoMEM].addCst(addr_reg, \
                        addr_cst, p.expr.value, i, p.cond)
                    # For MEMtoMEM
                    elif (isinstance(p.expr, MEMExpr)):
                        if (isinstance(p.expr.addr, SSAExpr)):
                            self.types[QueryType.MEMtoMEM].addExpr(addr_reg,\
                             addr_cst, p.expr.addr.reg.num, 0, i, p.cond)
                        elif (isinstance(p.expr.addr, OpExpr)):
                            (isInc, num, inc) = p.expr.addr.isRegIncrement(-1)
                            if (isInc):
                                self.types[QueryType.MEMtoMEM].addExpr(addr_reg,\
                                 addr_cst, num, inc, i, p.cond)
Exemple #6
0
def load(args):
    global helpStr
    global loaded
    # Parse arguments and filename
    filename = None
    user_arch = None
    i = 0
    seenArch = False
    seenRopgadget = False
    ropgadget_options = ''
    if (not args):
        print(helpStr)
        return

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

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

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

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

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

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

    # Init the binary scanner
    initScanner(filename)

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

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

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

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