Exemple #1
0
class CrashGraph:

    def __init__(self, object, file_name):
        """" Initialized the object's internal data.
        Args:
            object: Crash object
            file_name: png output file name
        """
        self.r2_obj = object.r2_obj
        self.r2_dbg_obj = object.r2_dbg_obj
        self.r2_stand_obj = object.r2_stand_obj
        self.graph_obj = Graph()
        self.count = 1
        self.file_name = file_name


    def crash_graph(self):
        """ Graph generation """

        self.r2_stand_obj.analyze()
        self.arch_obj = Arch(self.r2_obj)

        self.r2_dbg_obj.debug_setenv("dbg.btdepth", "256")

        #afl
        func_list = self.r2_stand_obj.aflqj()

        if not func_list:
            print("No functions")
            sys.exit(-1)

        #set bps
        for function in func_list:
            self.r2_dbg_obj.debug_break(function)

        self.node_list = []
        self.range_list = []
        first = True

        while True:
            # continue
            self.r2_dbg_obj.debug_continue()

            get_info = self.r2_dbg_obj.debug_infoj()
            signal = get_info["signal"]

            self.r2_dbg_obj.debug_dmmSy()

            self.pc = self.arch_obj.get_reg("program_counter")
            self.pdj = self.r2_dbg_obj.debug_pdj_single(self.pc)
            bt = self.r2_dbg_obj.debug_dbt()

            # check access violation signal
            if Checks.check_signal(signal):
                regs = self.r2_dbg_obj.debug_registers()
                node_name = "crash_node"
                message = ""
                is_exploitable = False

                if self.pdj[0]["type"] == "invalid":
                    print("ERROR: Function crash_graph, the type is invalid!")
                    return False

                opcode = self.pdj[0]["opcode"]
                crash_address = self.pdj[0]["offset"]

                is_exploitable = CrashAnal.exploitable(signal, self.r2_dbg_obj)
                if is_exploitable:
                    exploitable_message = "PROBABLY EXPLOITABLE"
                    message = "crash details"
                else:
                    exploitable_message = "PROBABLY NOT EXPLOITABLE"
                    message = "details"

                label = "Exploitable: " + exploitable_message + " \n " + "crash instruction: \n" + str(hex(crash_address)) + " - " + str(opcode) + " \nbacktrace: \n " + bt + " \n " + "registers: \n" + regs + " \n "
                self.node = self.graph_obj.create_node(node_name, "green", label)
                self.node_list.append(self.node)

                # create edge
                try:
                    caller_address = bt.splitlines()[1].split()[1]
                except Exception as ex:
                    print("WARNING: caller address - backtrace error: %s" % ex)
                    caller_address = "0x0"

                self.create_edge(int(caller_address, 16), message)

                break

            if signal != "SIGTRAP":
                break

            if first:
                self.create_node("gold")
                first = False
                continue

            self.create_node("gold")

            try:
                caller_address = self.pdj[0]["xrefs"][0]["addr"]
            except Exception as ex:
                print("WARNING: caller address - xref not there: %s" % ex)
                try:
                    caller_address = bt.splitlines()[1].split()[1]
                except Exception as ex:
                    print("WARNING: caller address - backtrace erro: %s" % ex)
                    continue

            # create edge
            self.create_edge(caller_address, self.count)

        # create pdf
        self.graph_obj.create_pdf(self.file_name)

    def create_node(self, color):
        function_address = self.pdj[0]["fcn_addr"]
        func_address_end = self.pdj[0]["fcn_last"]
        r = range(function_address, func_address_end)
        self.range_list.append(r)
        func_name = self.pdj[0]["flags"][0]
        node_name = func_name
        label = func_name + " [ " + str(hex(function_address)) + " - " + str(hex(func_address_end)) + " ] "
        self.node = self.graph_obj.create_node(node_name, color, label)
        self.node_list.append(self.node)

    def create_edge(self, caller_address, label):
        for range_addr in self.range_list:
            if caller_address in range_addr:
                for single_node in self.node_list:
                    a = range_addr[0]
                    b = single_node.obj_dict["attributes"]["label"].split()[2]
                    if int(range_addr[0]) == int(b, 16):
                        self.graph_obj.create_edge(single_node, self.node, label)
                        self.count += 1
                        return
Exemple #2
0
class Parse:
    def __init__(self, input_file, filename):
        """" Initialized the object's internal data.
        """
        self.input_file = input_file
        self.graph_obj = Graph()
        self.filename = filename
        self.count = 0
        self.disass = []
        self.last_node = ""
        self.start_address = ""
        self.end_address = ""
        self.pc = ""
        self.name_function = None
        self.args_label = ""
        self.ret = None
        self.args = []

    def read_file(self):
        with open(self.input_file) as fp:
            line = fp.readline()
            while line:
                self.parse(line, fp)
                line = fp.readline()

        # create pdf
        self.graph_obj.create_pdf(self.filename)

    def parse(self, line, fp):
        if "[ADDR]" in line:
            line = line.split()
            self.parse_addr(line, fp)
        elif "[NOSYM]" in line:
            self.parse_nosym(line, fp)
        elif "[ARG]" in line:
            self.parse_args(line, fp)
            self.generate_ret_args()
        elif "[RET]" in line:
            self.parse_ret(line)
            self.generate_ret_args()
        else:
            return

    def parse_addr(self, line, fp):
        self.start_address = line[3]
        self.end_address = line[6]
        self.pc = line[8]
        self.name_function = line[10]
        new_line = fp.readline()
        if "TAG" in new_line:
            self.parse_disass(new_line, fp)
        if self.count < 600:
            self.generate_graph(True)

    def parse_disass(self, line, fp):
        self.disass = []
        self.bb_start = line.split()[1]

        while "END" not in line:
            line = fp.readline()
            a = line[52:]
            self.disass.append(a)

        fp.readline()

    def parse_nosym(self, line, fp):
        self.pc = line.split()[2]
        self.name_function = self.pc
        self.start_address = line.split()[6]
        self.end_address = line.split()[10]
        new_line = fp.readline()
        if "TAG" in new_line:
            self.parse_disass(new_line, fp)
        self.generate_graph(False)

    def parse_args(self, line, fp):
        self.wrap_function = line.split()[2]
        arg = "Arg: " + line.split()[5] + "\n"
        self.args.append(arg)
        line = fp.readline()
        while "ARG" in line:
            arg = "Arg: " + line.split()[5] + "\n"
            self.args.append(arg)

    def parse_ret(self, line):
        self.ret = "Return value: " + line.split()[4]

    def generate_ret_args(self):
        node_name = self.wrap_function
        color = "Orange"

        if not self.args_label:
            self.args_label = "Function: " + self.wrap_function + " [ " + self.start_address + " - " + self.end_address + " ] \n"

            if self.args:
                self.args_label += "".join(self.args)
                self.args = []
        if self.ret:
            self.args_label += "\n" + self.ret
            self.ret = None
            node_id = node_name
            self.graph_obj.create_node(node_id, color, self.args_label)
            self.args_label = ""

    def generate_graph(self, no_sym):
        color = "Green"
        label = ""
        node_name = self.pc

        if no_sym:
            label += self.name_function
        else:
            label = "BB"

        label += " [ " + self.start_address + " - " + self.end_address + " ] "
        label += "\n PC: " + self.pc + "\n"

        if self.disass:
            label += "".join(self.disass)
            self.disass = []
            color = "yellow"

        node_id = node_name

        if self.count == 0:  # first node
            self.node = self.graph_obj.create_node(node_id, color, label)
            self.last_node = self.node
            self.count = self.count + 1
        else:
            self.node = self.graph_obj.create_node(node_id, color, label)
            self.graph_obj.create_edge(self.last_node, self.node, self.count)
            self.count = self.count + 1
            self.last_node = self.node
Exemple #3
0
class Parse:
    def __init__(self, input_file, filename, crash_desc):
        """" Initialized the object's internal data.
        """
        self.input_file = input_file
        self.graph_obj = Graph()
        self.filename = filename
        self.count = 0
        self.disass = []
        self.last_node = ""
        self.start_address = ""
        self.end_address = ""
        self.pc = ""
        self.name_function = ""
        self.args_label = ""
        self.ret = ""
        self.signal = ""
        self.signal_num = ""
        self.args = []
        self.crash_desc = crash_desc

    def read_file(self):
        with open(self.input_file) as fp:
            line = fp.readline()
            while line:
                new_line = self.parse(line, fp)
                if new_line == None:
                    line = fp.readline()
                else:
                    line = new_line

        # create pdf
        self.graph_obj.create_pdf(self.filename)

    def parse(self, line, fp):
        if "[FUNC]" in line:
            self.parse_line(line, True)
            new_line = self.parse_addr(fp)
            return new_line
        elif "[NOFUNC]" in line:
            self.parse_line(line, False)
            new_line = self.parse_nosym(fp)
            return new_line
        elif "[ARG]" in line:
            new_line = self.parse_args(line, fp)
            self.generate_ret_args()
            return new_line
        elif "[RET]" in line:
            new_line = self.parse_ret(line, fp)
            self.generate_ret_args()
            return new_line
        elif "[CRASH]" in line:
            self.parse_crash(line)
            self.generate_crash()
        else:
            return None

    def parse_line(self, line, func):
        line = line.split(";")
        self.start_address = line[1]
        self.end_address = line[2]
        self.pc = line[3]
        if func:
            self.name_function = line[4]
        else:
            self.name_function = self.pc

    def parse_crash(self, line):
        line = line.split(";")
        self.signal_num = line[1]
        self.signal = line[2]
        self.pc = line[3]

    def parse_addr(self, fp):
        new_line = fp.readline()
        if "TAG" in new_line:
            self.parse_disass(new_line, fp)
            new_line = None

        if self.count < 60000:
            self.generate_graph(True)
        else:
            print(
                "It is not possible to generate the graph! (In pydot.py the call subprocess.Popen never end)"
            )
            sys.exit()
        return new_line

    def parse_disass(self, line, fp):
        self.disass = []
        self.bb_start = line.split()[1]

        while "END" not in line:
            line = fp.readline()
            a = line[52:]
            self.disass.append(a)

        fp.readline()

    def parse_nosym(self, fp):
        new_line = fp.readline()
        if "TAG" in new_line:
            self.parse_disass(new_line, fp)
            new_line = None

        if self.count < 60000:
            self.generate_graph(False)
        else:
            print(
                "It is not possible to generate the graph! (In pydot.py the call subprocess.Popen never end)"
            )
            sys.exit()

        return new_line

    def parse_args(self, line, fp):
        line = line.split(";")
        self.wrap_function = line[1]
        self.pc = line[2]
        self.arg_num = line[3]
        arg = "Arg" + self.arg_num + ": " + line[5] + "\n"
        self.args.append(arg)
        new_line = fp.readline()
        if "DUMP" in new_line:
            new_line = new_line.split(";")
            arg = "DUMP: " + new_line[2] + "\n"
            self.args.append(arg)
            new_line = None
        return new_line

    def parse_ret(self, line, fp):
        line = line.split(";")
        self.wrap_function = line[1]
        self.pc = line[2]
        self.ret = " Return value: " + line[3] + "\n"
        new_line = fp.readline()
        if "DUMP" in new_line:
            new_line = new_line.split(";")
            ret = "DUMP: " + new_line[2] + "\n"
            self.ret += ret
            new_line = None
        return new_line

    def generate_ret_args(self):
        node_name = str(self.wrap_function)
        color = "Orange"

        if not self.args_label:
            self.args_label = "Function: " + self.wrap_function + " [ " + self.start_address + " - " + self.end_address + " ] \n"

        if self.args:
            self.args_label += "".join(self.args)
            self.args = []

        if self.ret:
            self.args_label += "\nFunction: " + self.wrap_function + self.ret
            self.ret = None
            node_id = node_name
            self.graph_obj.create_node(node_id, color, self.args_label)
            self.args_label = ""

    def generate_graph(self, no_sym):
        color = "Green"
        label = ""
        node_name = str(self.pc)

        if no_sym:
            label += self.name_function
        else:
            label = "BB"

        label += " [ " + self.start_address + " - " + self.end_address + " ] "
        label += "\n PC: " + self.pc + "\n"

        if self.disass:
            label += "".join(self.disass)
            self.disass = []
            color = "yellow"

        node_id = node_name

        if self.count == 0:  # first node
            self.graph_obj.create_node(node_id, color, label)
            self.last_node = node_id
            self.count = self.count + 1
        else:
            self.graph_obj.create_node(node_id, color, label)
            self.graph_obj.create_edge(self.last_node, node_id, self.count)
            self.count = self.count + 1
            self.last_node = node_id

    def generate_crash(self):
        node_name = str(self.pc)
        self.crash_desc += "\nCrash at: " + self.pc + "Signal: " + self.signal_num + " [" + self.signal + "]"

        self.graph_obj.create_node(node_name, "Red", self.crash_desc)
        self.graph_obj.create_edge(self.last_node, node_name, self.count)