def _hotkey_paintDown(self, va=None): ''' Paint the VA's from the selected basic block down to all possible non-looping blocks. This is valuable for determining what code can execute from any starting basic block, without a loop. ''' #TODO: make overlapping colors available for multiple paintings graph = viv_graphutil.buildFunctionGraph(self.vw, self.fva, revloop=True) startva = self.mem_canvas._canv_curva if startva == None: return viv_graphutil.preRouteGraphDown(graph, startva, mark='hit') count = 0 colormap = {} for node in graph.getNodesByProp('hit'): count += 1 off = 0 cbsize = node[1].get('cbsize') if cbsize == None: raise Exception('node has no cbsize: %s' % repr(node)) # step through opcode for a node while off < cbsize: op = self.vw.parseOpcode(node[0] + off) colormap[op.va] = 'brown' off += len(op) self.vw.vprint("Colored Blocks: %d" % count) vqtevent('viv:colormap', colormap) return colormap
def _hotkey_paintMerge(self, va=None): ''' same as paintdown but only until the graph remerges ''' graph = viv_graphutil.buildFunctionGraph(self.vw, self.fva, revloop=True) startva = self.mem_canvas._canv_curva if startva == None: return viv_graphutil.findRemergeDown(graph, startva) count = 0 colormap = {} for node in graph.getNodesByProp('hit'): count += 1 off = 0 cbsize = node[1].get('cbsize') if cbsize == None: raise Exception('node has no cbsize: %s' % repr(node)) # step through opcode for a node while off < cbsize: op = self.vw.parseOpcode(node[0] + off) colormap[op.va] = 'brown' off += len(op) self.vw.vprint("Colored Blocks: %d" % count) vqtevent('viv:colormap', colormap) return colormap
def _hotkey_paintDown(self, va=None): """ Paint the VA's from the selected basic block down to all possible non-looping blocks. This is valuable for determining what code can execute from any starting basic block, without a loop. """ # TODO: make overlapping colors available for multiple paintings graph = viv_graphutil.buildFunctionGraph(self.vw, self.fva, revloop=True) startva = self.mem_canvas._canv_curva if startva == None: return viv_graphutil.preRouteGraphDown(graph, startva, mark="hit") count = 0 colormap = {} for node in graph.getNodesByProp("hit"): count += 1 off = 0 cbsize = node[1].get("cbsize") if cbsize == None: raise Exception("node has no cbsize: %s" % repr(node)) # step through opcode for a node while off < cbsize: op = self.vw.parseOpcode(node[0] + off) colormap[op.va] = "brown" off += len(op) self.vw.vprint("Colored Blocks: %d" % count) vqtevent("viv:colormap", colormap) return colormap
def _hotkey_paintUp(self, va=None): ''' Paint the VA's from the selected basic block up to all possible non-looping starting points. ''' graph = viv_graphutil.buildFunctionGraph(self.vw, self.fva, revloop=True) startva = self.mem_canvas._canv_curva if startva == None: return viv_graphutil.preRouteGraphUp(graph, startva, mark='hit') count = 0 colormap = {} for node in graph.getNodesByProp('hit'): count += 1 off = 0 cbsize = node[1].get('cbsize') if cbsize == None: raise Exception('node has no cbsize: %s' % repr(node)) # step through opcode for a node while off < cbsize: op = self.vw.parseOpcode(node[0] + off) colormap[op.va] = 'orange' off += len(op) self.vw.vprint("Colored Blocks: %d" % count) vqtevent('viv:colormap', colormap) return colormap
def _hotkey_paintMerge(self, va=None): """ same as paintdown but only until the graph remerges """ graph = viv_graphutil.buildFunctionGraph(self.vw, self.fva, revloop=True) startva = self.mem_canvas._canv_curva if startva == None: return viv_graphutil.findRemergeDown(graph, startva) count = 0 colormap = {} for node in graph.getNodesByProp("hit"): count += 1 off = 0 cbsize = node[1].get("cbsize") if cbsize == None: raise Exception("node has no cbsize: %s" % repr(node)) # step through opcode for a node while off < cbsize: op = self.vw.parseOpcode(node[0] + off) colormap[op.va] = "brown" off += len(op) self.vw.vprint("Colored Blocks: %d" % count) vqtevent("viv:colormap", colormap) return colormap
def _hotkey_paintUp(self, va=None): """ Paint the VA's from the selected basic block up to all possible non-looping starting points. """ graph = viv_graphutil.buildFunctionGraph(self.vw, self.fva, revloop=True) startva = self.mem_canvas._canv_curva if startva == None: return viv_graphutil.preRouteGraphUp(graph, startva, mark="hit") count = 0 colormap = {} for node in graph.getNodesByProp("hit"): count += 1 off = 0 cbsize = node[1].get("cbsize") if cbsize == None: raise Exception("node has no cbsize: %s" % repr(node)) # step through opcode for a node while off < cbsize: op = self.vw.parseOpcode(node[0] + off) colormap[op.va] = "orange" off += len(op) self.vw.vprint("Colored Blocks: %d" % count) vqtevent("viv:colormap", colormap) return colormap
def _finishFuncRender(self, data): ''' Update the window title and emit the renderDoneSignal so other things can run that are sitting on that signal ''' addr = self.updateWindowTitle() if addr is not None: vqtevent('viv:colormap', {addr: 'orange'}) self._renderDoneSignal.emit()
def _renderMemory(self): try: expr = str(self.addr_entry.text()) if not expr: return try: addr = self.vw.parseExpression(expr) except Exception as e: self.mem_canvas.addText('Invalid Address: %s (%s)' % (expr, e)) return # get a location anchor if one exists, otherwise, we may end up in no-man's land, # since we rely on labels, which only exist for the base of a location. loc = self.vw.getLocation(addr) if loc is not None: addr = loc[L_VA] # check if we're already rendering this function. if so, just scroll to addr fva = self.vw.getFunction(addr) if fva is None: self.vw.vprint('0x%.8x is not in a function!' % addr) return if fva == self.fva: self.mem_canvas.page().mainFrame().scrollToAnchor( 'viv:0x%.8x' % addr) vqtevent('viv:colormap', {addr: 'orange'}) self.updateWindowTitle() return # if we're rendering a different function, get to work! self.clearText() self.renderFunctionGraph(fva) self.mem_canvas.page().mainFrame().scrollToAnchor('viv:0x%.8x' % addr) self.updateWindowTitle() self.mem_canvas.page().mainFrame().scrollToAnchor('viv:0x%.8x' % addr) vqtevent('viv:colormap', {addr: 'orange'}) self.updateWindowTitle() self._renderDoneSignal.emit() except Exception as e: self.vw.vprint('_renderMemory hit exception: %s' % str(e)) self.vw.vprint('%s' % traceback.format_exc())
# only want one listing of each va, no matter how many times it matches if addthis: res.append(va) except: self.vprint(''.join(traceback.format_exception(*sys.exc_info()))) if len(res) == 0: self.vprint('pattern not found: %s (%s)' % (pattern.encode('hex'), repr(pattern))) return # set the color for each finding color = options.markColor colormap = { va : color for va in res } if self._viv_gui != None: vqtevent('viv:colormap', colormap) self.vprint('matches for: %s (%s)' % (pattern.encode('hex'), repr(pattern))) for va in res: mbase,msize,mperm,mfile = self.memobj.getMemoryMap(va) pname = e_mem.reprPerms(mperm) sname = self.reprPointer(va) op = self.parseOpcode(va) self.canvas.renderMemory(va, len(op)) cmt = self.getComment(va) if cmt != None: self.canvas.addText('\t\t; %s' % cmt) self.canvas.addText('\n')
def do_searchopcodes(self, line): ''' search opcodes/function for a pattern searchopcodes [-f <funcva>] [options] <pattern> -f [fva] - focus on one function -c - search comments -o - search operands -t - search text -M <color> - mark opcodes (default = orange) -R - pattern is REGEX (otherwise just text) ''' parser = e_cli.VOptionParser() parser.add_option('-f', action='store', dest='funcva', type='int') parser.add_option('-c', action='store_true', dest='searchComments') parser.add_option('-o', action='store_true', dest='searchOperands') parser.add_option('-t', action='store_true', dest='searchText') parser.add_option('-M', action='store', dest='markColor', default='orange') parser.add_option('-R', action='store_true', dest='is_regex') argv = shlex.split(line) try: options, args = parser.parse_args(argv) except Exception as e: self.vprint(repr(e)) return self.do_help('searchopcodes') pattern = ' '.join(args) if len(pattern) == 0: self.vprint('you must specify a pattern') return self.do_help('searchopcodes') # generate our interesting va list valist = [] if options.funcva: # setup valist from function data try: fva = options.funcva graph = viv_graph.buildFunctionGraph(self, fva) except Exception as e: self.vprint(repr(e)) return for nva, node in graph.getNodes(): va = nva endva = va + node.get('cbsize') while va < endva: lva, lsz, ltype, ltinfo = self.getLocation(va) valist.append(va) va += lsz else: # the whole workspace is our oyster valist = [ va for va, lvsz, ltype, ltinfo in self.getLocations(LOC_OP) ] res = [] canv = e_canvas.StringMemoryCanvas(self) defaultSearchAll = True for va in valist: try: addthis = False op = self.parseOpcode(va) # search comment if options.searchComments: defaultSearchAll = False cmt = self.getComment(va) if cmt is not None: if options.is_regex: if len(re.findall(pattern, cmt)): addthis = True else: if pattern in cmt: addthis = True # search operands if options.searchOperands: defaultSearchAll = False for opidx, oper in enumerate(op.opers): # we're writing to a temp canvas, so clear it before each test canv.clearCanvas() oper = op.opers[opidx] oper.render(canv, op, opidx) operepr = canv.strval if options.is_regex: if len(re.findall(pattern, operepr)): addthis = True else: if pattern in operepr: addthis = True # if we're doing non-regex, let's test against real numbers # (instead of converting to hex and back) numpattrn = pattern try: numpattrn = int(numpattrn, 0) except: pass if numpattrn in vars(oper).values(): addthis = True # search full text if options.searchText or defaultSearchAll: # search through the rendering of the opcode, as well as the comment canv.clearCanvas() op.render(canv) oprepr = canv.strval cmt = self.getComment(va) if cmt is not None: oprepr += " ; " + cmt if options.is_regex: if len(re.findall(pattern, oprepr)): addthis = True else: if pattern in oprepr: addthis = True # only want one listing of each va, no matter how many times it matches if addthis: res.append(va) except: self.vprint(''.join( traceback.format_exception(*sys.exc_info()))) if len(res) == 0: self.vprint('pattern not found: %s (%s)' % (pattern.encode('utf-8').hex(), repr(pattern))) return # set the color for each finding color = options.markColor colormap = {va: color for va in res} if self._viv_gui is not None: from vqt.main import vqtevent vqtevent('viv:colormap', colormap) self.vprint('matches for: %s (%s)' % (pattern.encode('utf-8').hex(), repr(pattern))) for va in res: mbase, msize, mperm, mfile = self.memobj.getMemoryMap(va) pname = e_memory.reprPerms(mperm) sname = self.reprPointer(va) op = self.parseOpcode(va) self.canvas.renderMemory(va, len(op)) cmt = self.getComment(va) if cmt is not None: self.canvas.addText('\t\t; %s (Perms: %s, Smartname: %s)' % (cmt, pname, sname)) self.canvas.addText('\n') self.vprint('done (%d results).' % len(res))
def _renderedSameFva(self, data): addr = self.updateWindowTitle() if addr is not None: vqtevent('viv:colormap', {addr: 'orange'})
def _finishFuncRender(self, data): addr = self.updateWindowTitle() if addr is not None: vqtevent('viv:colormap', {addr: 'orange'}) self._renderDoneSignal.emit()