def set_color(self, color=None): for line in self.lines: line.color = color node_info = idaapi.node_info_t() node_info.bg_color = color idaapi.set_node_info2(self.startEA, self.id, node_info, idaapi.NIF_BG_COLOR)
def resetBlocks(): p = idaapi.node_info_t() p.bg_color = 0xFFFFCC #fname = idaapi.get_root_filename() fname = idc.eval_idc("ARGV[1]") funs_file = fname + '.funs' if not os.path.isfile(funs_file): print('No file at %s\n Creating the database files needed by RESim.' % funs_file) resimUtils.dumpFuns(fname=fname) funs_fh = open(funs_file) fun_json = json.load(funs_fh) print('funs_file %s' % funs_file) for fun in fun_json: fun_addr = int(fun) #print('fun_addr 0x%x' % fun_addr) f = idaapi.get_func(fun_addr) #print('fun addr 0x%x' % fun_addr) #print('fun is %s' % str(f)) if f is None: #print('no function found for 0x%x' % fun_addr) continue #print('doing function found for 0x%x' % fun_addr) graph = ida_gdl.FlowChart(f, flags=ida_gdl.FC_PREDS) for bb in graph: ida_graph.set_node_info( fun_addr, bb.id, p, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR)
def clear_nodes(self, nodes_metadata): """ Clear paint from the given graph nodes. """ # 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 # NOTE/COMPAT: if disassembler.USING_IDA7API: set_node_info = idaapi.set_node_info else: set_node_info = idaapi.set_node_info2 # # loop through every node that we have metadata data for, clearing # their paint (color) in the IDA graph view as applicable. # for node_metadata in nodes_metadata: # do the *actual* painting of a single node instance set_node_info(node_metadata.function.address, node_metadata.id, node_info, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR) self._painted_nodes.discard(node_metadata.address)
def paint_node_coverage(nodes_metadata, nodes_coverage): """ Paint function graph nodes using the given node coverages. """ # create a node info object as our vehicle for setting the node color node_info = idaapi.node_info_t() # # loop through every node that we have coverage data for, painting them # in the IDA graph view as applicable. # for node_coverage in nodes_coverage.itervalues(): node_metadata = nodes_metadata[node_coverage.address] # assign the background color we would like to paint to this node node_info.bg_color = node_coverage.coverage_color # # remember, nodes may technically be 'shared' between functions, # so we need to paint the node in every function flowchart that # has a reference to it. # for function_address, node_id in node_metadata.ids.iteritems(): # do the *actual* painting of a single node instance idaapi.set_node_info2(function_address, node_id, node_info, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR)
def unpaint_node_coverage(nodes_metadata, nodes_coverage): """ Unpaint function graph nodes using the given node coverages. """ # 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 # # loop through every node that we have coverage data for, clearing # their paint (color) in the IDA graph view as applicable. # for node_coverage in nodes_coverage.itervalues(): node_metadata = nodes_metadata[node_coverage.address] # # remember, nodes may technically be 'shared' between functions, # so we need to clear the node's paint in every function flowchart # that has a reference to it. # for function_address, node_id in node_metadata.ids.iteritems(): # do the *actual* painting of a single node instance idaapi.set_node_info2(function_address, node_id, node_info, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR)
def paint_nodes(self, nodes_coverage): """ Paint node level coverage defined by the current database mappings. """ # create a node info object as our vehicle for setting the node color node_info = idaapi.node_info_t() # # loop through every node that we have coverage data for, painting them # in the IDA graph view as applicable. # for node_coverage in nodes_coverage: node_metadata = node_coverage._database._metadata.nodes[ node_coverage.address] # assign the background color we would like to paint to this node node_info.bg_color = node_coverage.coverage_color # do the *actual* painting of a single node instance idaapi.set_node_info2(node_metadata.function.address, node_metadata.id, node_info, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR) self._painted_nodes.add(node_metadata.address)
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 set_color(self, color=None): for line in self.lines: line.color = color if color is None: idaapi.clr_node_info2(self._fc._q.bounds.startEA, self.id, idaapi.NIF_BG_COLOR) else: node_info = idaapi.node_info_t() node_info.bg_color = color idaapi.set_node_info2(self._fc._q.bounds.startEA, self.id, node_info, idaapi.NIF_BG_COLOR)
def color(self): node_info = idaapi.node_info_t() success = idaapi.get_node_info2(node_info, self._fc._q.bounds.startEA, self.id) if not success: return None if not node_info.valid_bg_color(): return None return node_info.bg_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 _OnNodeInfo(self, node_id): """Sets the node info based on its attributes.""" handler, value, attrs = self._get_handling_triplet(node_id) frame_color = handler.on_frame_color(value, attrs) node_info = idaapi.node_info_t() if frame_color is not None: node_info.frame_color = frame_color flags = node_info.get_flags_for_valid() self.SetNodeInfo(node_id, node_info, flags)
def color_block(ea=None, color=0x55ff7f): """http://reverseengineering.stackexchange.com/questions/10662/change-block-node-color-with-idapython and WanderingGlitch for the tip of refresh_idaview_anyway()""" func_top = fn.top() f = idaapi.get_func(ea) g = idaapi.FlowChart(f, flags=idaapi.FC_PREDS) bb_id = get_bb_id(g, ea) p = idaapi.node_info_t() p.bg_color = color idaapi.set_node_info2(func_top, bb_id, p, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR) idaapi.refresh_idaview_anyway()
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_nodes(function_address, nodes, color): """ Color a list of nodes within the function graph at function_address. """ # create node info object with specified color node_info = idaapi.node_info_t() node_info.bg_color = color # paint the specified nodes for node in nodes: idaapi.set_node_info2( function_address, node.id, node_info, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR )
def OnRefresh(self): """ Event called when the graph is refreshed or first created. From this event you are supposed to create nodes and edges. This callback is mandatory. @note: ***It is important to clear previous nodes before adding nodes.*** @return: Returning True tells the graph viewer to use the items. Otherwise old items will be used. """ self.nodes = {} self.Clear() # nodes for n in range(len(self.items)): item = self.items[n] focus_node, hl, color = self.get_node_info(n) node_label = self.get_node_label(n, highlight_node=hl) nid = self.AddNode((node_label, color)) p = idaapi.node_info_t() p.frame_color = 0x000000 if hl: p.frame_color = self.CL_NODE_HIGHLIGHT if focus_node: p.frame_color = self.CL_NODE_FOCUS self.SetNodeInfo(nid, p, idaapi.NIF_FRAME_COLOR) self.nodes[item.obj_id] = nid if self.center_node and focus_node: widget = ida_kernwin.find_widget(self._title) ida_graph.viewer_center_on(widget, nid) # edges for n in range(len(self.items)): item = self.items[n] for i in range(self.nsucc(n)): t = self.succ(n, i) self.AddEdge(self.nodes[item.obj_id], self.nodes[self.items[t].obj_id]) return True
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 getBlock(tgtEA): ''' Get the basic block for taget EA, returns None if not found ''' f = idaapi.get_func(tgtEA) if not f: return None fc = idaapi.FlowChart(f) p = idaapi.node_info_t() p.bg_color = 0x00ff00 # green for block in fc: if block.startEA <= tgtEA: if block.endEA > tgtEA: for ea in Heads(block.startEA, block.endEA): SetColor(ea, CIC_ITEM, 0x00ff00) return block return None
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 SetBbColor(self, ea=None, color=0x55ff7f): ''' SetBbColor(ea, color) => None Set Color for selected base block (default color = green) Example: ida SetBbColor 0x456789 [0xFFFFFF] ''' def get_bb(graph, ea): for block in graph: if block.startEA <= ea and block.endEA > ea: return block f = idaapi.get_func(ea) g = idaapi.FlowChart(f, flags=idaapi.FC_PREDS) bb = get_bb(g, ea) # create color node p = idaapi.node_info_t() p.bg_color = color # Set Color idaapi.set_node_info2(f.start_ea, bb.id, p, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR) idaapi.refresh_idaview_anyway() return None
def OnRefresh(self): """ @return: 返回 True 告诉 graph viewer 使用新的 items """ self.nodes = {} self.Clear() # nodes for n in range(len(self.items)): item = self.items[n] focus_node, highlight_node, color = self._get_node_info(n) node_label = self._get_node_label(n, highlight_node=highlight_node) nid = self.AddNode((node_label, color)) framecol = self.COLOR_FRAME_DEFAULT if highlight_node: framecol = self.COLOR_FRAME_HIGHLIGHT if focus_node: framecol = self.COLOR_FRAME_FOCUS p = idaapi.node_info_t() p.frame_color = framecol self.SetNodeInfo(nid, p, idaapi.NIF_FRAME_COLOR) self.nodes[item.obj_id] = nid if self.center_node and focus_node: widget = ida_kernwin.find_widget(self._title) ida_graph.viewer_center_on(widget, nid) # edges for n in range(len(self.items)): item = self.items[n] for i in range(self._nsucc(n)): t = self._succ(n, i) self.AddEdge(self.nodes[item.obj_id], self.nodes[self.items[t].obj_id]) return True
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)
import json import idaapi import ida_graph import ida_gdl import idaversion def getBB(graph, bb): for block in graph: if block.start_ea <= bb and block.end_ea > bb: return block.id return None p = idaapi.node_info_t() p.bg_color = 0xFFFFCC fname = get_root_filename() funs_fh = open(fname + '.funs') funs_file = fname + '.funs' if not os.path.isfile(funs_file): ''' maybe a symbolic link, ask monitor for name ''' cmd = '@cgc.getCoverageFile()' latest_funs_file = gdbProt.Evalx('SendGDBMonitor("%s");' % cmd).strip() print('no file %s, monitor says %s' % (funs_file, latest_funs_file)) command = "@cgc.getSOFromFile('%s')" % fname simicsString = gdbProt.Evalx('SendGDBMonitor("%s");' % command) print('so stuff: %s' % simicsString) if ':' in simicsString: adders = simicsString.split(':')[1] start = adders.split('-')[0]
def doColor(latest_hits_file, all_hits_file, pre_hits_file): with open(latest_hits_file) as funs_fh: latest_hits_json = json.load(funs_fh) print('loaded blocks from %s, got %d functions' % (latest_hits_file, len(latest_hits_json))) with open(all_hits_file) as funs_fh: all_hits_json = json.load(funs_fh) print('loaded blocks from %s, got %d functions' % (all_hits_file, len(all_hits_json))) with open(pre_hits_file) as funs_fh: pre_hits_json = json.load(funs_fh) print('loaded blocks from %s, got %d functions' % (pre_hits_file, len(pre_hits_json))) p = idaapi.node_info_t() ''' New hits ''' p.bg_color = new_hit_color num_new = 0 edges = OrderedDict() for fun in latest_hits_json: fun_addr = int(fun) f = idaapi.get_func(fun_addr) #print('fun addr 0x%x' % fun_addr) graph = ida_gdl.FlowChart(f, flags=ida_gdl.FC_PREDS) ''' get edges leaving all hit blocks ''' ''' edges[branch_to] = branch_from ''' ''' retain order of hits in list of branches not taken ''' for bb_addr in latest_hits_json[fun]: ''' get the BB and check its branch-to's ''' block = getBB(graph, bb_addr) if block is not None: for s in block.succs(): if s.start_ea not in latest_hits_json[fun] and not (fun in pre_hits_json and s.start_ea in pre_hits_json[fun]) and s.start_ea not in edges: #print('added edges[0%x] block 0x%x block.end_ea 0x%x bb_addr was 0x%x ' % (s.start_ea, block.start_ea, block.end_ea, bb_addr)) ''' branch from block was not hit ''' edges[s.start_ea] = block.start_ea for bb in latest_hits_json[fun]: block = getBB(graph, bb) if block is not None: bb_id = block.id if fun not in all_hits_json or bb not in all_hits_json[fun]: ''' first time bb has been hit in any data session ''' p.bg_color = new_hit_color ida_graph.set_node_info(fun_addr, bb_id, p, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR) print('new hit fun 0x%x bb: 0x%x bb_id: %d block.start_ea 0x%x end 0x%x' % (fun_addr, bb, bb_id, block.start_ea, block.end_ea)) num_new += 1 elif bb in all_hits_json[fun]: ''' also hit in earlier data session ''' p.bg_color = old_hit_color ida_graph.set_node_info(fun_addr, bb_id, p, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR) #print('old hit fun 0x%x bb: 0x%x' % (fun_addr, bb)) else: print('impossible') exit(1) print('Data run generated %d new hits' % num_new) print('Unhit edges') ''' Not hit on recent data session, but hit previously ''' p.bg_color = not_hit_color for fun in all_hits_json: fun_addr = int(fun) f = idaapi.get_func(fun_addr) #print('fun addr 0x%x' % fun_addr) if f is None: print('unable to get function from addr 0x%x' % fun_addr) continue graph = ida_gdl.FlowChart(f, flags=ida_gdl.FC_PREDS) for bb in all_hits_json[fun]: bb_id = getBBId(graph, bb) if bb_id is not None: if fun not in latest_hits_json or bb not in latest_hits_json[fun]: ida_graph.set_node_info(fun_addr, bb_id, p, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR) #print('not hit fun 0x%x bb: 0x%x' % (fun_addr, bb)) ''' Hit prior to start of any data session, i.e., IO setup ''' p.bg_color = pre_hit_color for fun in pre_hits_json: fun_addr = int(fun) f = idaapi.get_func(fun_addr) #print('fun addr 0x%x' % fun_addr) graph = ida_gdl.FlowChart(f, flags=ida_gdl.FC_PREDS) for bb in pre_hits_json[fun]: bb_id = getBBId(graph, bb) if bb_id is not None: if (fun not in latest_hits_json or bb not in latest_hits_json[fun]) and (fun not in all_hits_json or bb not in all_hits_json[fun]): ida_graph.set_node_info(fun_addr, bb_id, p, idaapi.NIF_BG_COLOR | idaapi.NIF_FRAME_COLOR) #print('not hit fun 0x%x bb: 0x%x' % (fun_addr, bb)) return edges
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 _set_node_bg_color(self, node_id, bg_color): node_info = idaapi.node_info_t() node_info.bg_color = bg_color self.SetNodeInfo(node_id, node_info, idaapi.NIF_BG_COLOR)