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: # for line in fp self.parse(line, fp) line = fp.readline() # create png self.graph_obj.create_png(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) 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) self.generate_graph() 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): self.pc = line[3] self.name_function = None 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): color = "Green" if self.name_function: node_name = self.name_function else: node_name = "NoSym" label = self.name_function + " [ " + self.start_address + " - " + self.end_address + " ] " label += "\n PC: " + self.PC + "\n" if self.disass: label += "".join(self.disass) self.disass = [] node_name = "disas" color = "yellow" node_id = node_name + str(self.count) 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
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 png self.graph_obj.create_png(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