예제 #1
0
    def classify_JOP_gadget(self, gadget):
        """
        Analyzes a gadget to determine which expressivity classes it satisfies
        :param Gadget gadget: gadget to analyze
        :return: None, but modifies Gadget expressivity collections
        """
        last_instr = gadget.instructions[len(gadget.instructions) - 1]
        op1 = last_instr.op1
        op1_family = Instruction.get_word_operand_register_family(op1)

        if self.practical_ROP[3] is False:
            if "[" in op1 and op1_family in [
                    0, 5
            ] and "+" not in op1 and "-" not in op1 and "*" not in op1:
                self.practical_ROP[3] = True

        if self.practical_ROP[5] is False:
            if op1_family in [
                    0, 5
            ] and "+" not in op1 and "-" not in op1 and "*" not in op1:
                self.practical_ROP[5] = True

        if self.practical_ROP[7] is False:
            if "[" in op1 and op1_family in [
                    0, 4, 5
            ] and "+" not in op1 and "-" not in op1 and "*" not in op1:
                self.practical_ROP[7] = True

        if self.practical_ASLR_ROP[0] is False:
            if "[" not in op1 and op1_family not in [None, 6, 7]:
                self.practical_ASLR_ROP[0] = True

        if self.practical_ASLR_ROP[1] is False:
            if "[" in op1 and op1_family not in [
                    None, 6, 7
            ] and "+" not in op1 and "-" not in op1 and "*" not in op1:
                self.practical_ASLR_ROP[1] = True
예제 #2
0
    def classify_gadget(self, gadget):
        """
        Analyzes a gadget to determine which expressivity classes it satisfies
        :param Gadget gadget: gadget to analyze
        :return: None, but modifies Gadget expressivity collections
        """
        first_instr = gadget.instructions[0]
        opcode = first_instr.opcode
        op1 = first_instr.op1
        op2 = first_instr.op2
        op1_family = Instruction.get_word_operand_register_family(op1)
        op2_family = Instruction.get_word_operand_register_family(op2)

        # For performance, iterate through the expressivity classes and perform analysis. Analysis rules should
        # set as many classes as possible.
        if self.practical_ROP[0] is False:
            if opcode == "dec" and op1_family in [0, 5] and "[" not in op1:
                self.practical_ROP[0] = True

                # Also satisfies:
                self.turing_complete_ROP[0] = True
                self.practical_ASLR_ROP[9] = True

        if self.practical_ROP[1] is False:
            if opcode == "inc" and op1_family in [0, 5] and "[" not in op1:
                self.practical_ROP[1] = True

                # Also satisfies:
                self.turing_complete_ROP[0] = True
                self.practical_ASLR_ROP[8] = True

        if self.practical_ROP[2] is False:
            if opcode == "pop" and op1_family in [0, 5] and "[" not in op1:
                self.practical_ROP[2] = True

                # Also satisfies:
                self.turing_complete_ROP[1] = True
                self.practical_ASLR_ROP[5] = True

        if self.practical_ROP[3] is False:
            if (opcode == "pop" and op1_family == 4 and "[" not in op1) or \
               (opcode in ["xchg", "move"] and op1_family == 4 and op2_family in [0, 5]
                                                               and "[" not in op1 and "[" not in op2) or \
               (opcode == "lea" and op1_family == 4 and op2_family in [0, 5]
                                                    and "+" not in op2 and "-" not in op2 and "*" not in op2) or \
               (opcode == "xchg" and op1_family in [0, 5] and op2_family == 4 and "[" not in op1 and "[" not in op2):
                self.practical_ROP[3] = True

        if self.practical_ROP[4] is False:
            if opcode == "xchg" and ((op1_family == 0 and op2_family == 5) or (op2_family == 0 and op1_family == 5)) \
               and "[" not in op1 and "[" not in op2:
                self.practical_ROP[4] = True

        if self.practical_ROP[5] is False:
            if opcode == "push" and op1_family in [0, 4, 5] and "[" not in op1:
                self.practical_ROP[5] = True

        if self.practical_ROP[6] is False:
            if opcode in ["clc", "sahf"] or \
               (opcode in ["test", "add", "adc", "sub", "sbb", "and", "or", "xor", "cmp"] and
               op1_family in [0, 4, 5] and op2_family in [0, 4, 5] and "[" not in op1 and "[" not in op2):
                self.practical_ROP[6] = True

                # Also satisfies:
                self.turing_complete_ROP[7] = True
                self.practical_ASLR_ROP[4] = True

        if self.practical_ROP[7] is False:
            if (opcode.startswith("stos") or opcode in ["mov", "add", "or"]) and "[" in op1 and "+" not in op1 and \
               "-" not in op1 and "*" not in op1 and op1_family in [0, 4, 5] and op2_family in [0, 4, 5] and \
               op1_family != op2_family:
                self.practical_ROP[7] = True

                # Also satisfies:
                self.turing_complete_ROP[6] = True
                self.practical_ASLR_ROP[2] = True

        if self.practical_ROP[8] is False:
            if (opcode.startswith("lods") or opcode in ["mov", "add", "adc", "sub", "sbb", "and", "or", "xor"]) and \
               "[" in op2 and "+" not in op2 and "-" not in op2 and "*" not in op2 and op1_family in [0, 4, 5] and \
               op2_family in [0, 4, 5] and op1_family != op2_family:
                self.practical_ROP[8] = True

                # Also satisfies:
                self.turing_complete_ROP[5] = True
                self.practical_ASLR_ROP[1] = True

        # NOTE: Single rule for two classes
        if self.practical_ROP[9] is False or self.practical_ASLR_ROP[
                7] is False:
            if opcode == "leave":
                self.practical_ROP[9] = True
                self.practical_ASLR_ROP[7] = True

        if self.practical_ROP[10] is False:
            if (opcode == "pop" and op1_family == 6 and "[" not in op1) or \
               (opcode == "xchg" and op1_family is not None and op2_family is not None and op1_family != op2_family
                                 and (op1_family == 6 or op2_family == 6) and "[" not in op1 and "[" not in op2) or \
               (opcode in ["add", "adc", "sub", "sbb"] and "[" not in op1 and op1_family == 6 and
               op2_family not in [None, 6] and "+" not in op2 and "-" not in op2 and "*" not in op2):
                self.practical_ROP[10] = True

        if self.turing_complete_ROP[0] is False:
            if opcode in ["inc", "dec"] and op1_family not in [None, 7] and "+" not in op1 and "-" not in op1 and \
               "*" not in op1:
                self.turing_complete_ROP[0] = True

        if self.turing_complete_ROP[1] is False:
            if opcode == "pop" and op1_family not in [None, 7
                                                      ] and "[" not in op1:
                self.turing_complete_ROP[1] = True

        if self.turing_complete_ROP[2] is False:
            if opcode in ["add", "adc", "sub", "sbb"] and op1_family not in [None, 7] and "+" not in op1 and \
                    "-" not in op1 and "*" not in op1 and op2_family not in [None, 7] and "+" not in op2 and \
                    "-" not in op2 and "*" not in op2 and op1_family != op2_family:
                self.turing_complete_ROP[2] = True

        if self.turing_complete_ROP[3] is False:
            if (opcode == "xor" and op1_family not in [None, 7] and "+" not in op1 and "-" not in op1 and "*" not in op1
               and op2_family not in [None, 7] and "+" not in op2 and "-" not in op2 and "*" not in op2
               and op1_family != op2_family) or \
               (opcode in ["neg", "not"] and op1_family not in [None, 7] and "+" not in op1 and "-" not in op1
               and "*" not in op1):
                self.turing_complete_ROP[3] = True

        if self.turing_complete_ROP[4] is False:
            if opcode in ["and", "or"] and op1_family not in [None, 7] and "+" not in op1 and \
                    "-" not in op1 and "*" not in op1 and op2_family not in [None, 7] and "+" not in op2 and \
                    "-" not in op2 and "*" not in op2 and op1_family != op2_family:
                self.turing_complete_ROP[4] = True

        if self.turing_complete_ROP[5] is False:
            if (opcode.startswith("lods") or opcode in ["mov", "add", "adc", "sub", "sbb", "and", "or", "xor"]) and \
               "[" in op2 and "+" not in op2 and "-" not in op2 and "*" not in op2 and \
               op1_family not in [None, 7] and op2_family not in [None, 7] and op1_family != op2_family:
                self.turing_complete_ROP[5] = True

        if self.turing_complete_ROP[6] is False:
            if (opcode.startswith("stos") or opcode in ["mov", "add", "or"]) and "[" in op1 and "+" not in op1 and \
               "-" not in op1 and "*" not in op1 and op1_family not in [None, 7] and op2_family not in [None, 7] and \
               op1_family != op2_family:
                self.turing_complete_ROP[6] = True

        if self.turing_complete_ROP[7] is False:
            if opcode in ["clc", "sahf"] or \
               (opcode in ["test", "add", "adc", "sub", "sbb", "and", "or", "xor", "cmp"] and
               op1_family not in [None, 7] and op2_family not in [None, 7] and "+" not in op1 and "-" not in op1 and
               "*" not in op1 and "+" not in op2 and "-" not in op2 and "*" not in op2 and op1_family != op2_family):
                self.turing_complete_ROP[7] = True

        if self.turing_complete_ROP[8] is False:
            if opcode in ["add", "adc", "sub", "sbb"] and "[" not in op2 and op2_family == 7 and \
               op1_family not in [None, 7] and "+" not in op1 and "-" not in op1 and "*" not in op1:
                self.turing_complete_ROP[8] = True

        if self.turing_complete_ROP[9] is False:
            if (opcode == "pop" and op1_family == 7 and "[" not in op1) or \
               (opcode == "xchg" and op1_family is not None and op2_family is not None and op1_family != op2_family
                                 and (op1_family == 7 or op2_family == 7) and "[" not in op1 and "[" not in op2) or \
               (opcode in ["add", "adc", "sub", "sbb"] and "[" not in op1 and op1_family == 7 and
               op2_family not in [None, 7] and "+" not in op2 and "-" not in op2 and "*" not in op2):
                self.turing_complete_ROP[9] = True

        if self.turing_complete_ROP[10] is False:
            if opcode in ["lahf", "pushf"] or \
               (opcode in ["adc", "sbb"] and op1_family not in [None, 7] and op2_family not in [None, 7] and
               "+" not in op1 and "-" not in op1 and "*" not in op1 and
               "+" not in op2 and "-" not in op2 and "*" not in op2 and op1_family != op2_family):
                self.turing_complete_ROP[10] = True

        # Next 6 classes have common and very specific requirements, check once
        if opcode == "xchg" and "[" not in op1 and "[" not in op2 and op1_family != op2_family:
            if self.turing_complete_ROP[11] is False:
                if op1_family in [0, 1] and op2_family in [0, 1]:
                    self.turing_complete_ROP[11] = True

            if self.turing_complete_ROP[12] is False:
                if op1_family in [0, 2] and op2_family in [0, 2]:
                    self.turing_complete_ROP[12] = True

            if self.turing_complete_ROP[13] is False:
                if op1_family in [0, 3] and op2_family in [0, 3]:
                    self.turing_complete_ROP[13] = True

            if self.turing_complete_ROP[14] is False:
                if op1_family in [0, 6] and op2_family in [0, 6]:
                    self.turing_complete_ROP[14] = True

            if self.turing_complete_ROP[15] is False:
                if op1_family in [0, 4] and op2_family in [0, 4]:
                    self.turing_complete_ROP[15] = True

            if self.turing_complete_ROP[16] is False:
                if op1_family in [0, 5] and op2_family in [0, 5]:
                    self.turing_complete_ROP[16] = True

        if self.practical_ASLR_ROP[0] is False:
            if opcode == "push" and op1_family not in [None, 6, 7
                                                       ] and "[" not in op1:
                self.practical_ASLR_ROP[0] = True

        if self.practical_ASLR_ROP[1] is False:
            if (opcode.startswith("lods") or opcode in ["mov", "add", "adc", "sub", "sbb", "and", "or", "xor"]) and \
               "[" in op2 and "+" not in op2 and "-" not in op2 and "*" not in op2 and \
               op1_family not in [None, 7] and op2_family not in [None, 6, 7] and op1_family != op2_family:
                self.practical_ASLR_ROP[1] = True

        if self.practical_ASLR_ROP[2] is False:
            if (opcode.startswith("stos") or opcode == "mov") and "[" in op1 and "+" not in op1 and \
               "-" not in op1 and "*" not in op1 and op1_family not in [None, 7] and op2_family not in [None, 7] and \
               op1_family != op2_family:
                self.practical_ASLR_ROP[2] = True

        if self.practical_ASLR_ROP[3] is False:
            if opcode in ["mov", "add", "adc", "and", "or", "xor"] and "[" not in op1 and "[" not in op2 and \
               op1_family not in [None, 7] and op2_family == 7:
                self.practical_ASLR_ROP[3] = True

        if self.practical_ASLR_ROP[4] is False:
            if opcode in ["clc", "sahf"] or \
               (opcode in ["test", "add", "adc", "sub", "sbb", "and", "or", "xor", "cmp"] and
               op1_family not in [None, 7] and op2_family not in [None, 7] and "[" not in op1 and "[" not in op2):
                self.practical_ASLR_ROP[4] = True

        if self.practical_ASLR_ROP[5] is False:
            if opcode == "pop" and op1_family in [0, 4, 5] and "[" not in op1:
                self.practical_ASLR_ROP[5] = True

        if self.practical_ASLR_ROP[6] is False:
            if opcode == "pop" and op1_family in [1, 2, 3, 6
                                                  ] and "[" not in op1:
                self.practical_ASLR_ROP[6] = True

        # NOTE class 8 (index 7) is combined above

        if self.practical_ASLR_ROP[8] is False:
            if opcode == "inc" and op1_family not in [None, 7
                                                      ] and "[" not in op1:
                self.practical_ASLR_ROP[8] = True

        if self.practical_ASLR_ROP[9] is False:
            if opcode == "dec" and op1_family not in [None, 7
                                                      ] and "[" not in op1:
                self.practical_ASLR_ROP[9] = True

        if self.practical_ASLR_ROP[10] is False:
            if opcode in ["add", "adc", "sub", "sbb"] and op1_family not in [None, 7] and "[" not in op1 and \
               op2_family not in [None, 7] and "[" not in op2 and op1_family != op2_family:
                self.practical_ASLR_ROP[10] = True

        # For the next 24 classes, some fairly common gadgets will satisfy many classes and significant
        # overlap in definitions exists. Check these without first seeing if the class is satisfied
        # POP AX
        if opcode == "pop" and "[" not in op1 and op1_family == 0:
            self.practical_ASLR_ROP[13] = True
            self.practical_ASLR_ROP[17] = True
            self.practical_ASLR_ROP[21] = True
            self.practical_ASLR_ROP[25] = True
            self.practical_ASLR_ROP[29] = True
            self.practical_ASLR_ROP[33] = True

        # XCHG AX with another GPR
        if opcode == "xchg" and "[" not in op1 and "[" not in op2:
            if op1_family == 0:
                if op2_family == 1:
                    self.practical_ASLR_ROP[11] = True
                    self.practical_ASLR_ROP[12] = True
                    self.practical_ASLR_ROP[13] = True
                    self.practical_ASLR_ROP[14] = True
                elif op2_family == 2:
                    self.practical_ASLR_ROP[15] = True
                    self.practical_ASLR_ROP[16] = True
                    self.practical_ASLR_ROP[17] = True
                    self.practical_ASLR_ROP[18] = True
                elif op2_family == 3:
                    self.practical_ASLR_ROP[19] = True
                    self.practical_ASLR_ROP[20] = True
                    self.practical_ASLR_ROP[21] = True
                    self.practical_ASLR_ROP[22] = True
                elif op2_family == 6:
                    self.practical_ASLR_ROP[23] = True
                    self.practical_ASLR_ROP[24] = True
                    self.practical_ASLR_ROP[25] = True
                    self.practical_ASLR_ROP[26] = True
                elif op2_family == 4:
                    self.practical_ASLR_ROP[27] = True
                    self.practical_ASLR_ROP[28] = True
                    self.practical_ASLR_ROP[29] = True
                    self.practical_ASLR_ROP[30] = True
                elif op2_family == 5:
                    self.practical_ASLR_ROP[31] = True
                    self.practical_ASLR_ROP[32] = True
                    self.practical_ASLR_ROP[33] = True
                    self.practical_ASLR_ROP[34] = True

            elif op2_family == 0:
                if op1_family == 1:
                    self.practical_ASLR_ROP[11] = True
                    self.practical_ASLR_ROP[12] = True
                    self.practical_ASLR_ROP[13] = True
                    self.practical_ASLR_ROP[14] = True
                elif op1_family == 2:
                    self.practical_ASLR_ROP[15] = True
                    self.practical_ASLR_ROP[16] = True
                    self.practical_ASLR_ROP[17] = True
                    self.practical_ASLR_ROP[18] = True
                elif op1_family == 3:
                    self.practical_ASLR_ROP[19] = True
                    self.practical_ASLR_ROP[20] = True
                    self.practical_ASLR_ROP[21] = True
                    self.practical_ASLR_ROP[22] = True
                elif op1_family == 6:
                    self.practical_ASLR_ROP[23] = True
                    self.practical_ASLR_ROP[24] = True
                    self.practical_ASLR_ROP[25] = True
                    self.practical_ASLR_ROP[26] = True
                elif op1_family == 4:
                    self.practical_ASLR_ROP[27] = True
                    self.practical_ASLR_ROP[28] = True
                    self.practical_ASLR_ROP[29] = True
                    self.practical_ASLR_ROP[30] = True
                elif op1_family == 5:
                    self.practical_ASLR_ROP[31] = True
                    self.practical_ASLR_ROP[32] = True
                    self.practical_ASLR_ROP[33] = True
                    self.practical_ASLR_ROP[34] = True

        # MOV between AX and another GPR
        if opcode == "mov" and "[" not in op1 and "[" not in op2:
            if op1_family == 0:
                if op2_family == 1:
                    self.practical_ASLR_ROP[13] = True
                    self.practical_ASLR_ROP[14] = True
                elif op2_family == 2:
                    self.practical_ASLR_ROP[17] = True
                    self.practical_ASLR_ROP[18] = True
                elif op2_family == 3:
                    self.practical_ASLR_ROP[21] = True
                    self.practical_ASLR_ROP[22] = True
                elif op2_family == 6:
                    self.practical_ASLR_ROP[25] = True
                    self.practical_ASLR_ROP[26] = True
                elif op2_family == 4:
                    self.practical_ASLR_ROP[29] = True
                    self.practical_ASLR_ROP[30] = True
                elif op2_family == 5:
                    self.practical_ASLR_ROP[33] = True
                    self.practical_ASLR_ROP[34] = True

            elif op2_family == 0:
                if op1_family == 1:
                    self.practical_ASLR_ROP[11] = True
                    self.practical_ASLR_ROP[12] = True
                elif op1_family == 2:
                    self.practical_ASLR_ROP[15] = True
                    self.practical_ASLR_ROP[16] = True
                elif op1_family == 3:
                    self.practical_ASLR_ROP[19] = True
                    self.practical_ASLR_ROP[20] = True
                elif op1_family == 6:
                    self.practical_ASLR_ROP[23] = True
                    self.practical_ASLR_ROP[24] = True
                elif op1_family == 4:
                    self.practical_ASLR_ROP[27] = True
                    self.practical_ASLR_ROP[28] = True
                elif op1_family == 5:
                    self.practical_ASLR_ROP[31] = True
                    self.practical_ASLR_ROP[32] = True

        # ["add", "adc", "sub", "sbb", "and", "or", "xor"] between AX and another GPR
        if opcode in ["add", "adc", "sub", "sbb", "and", "or", "xor"
                      ] and "[" not in op1 and "[" not in op2:
            if op1_family == 0:
                if op2_family == 1:
                    self.practical_ASLR_ROP[14] = True
                elif op2_family == 2:
                    self.practical_ASLR_ROP[18] = True
                elif op2_family == 3:
                    self.practical_ASLR_ROP[22] = True
                elif op2_family == 6:
                    self.practical_ASLR_ROP[26] = True
                elif op2_family == 4:
                    self.practical_ASLR_ROP[30] = True
                elif op2_family == 5:
                    self.practical_ASLR_ROP[34] = True

            elif op2_family == 0:
                if op1_family == 1:
                    self.practical_ASLR_ROP[12] = True
                elif op1_family == 2:
                    self.practical_ASLR_ROP[16] = True
                elif op1_family == 3:
                    self.practical_ASLR_ROP[20] = True
                elif op1_family == 6:
                    self.practical_ASLR_ROP[24] = True
                elif op1_family == 4:
                    self.practical_ASLR_ROP[28] = True
                elif op1_family == 5:
                    self.practical_ASLR_ROP[32] = True

        # Resume checks for individual classes 11, 15, 19, 23, 27, and 31. Others entirely checked entirely above
        if self.practical_ASLR_ROP[11] is False:
            if opcode == "pop" and "[" not in op1 and op1_family == 1:
                self.practical_ASLR_ROP[11] = True

        if self.practical_ASLR_ROP[15] is False:
            if opcode == "pop" and "[" not in op1 and op1_family == 2:
                self.practical_ASLR_ROP[15] = True

        if self.practical_ASLR_ROP[19] is False:
            if opcode == "pop" and "[" not in op1 and op1_family == 3:
                self.practical_ASLR_ROP[19] = True

        if self.practical_ASLR_ROP[23] is False:
            if opcode == "pop" and "[" not in op1 and op1_family == 6:
                self.practical_ASLR_ROP[23] = True

        if self.practical_ASLR_ROP[27] is False:
            if opcode == "pop" and "[" not in op1 and op1_family == 4:
                self.practical_ASLR_ROP[27] = True

        if self.practical_ASLR_ROP[31] is False:
            if opcode == "pop" and "[" not in op1 and op1_family == 5:
                self.practical_ASLR_ROP[31] = True