def __mark_bbls(self): for thread in self["mem_areas"][0]['threads']: for bbl in thread['bbls']: ea = bbl['start'] for _ in range(bbl['inst']): idaapi.set_item_color(ea, 0x49feaf) ea += idautils.DecodeInstruction(ea).size
def analysis_finish_cb(self, outfname, logfname, cfaoutfname, ea=None): bc_log.debug("Parsing analyzer result file") try: cfa = cfa_module.CFA.parse(outfname, logs=logfname) except (pybincat.PyBinCATException): bc_log.error("Could not parse result file") return None self.clear_background() self.cfa = cfa if cfa: # XXX add user preference for saving to idb? in that case, store # reference to marshalled cfa elsewhere bc_log.info("Storing analysis results to idb...") with open(outfname, 'rb') as f: self.netnode["out.ini"] = f.read() with open(logfname, 'rb') as f: self.netnode["analyzer.log"] = f.read() if self.remapped_bin_path: self.netnode["remapped_bin_path"] = self.remapped_bin_path self.netnode["remap_binary"] = self.remap_binary if cfaoutfname is not None and os.path.isfile(cfaoutfname): with open(cfaoutfname, 'rb') as f: self.last_cfaout_marshal = f.read() bc_log.info("Analysis results have been stored idb.") else: bc_log.info("Empty or unparseable result file.") bc_log.debug("----------------------------") # Update current RVA to start address (nodeid = 0) # by default, use current ea - e.g, in case there is no results (cfa is # None) or no node 0 (happens in backward mode) current_ea = self.current_ea if ea is not None: current_ea = ea else: try: node0 = cfa['0'] if node0: current_ea = node0.address.value except (KeyError, TypeError): # no cfa is None, or no node0 pass self.set_current_ea(current_ea, force=True) self.netnode["current_ea"] = current_ea if not cfa: return for addr, nodeids in cfa.states.items(): ea = addr.value tainted = False for n_id in nodeids: # is it tainted? # find children state state = cfa[n_id] if state.tainted: tainted = True break if tainted: idaapi.set_item_color(ea, 0xDDFFDD) else: idaapi.set_item_color(ea, 0xCDCFCE)
def activate(self, ctx): import json filepath = idc.AskFile(False, "*.zmu;*.overlay;*", "Load Zelos Overlay...") if filepath is None: return f = open(filepath, "r") zelos_data = f.read() f.close() zelos_data = zelos_data[len("DISAS\n"):] zelos_dump = json.loads(zelos_data) # Apply the overlay data for comment in zelos_dump["comments"]: ea = comment["address"] try: comment_text = str(comment["text"]) except UnicodeEncodeError: comment_text = "" color = comment.get("color", 0x73F0DF) # Set color of instruction line idaapi.set_item_color(ea, color) idaapi.set_cmt(ea, comment_text, False) # Set function name if not already changed idc.GetFunctionAttr(ea, idc.FUNCATTR_START) name = idc.GetFunctionName(ea) if len(name) > 0 and name.startswith("zmu_") is False: idc.MakeName(ea, "zmu_" + name) return 1
def activate(self, ctx): import json filepath = idc.AskFile(False, '*.zmu;*.overlay;*', 'Load Zemu Overlay...') if filepath is None: return f = open(filepath, 'r') zemu_data = f.read() f.close() zemu_data = zemu_data[len('DISAS\n'):] zemu_dump = json.loads(zemu_data) # Apply the overlay data for comment in zemu_dump['comments']: ea = comment['address'] comment_text = str(comment['text']) color = comment.get('color', 0x73f0df) # Set color of instruction line idaapi.set_item_color(ea, color) idaapi.set_cmt(ea, comment_text, False) # Set function name if not already changed idc.GetFunctionAttr(ea, idc.FUNCATTR_START) name = idc.GetFunctionName(ea) if len(name) > 0 and name.startswith('zmu_') == False: idc.MakeName(ea, 'zmu_' + name) return 1
def clear_instructions(self, instructions): """ Clear paint from the given instructions. """ for address in instructions: idaapi.set_item_color(address, idc.DEFCOLOR) self._painted_instructions.discard(address)
def paint_instructions(self, instructions): """ Paint instruction level coverage defined by the current database mapping. """ for address in instructions: idaapi.set_item_color(address, self.palette.ida_coverage) self._painted_instructions.add(address)
def highlight(self, color=COLOR): for ea in idautils.Heads(): if idaapi.isCode(idaapi.getFlags(ea)) and idaapi.is_call_insn(ea): current_color = idaapi.get_item_color(ea) if current_color == self.COLOR: idaapi.set_item_color(ea, idc.DEFCOLOR) elif current_color == idc.DEFCOLOR: idaapi.set_item_color(ea, self.COLOR)
def run(self, arg): try: for ea in idautils.Heads(): idaapi.set_item_color(ea, self.COLOR_DEFAULT) except Exception as err: idaapi.msg("Exception during run: %s\n" % str(err)) raise
def highlight(self): for ea in idautils.Heads(): flags = ida_shims.get_full_flags(ea) if ida_shims.is_code(flags) and idaapi.is_call_insn(ea): current_color = idaapi.get_item_color(ea) if current_color == self.COLOR: idaapi.set_item_color(ea, idc.DEFCOLOR) elif current_color == idc.DEFCOLOR: idaapi.set_item_color(ea, self.COLOR)
def clear_background(self): """ reset background color for previous analysis """ if self.cfa: color = idaapi.calc_bg_color(idaapi.NIF_BG_COLOR) for v in self.cfa.states: ea = v.value idaapi.set_item_color(ea, color)
def mark_bbls(self, mem_area_id): if not self._from_idb: for tid in self._maze['process']['mem_areas'][mem_area_id]['tids']: for thread in self._maze['process']['threads']: if tid == thread['tid']: for bbl in thread['bbls']: ea = bbl['start'] for _ in range(bbl['inst']): inst_size = idc.MakeCode(ea) idaapi.set_item_color(ea, 0x49feaf) ea += inst_size
def colorize_node(self, ea, color): # Colorizes an entire code block func = idaapi.get_func(ea) if func: for block in idaapi.FlowChart(func): if block.startEA <= ea and block.endEA > ea: ea = block.startEA while ea < block.endEA: idaapi.set_item_color(ea, color) ea = idc.NextHead(ea) break
def cb_curline(self, ea): if self.prev_loc: prev_ea, prev_color = self.prev_loc cur_color = idaapi.get_item_color(prev_ea) # race condition: block/instruction's color may have been modified # after it was saved if (cur_color != prev_color) and (cur_color != COL_CURLINE): prev_color = cur_color idaapi.set_item_color(prev_ea, prev_color) self.prev_loc = [ea, idaapi.get_item_color(ea)] idaapi.set_item_color(ea, COL_CURLINE)
def paint_instruction_coverage(coverage, color): """ Paint instructions using the given coverage blocks. """ # # loop through every byte in each block (base_address -> base_address+size) # given, coloring each byte individually # for address in coverage.coverage_data: idaapi.set_item_color(address, color)
def color(ea, nbins, c): '''Color 'nbins' instructions starting from ea''' colors = defaultdict(int, { 'black': 0x000000, 'red': 0x0000FF, 'blue': 0xFF0000, 'green': 0x00FF00 }) for _ in range(nbins): idaapi.del_item_color(ea) idaapi.set_item_color(ea, colors[c]) ea += idc.ItemSize(ea)
def OnSelectLine(self, n): self.selcount += 1 func_addr = int(self.items[n][0], 16) func_name = self.items[n][1] t_addrs = self.function_to_addrs[func_addr] idaapi.msg("%d tainted instructions in %s\n" % \ (len(t_addrs), func_name)) for tainted_addr in t_addrs: idaapi.set_item_color(tainted_addr, TAINTED) idaapi.jumpto(func_addr)
def color(ea, nbins, c): '''Color 'nbins' instructions starting from ea''' colors = defaultdict(int, { 'black' : 0x000000, 'red' : 0x0000FF, 'blue' : 0xFF0000, 'green' : 0x00FF00 } ) for _ in range(nbins): idaapi.del_item_color(ea) idaapi.set_item_color(ea, colors[c]) ea += idc.ItemSize(ea)
def colorize_node(self, ea, color): func = idaapi.get_func(ea) if func: for block in idaapi.FlowChart(func): block_start_ea = ida_shims.start_ea(block) block_end_ea = ida_shims.end_ea(block) if block_start_ea <= ea and block_end_ea > ea: ea = block_start_ea while ea < block_end_ea: idaapi.set_item_color(ea, color) ea = ida_shims.next_head(ea) break
def color_items(address, size, color): """ Color a region of bytes as specified by address and size. """ # loop through the entire region (address -> address+size) coloring lines while size > 0: # color the current item idaapi.set_item_color(address, color) # move forward to the next item next_address = idaapi.next_not_tail(address) size -= next_address - address address = next_address
def apply_colors(self, vd, result): self.reset_all_colors() if not result: return pseudocode, lineno, col, item_ea_list = result disasm_lines = [(ea, idaapi.get_item_color(ea)) for ea in item_ea_list] if len(item_ea_list): idaapi.jumpto(item_ea_list[0], -1, idaapi.UIJMP_IDAVIEW | idaapi.UIJMP_DONTPUSH) self.pseudocode_instances[vd.view_idx] = (pseudocode, lineno, col, disasm_lines) if pseudocode: try: pseudocode[lineno].bgcolor = HL_COLOR except Exception as err: # wtf print(err) for ea, _ in disasm_lines: idaapi.set_item_color(ea, HL_COLOR)
def reset_colors(self, idx, ignore_vd=False): v = self.pseudocode_instances[idx] if v: pseudocode, lineno, color, disasm_lines = v if not ignore_vd and pseudocode: try: if color != HL_COLOR: pseudocode[lineno].bgcolor = color else: pseudocode[lineno].bgcolor = DEF_COLOR except Exception as e: # wtf print(e) for ea, color in disasm_lines: if color != HL_COLOR: idaapi.set_item_color(ea, color) else: idaapi.set_item_color(ea, DEF_COLOR) # pseudocode_instances.pop(idx) return
def forcus_addr(self, from_addr): db_metadata = self._model._director.metadata cfunc = self._model._director.cfunc_current if cfunc: decompilation_text = cfunc.get_pseudocode() # # the objective here is to paint hexrays lines that are associated with # our runtime data. unfortunately, there are very few API resources that # link decompilation line numbers to anything (eg, citems, nodes, ea, etc) # # this means that we must build our own data relationships to draw from # # # first, let's build a relationship between a given line of text, and the # citems that contribute to it. the only way to do that (as I see it) is # to lex citem ID's out of the decompiled output string # line2citem = map_line2citem(decompilation_text) # # now that we have some understanding of how citems contribute to each # line of decompiled text, we can use this information to build a # relationship that ties graph nodes (basic blocks) to individual lines. # line2node = map_line2itemaddress(cfunc, db_metadata, line2citem) idaapi.set_item_color(from_addr, 0x1EDB98) for line_number, line_nodes in line2node.iteritems(): if from_addr in line_nodes: decompilation_text[line_number].bgcolor = 0x1EDB98 idaapi.refresh_idaview_anyway() break else: idaapi.set_item_color(from_addr, 0x1EDB98)
def cb_color(self, ea): idaapi.set_item_color(ea, COL_CBTRACE)
def run(self, arg): try: for ea in idautils.Heads(): #print(idc.print_operand(ea, 0)) mnem = idc.print_insn_mnem(ea) # color call instructions if mnem == 'call': idaapi.set_item_color(ea, self.COLOR_CALL) continue # color lea instructions if mnem == 'lea': idaapi.set_item_color(ea, self.COLOR_POINTER) continue # color suspected crypto instructions # xor that does not zero out the register if mnem == 'xor' and (idc.print_operand(ea, 0) != idc.print_operand(ea, 1)): idaapi.set_item_color(ea, self.COLOR_CRYPTO) continue # common RC4 instructions if mnem == 'cmp' and idc.get_operand_type( ea, 0) == ida_ua.o_reg and idc.print_operand( ea, 1) == '0x100': idaapi.set_item_color(ea, self.COLOR_CRYPTO) continue # misc math operations mathInstrList = [ 'sar', 'sal', 'shr', 'shl', 'ror', 'rol', 'idiv', 'div', 'imul', 'mul', 'not' ] if mnem in mathInstrList: idaapi.set_item_color(ea, self.COLOR_CRYPTO) continue # color string operations # skip instructions that start with 'c' to exclude conditional moves, e.g. cmovs if (mnem.startswith('c') == False) and (mnem.endswith('x') == False) and \ (('scas' in mnem) or ('movs' in mnem) or ('stos' in mnem)): idaapi.set_item_color(ea, self.COLOR_STRING_OPERATION) continue except Exception as err: idaapi.msg("Exception during run: %s\n" % str(err)) raise
def set_item_color(self, address, color): return idaapi.set_item_color(address, color)
def analysis_finish_cb(self, outfname, logfname, cfaoutfname, ea=None): idaapi.show_wait_box("HIDECANCEL\nParsing BinCAT analysis results") bc_log.debug("Parsing analyzer result file") # Here we can't check for user_cancelled because the UI is # unresponsive when parsing. try: cfa = cfa_module.CFA.parse(outfname, logs=logfname) except (pybincat.PyBinCATException, NoSectionError): idaapi.hide_wait_box() bc_log.error("Could not parse result file") return None self.clear_background() self.cfa = cfa if cfa: # XXX add user preference for saving to idb? in that case, store # reference to marshalled cfa elsewhere bc_log.info("Storing analysis results to idb...") with open(outfname, 'rb') as f: self.netnode["out.ini"] = f.read() with open(logfname, 'rb') as f: self.netnode["analyzer.log"] = f.read() if self.remapped_bin_path: self.netnode["remapped_bin_path"] = self.remapped_bin_path self.netnode["remap_binary"] = self.remap_binary if cfaoutfname is not None and os.path.isfile(cfaoutfname): with open(cfaoutfname, 'rb') as f: self.last_cfaout_marshal = f.read() bc_log.info("Analysis results have been stored idb.") else: bc_log.info("Empty or unparseable result file.") bc_log.debug("----------------------------") idaapi.replace_wait_box("Updating IDB with BinCAT results") # Update current RVA to start address (nodeid = 0) # by default, use current ea - e.g, in case there is no results (cfa is # None) or no node 0 (happens in backward mode) current_ea = self.current_ea if ea is not None: current_ea = ea else: try: node0 = cfa['0'] if node0: current_ea = node0.address.value except (KeyError, TypeError): # no cfa is None, or no node0 pass try: self.set_current_ea(current_ea, force=True) except TypeError as e: bc_log.warn("Could not load results from IDB") bc_log.warn("------ BEGIN EXCEPTION -----") bc_log.exception(e) bc_log.warn("------ END EXCEPTION -----") idaapi.hide_wait_box() return None self.netnode["current_ea"] = current_ea if not cfa: return for addr, nodeids in cfa.addr_nodes.items(): if hasattr(idaapi, "user_cancelled") and idaapi.user_cancelled() > 0: bc_log.info("User cancelled!") idaapi.hide_wait_box() return None ea = addr.value tainted = False taint_id = 1 for n_id in nodeids: # is it tainted? # find child nodes node = cfa[n_id] if node.tainted: tainted = True if node.taintsrc: # Take the first one taint_id = int(node.taintsrc[0].split("-")[1]) break if tainted: idaapi.set_item_color(ea, taint_color(taint_id)) else: idaapi.set_item_color(ea, 0xF0F0F0) idaapi.hide_wait_box() self.gui.focus_registers()
def colorize(addr, color): idaapi.set_item_color(addr, color)
''' Highlights instructions that reads and writes to heap based on trace from PIN tool ''' try: trace = open("StructTrace","r").readlines() except: sys.exit("Error opening file!") address_read = [] address_write = [] for line in trace: if '@' not in line: continue eip = line.split('@')[0].strip() if eip in address_read + address_write: continue if 'MREAD' in line: address_read.append(eip) else: address_write.append(eip) # Red for addr in address_write: ea = int(addr, 16) idaapi.set_item_color(ea, 0xffd2f8) # Green for addr in address_read: ea = int(addr, 16) idaapi.set_item_color(ea, 0x00ff00)
def cb_restore_last_line(self): if self.prev_loc: ea, col = self.prev_loc idaapi.set_item_color(ea, col)
def ida_apply_colors(coverage, colors): base_address = idaapi.get_imagebase() for rva, freq in coverage.items(): idaapi.set_item_color(base_address + rva, colors[freq])
def color_lines(self, start, end, color): address = idaapi.get_imagebase() + start while address < idaapi.get_imagebase() + end: idaapi.set_item_color(address, color) address += ida_bytes.get_item_size(address)