def _paint_nodes(self, node_addresses): """ Paint node level coverage defined by the current database mappings. """ db_coverage = self.director.coverage db_metadata = self.director.metadata # create a node info object as our vehicle for setting the node color node_info = idaapi.node_info_t() node_info.bg_color = self.palette.coverage_paint node_flags = idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR # # loop through every node that we have coverage data for, painting them # in the IDA graph view as applicable. # for node_address in node_addresses: # retrieve all the necessary structures to paint this node node_coverage = db_coverage.nodes.get(node_address, None) node_metadata = db_metadata.nodes.get(node_address, None) functions = db_metadata.get_functions_by_node(node_address) # # if we did not get *everything* that we needed, then it is # possible the database changesd, or the coverage set changed... # # this is kind of what we get for not using locks :D but that's # okay, just stop painting here and let the painter sort it out # if not (node_coverage and node_metadata and functions): self._msg_queue.put(self.MSG_ABORT) node_addresses = node_addresses[:node_addresses. index(node_address)] break # # get_functions_by_node() can return multiple functios (eg, a # shared node) but in IDA should only ever return one... so we # can pull it out now # function_metadata = functions[0] # ignore nodes that are only partially executed if node_coverage.instructions_executed != node_metadata.instruction_count: continue # do the *actual* painting of a single node instance set_node_info(function_metadata.address, node_metadata.id, node_info, node_flags) self._painted_nodes |= set(node_addresses) self._action_complete.set()
def reset_all_block_color_to_white(addr): white = 0xffffff f = idaapi.get_func(addr) g = idaapi.FlowChart(f, flags=idaapi.FC_PREDS) p = idaapi.node_info_t() p.bg_color = white base_block_ea = f.start_ea for block in g: idaapi.set_node_info(base_block_ea, block.id, p, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR)
def recoverColor(self): if not self.current_focused_addr: # print("1") return if self.current_bb_id == None: # print("2") return p = idaapi.node_info_t() color = 0xffffff p.bg_color = color idaapi.set_node_info(self.current_block_start_ea, self.current_bb_id, p, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR)
def set_color(self, color=None): for line in self.lines: line.color = color if color is None: idaapi.clr_node_info(self._fc._q.bounds.start_ea, self.id, idaapi.NIF_BG_COLOR) else: node_info = idaapi.node_info_t() node_info.bg_color = color idaapi.set_node_info(self._fc._q.bounds.start_ea, self.id, node_info, idaapi.NIF_BG_COLOR)
def _clear_nodes(self, node_addresses): """ Clear paint from the given graph nodes. """ db_metadata = self.director.metadata # create a node info object as our vehicle for resetting the node color node_info = idaapi.node_info_t() node_info.bg_color = idc.DEFCOLOR node_flags = idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR # # loop through every node that we have metadata data for, clearing # their paint (color) in the IDA graph view as applicable. # # read self._paint_nodes() comments for more info, the code below # is very similar, sans the repetitive comments # for node_address in node_addresses: functions = db_metadata.get_functions_by_node(node_address) node_metadatas = {} for function in functions: node_metadata = function.nodes.get(node_address, None) if not node_metadata: node_metadatas = {} break node_metadatas[function.address] = node_metadata # abort if something looks like it changed... if not node_metadatas: self._msg_queue.put(self.MSG_ABORT) node_addresses = node_addresses[:node_addresses. index(node_address)] break # do the *actual* painting of a single node instance for function_address, node_metadata in iteritems(node_metadatas): set_node_info(function_address, node_metadata.id, node_info, node_flags) self._painted_nodes -= set(node_addresses) self._action_complete.set()
def color_node(self, addresses, bg_color, frame_color): if len(addresses) <= 0: return func = idaapi.get_func(idaapi.get_imagebase() + addresses[0]) flowchart_ = idaapi.FlowChart(func) address_map = {} for address in addresses: address_map[idaapi.get_imagebase() + address] = 1 for code_block in flowchart_: if not code_block.start_ea in address_map: continue node_info = idaapi.node_info_t() node_info.bg_color = bg_color node_info.frame_color = frame_color idaapi.set_node_info(func.start_ea, code_block.id, node_info, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR)
def _clear_nodes(self, node_addresses): """ Clear paint from the given graph nodes. """ db_metadata = self.director.metadata # create a node info object as our vehicle for resetting the node color node_info = idaapi.node_info_t() node_info.bg_color = idc.DEFCOLOR node_flags = idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR # # loop through every node that we have metadata data for, clearing # their paint (color) in the IDA graph view as applicable. # for node_address in node_addresses: # retrieve all the necessary structures to paint this node node_metadata = db_metadata.nodes.get(node_address, None) functions = db_metadata.get_functions_by_node(node_address) # # abort if something looks like it changed... read the comments in # self._paint_nodes for more verbose information # if not (node_metadata and functions): self._msg_queue.put(self.MSG_ABORT) node_addresses = node_addresses[:node_addresses. index(node_address)] break function_metadata = functions[0] # do the *actual* painting of a single node instance set_node_info(function_metadata.address, node_metadata.id, node_info, node_flags) self._painted_nodes -= set(node_addresses) self._action_complete.set()
def _paint_nodes(self, node_addresses): """ Paint node level coverage defined by the current database mappings. """ db_coverage = self.director.coverage db_metadata = self.director.metadata # create a node info object as our vehicle for setting the node color node_info = idaapi.node_info_t() node_info.bg_color = self.palette.coverage_paint node_flags = idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR # # loop through every node that we have coverage data for, painting them # in the IDA graph view as applicable. # for node_address in node_addresses: # retrieve all the necessary structures to paint this node node_coverage = db_coverage.nodes.get(node_address, None) functions = db_metadata.get_functions_by_node(node_address) # # due to the fact that multiple functions may 'share' a node, # we need to go through and explicitly fetch the node metadata # from each function when performing a paint. # # this is because each function will have a unique node_id in # the target node_metadata(s) # node_metadatas = {} for function in functions: # attempt to safely fetch the node metadata from a function node_metadata = function.nodes.get(node_address, None) # # this is possible if function is getting torn down. this is because # we don't use locks. this just means it is time for us to bail as # the metadata state is changing and the paint should be canceled # if not node_metadata: node_metadatas = [] break node_metadatas[function.address] = node_metadata # # if we did not get *everything* that we needed, then it is # possible the database changesd, or the coverage set changed... # # this is kind of what we get for not using locks :D but that's # okay, just stop painting here and let the painter sort it out # if not (node_coverage and node_metadatas): self._msg_queue.put(self.MSG_ABORT) node_addresses = node_addresses[:node_addresses. index(node_address)] break # ignore nodes that are only partially executed if node_coverage.instructions_executed != node_metadata.instruction_count: continue # do the *actual* painting o;f a single node instance for function_address, node_metadata in iteritems(node_metadatas): set_node_info(function_address, node_metadata.id, node_info, node_flags) self._painted_nodes |= set(node_addresses) self._action_complete.set()
def changeColor(self): p = idaapi.node_info_t() color = 0xffff00 p.bg_color = color idaapi.set_node_info(self.current_block_start_ea, self.current_bb_id, p, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR)