def do_pathcount(self, line): ''' Mostly for testing the graph stuff... this will likely be removed. (does not count paths with loops currently...) Usage: pathcount <func_expr> ''' if not line: return self.do_help('pathcount') try: fva = self.parseExpression(line) if not self.isFunction(fva): self.vprint('Not a function!') return except Exception as e: self.vprint(str(e)) return g = v_t_graph.buildFunctionGraph(self, fva) pathcnt = 0 for path in v_t_graph.getCodePaths(g): self.vprint('Path through 0x%.8x: %s' % (fva, [hex(p[0]) for p in path])) pathcnt += 1 self.vprint('Total Paths: %d' % pathcnt)
def renderSymbolikPaths(self): try: self.memcanvas.clearCanvas() exprtxt = str(self.exprtext.text()) if not exprtxt: return exprparts = exprtxt.split(';') expr = exprparts[0] preeff = [] precons = [] for e in exprparts[1:]: s = self.symexpr.parseExpression(e) if isinstance(s, viv_sym_constraints.Constraint): precons.append(s) continue if isinstance(s, viv_sym_effects.SymbolikEffect): preeff.append(s) continue raise Exception('Unhandled Symbolik Expression: %s' % e) self.symctx.setSymPreEffects(preeff) self.symctx.setSymPreConstraints(precons) va = self.vw.parseExpression(expr) self.fva = self.vw.getFunction(va) if self.fva == None: raise Exception('Invalid Address: 0x%.8x' % va) # check the constraints codepaths = None codegraph = self.symctx.getSymbolikGraph(self.fva) cexpr = str(self.constraintext.text()) if cexpr: cva = self.vw.parseExpression(cexpr) ccb = self.vw.getCodeBlock(cva) if ccb != None and ccb in self.vw.getFunctionBlocks(self.fva): codepaths = viv_graph.getCodePathsThru( codegraph, ccb[0], loopcnt=3 ) #FIXME: allow the GUI-setting of loopcnt, instead of hard-coding if codepaths == None: codepaths = viv_graph.getCodePaths(codegraph, 3) #paths = self.symctx.getSymbolikPaths(self.fva, paths=codepaths, maxpath=100) paths = self.symctx.walkSymbolikPaths(self.fva, maxpath=100) self.pathview.loadSymbolikPaths(paths) except Exception, e: traceback.print_exc() self.memcanvas.addText('ERROR: %s' % e)
def renderSymbolikPaths(self): try: self.memcanvas.clearCanvas() exprtxt = str(self.exprtext.text()) if not exprtxt: return exprparts = exprtxt.split(';') expr = exprparts[0] preeff = [] precons = [] for e in exprparts[1:]: s = self.symexpr.parseExpression(e) if isinstance(s, viv_sym_constraints.Constraint): precons.append(s) continue if isinstance(s, viv_sym_effects.SymbolikEffect): preeff.append(s) continue raise Exception('Unhandled Symbolik Expression: %s' % e) self.symctx.setSymPreEffects(preeff) self.symctx.setSymPreConstraints(precons) va = self.vw.parseExpression(expr) self.fva = self.vw.getFunction(va) if self.fva == None: raise Exception('Invalid Address: 0x%.8x' % va ) # check the constraints codepaths = None codegraph = self.symctx.getSymbolikGraph(self.fva) cexpr = str(self.constraintext.text()) if cexpr: cva = self.vw.parseExpression(cexpr) ccb = self.vw.getCodeBlock(cva) if ccb != None and ccb in self.vw.getFunctionBlocks(self.fva): codepaths = viv_graph.getCodePathsThru(codegraph, ccb[0], loopcnt=3) #FIXME: allow the GUI-setting of loopcnt, instead of hard-coding if codepaths == None: codepaths = viv_graph.getCodePaths(codegraph, 3) #paths = self.symctx.getSymbolikPaths(self.fva, paths=codepaths, maxpath=100) paths = self.symctx.walkSymbolikPaths(self.fva, maxpath=100) self.pathview.loadSymbolikPaths(paths) except Exception, e: traceback.print_exc() self.memcanvas.addText('ERROR: %s' % e)
def test_graphutil_getcodepaths(self): ''' In this function, order doesn't matter ''' vw = self.gcc_vw g = v_t_graphutil.buildFunctionGraph(vw, 0x456190) paths = [ set([0x456190, 0x4561ba, 0x456202, 0x456216, 0x45621c, 0x456240, 0x4561fa, 0x456242]), set([0x456190, 0x4561ba, 0x456202, 0x456216, 0x45621c, 0x40aa97, 0x4561ea, 0x4561ef, 0x4561fa, 0x456242]), set([0x456190, 0x4561ba, 0x456202, 0x456216, 0x45621c, 0x40aa97, 0x4561ea, 0x4561fa, 0x456242]), set([0x456190, 0x4561ba, 0x456202, 0x456216, 0x4561c2, 0x4561d0, 0x4561ea, 0x4561ef, 0x4561fa, 0x456242]), set([0x456190, 0x4561ba, 0x456202, 0x456216, 0x4561c2, 0x4561d0, 0x4561ea, 0x4561fa, 0x456242]), set([0x456190, 0x4561ba, 0x456202, 0x456216, 0x4561c2, 0x40aa85, 0x40aa8d, 0x4561d0, 0x4561ea, 0x4561ef, 0x4561fa, 0x456242]), set([0x456190, 0x4561ba, 0x456202, 0x456216, 0x4561c2, 0x40aa85, 0x40aa8d, 0x4561d0, 0x4561ea, 0x4561fa, 0x456242]), set([0x456190, 0x4561ba, 0x456202, 0x456216, 0x4561c2, 0x40aa85, 0x40aab9, 0x456242]), set([0x456190, 0x4561ba, 0x456202, 0x45621c, 0x456240, 0x4561fa, 0x456242]), set([0x456190, 0x4561ba, 0x456202, 0x45621c, 0x40aa97, 0x4561ea, 0x4561ef, 0x4561fa, 0x456242]), set([0x456190, 0x4561ba, 0x456202, 0x45621c, 0x40aa97, 0x4561ea, 0x4561fa, 0x456242]), set([0x456190, 0x456242]), ] pathcount = 0 genr = v_t_graphutil.getCodePaths(g, loopcnt=0, maxpath=None) for path in genr: p = set(map(lambda k: k[0], path)) self.assertIn(p, paths) pathcount += 1 self.assertEqual(12, pathcount) g = v_t_graphutil.buildFunctionGraph(vw, vw.getFunction(0x0041a766)) thruCnt = glen(v_t_graphutil.getCodePathsThru(g, 0x0041a766)) self.assertEqual(2, thruCnt) thruCnt = glen(v_t_graphutil.getCodePathsThru(g, 0x0041a766, maxpath=1)) self.assertEqual(1, thruCnt) # this will not be true for all examples, but for this function it is g = v_t_graphutil.buildFunctionGraph(vw, vw.getFunction(0x0041a77d)) toCnt = glen(v_t_graphutil.getCodePathsTo(g, 0x0041a77d)) self.assertEqual(2, toCnt) toCnt = glen(v_t_graphutil.getCodePathsTo(g, 0x0041a77d, maxpath=99)) self.assertEqual(2, toCnt) g = v_t_graphutil.buildFunctionGraph(vw, vw.getFunction(0x004042eb)) fromCnt = glen(v_t_graphutil.getCodePathsFrom(g, 0x004042eb)) self.assertEqual(8, fromCnt) fromCnt = glen(v_t_graphutil.getCodePathsFrom(g, 0x004042eb, maxpath=3)) self.assertEqual(3, fromCnt)
def test_graphutil_getcodepaths(self): ''' In this function, order doesn't matter ''' vw = self.firefox_vw g = v_t_graphutil.buildFunctionGraph(vw, 0x140010e60) paths = [ set([5368778336, 5368778350, 5368778362, 5368778366, 5368778394, 5368778400]), set([5368778336, 5368778350, 5368778362, 5368778366, 5368778498, 5368778515, 5368778394, 5368778400]), set([5368778336, 5368778350, 5368778362, 5368778366, 5368778498, 5368778520, 5368778544, 5368778549]), set([5368778336, 5368778350, 5368778362, 5368778366, 5368778498, 5368778520, 5368778544, 5368778601, 5368778603]), set([5368778336, 5368778350, 5368778362, 5368778366, 5368778498, 5368778520, 5368778560, 5368778603]), set([5368778336, 5368778350, 5368778482, 5368778366, 5368778394, 5368778400]), set([5368778336, 5368778350, 5368778482, 5368778366, 5368778498, 5368778515, 5368778394, 5368778400]), set([5368778336, 5368778350, 5368778482, 5368778366, 5368778498, 5368778520, 5368778544, 5368778549]), set([5368778336, 5368778350, 5368778482, 5368778366, 5368778498, 5368778520, 5368778544, 5368778601, 5368778603]), set([5368778336, 5368778350, 5368778482, 5368778366, 5368778498, 5368778520, 5368778560, 5368778603]), set([5368778336, 5368778400]), ] pathcount = 0 genr = v_t_graphutil.getCodePaths(g, loopcnt=0, maxpath=None) for path in genr: p = set([k[0] for k in path]) self.assertIn(p, paths) pathcount += 1 self.assertEqual(11, pathcount) g = v_t_graphutil.buildFunctionGraph(vw, vw.getFunction(0x1400110a0)) thruCnt = glen(v_t_graphutil.getCodePathsThru(g, 0x1400110a0)) self.assertEqual(23, thruCnt) thruCnt = glen(v_t_graphutil.getCodePathsThru(g, 0x1400110a0, maxpath=2)) self.assertEqual(2, thruCnt) g = v_t_graphutil.buildFunctionGraph(vw, vw.getFunction(0x14001ead0)) toCnt = glen(v_t_graphutil.getCodePathsTo(g, 0x14001ec2a)) self.assertEqual(2, toCnt) toCnt = glen(v_t_graphutil.getCodePathsTo(g, 0x14001ec2a, maxpath=99)) self.assertEqual(2, toCnt) g = v_t_graphutil.buildFunctionGraph(vw, vw.getFunction(0x1400019ab)) fromCnt = glen(v_t_graphutil.getCodePathsFrom(g, 0x1400019ab)) self.assertEqual(2, fromCnt) fromCnt = glen(v_t_graphutil.getCodePathsFrom(g, 0x1400019ab, maxpath=1)) self.assertEqual(1, fromCnt)
def getSymbolikPaths(self, fva, paths=None, args=None, maxpath=1000, graph=None): ''' For each path through the function, run all symbolik effects in an emulator instance and yield emu, effects tuples... ''' if graph is None: graph = self.getSymbolikGraph(fva) if args is None: argdef = self.vw.getFunctionArgs(fva) args = [Arg(i, width=self.vw.psize) for i in range(len(argdef))] if paths is None: paths = viv_graph.getCodePaths(graph, maxpath=maxpath) pcnt = 0 for path in paths: if pcnt > maxpath: break pcnt += 1 skippath = False emu = self.getFuncEmu(fva, fargs=args) for fname, funccb in self.funccb.items(): emu.addFunctionCallback(fname, funccb) opcodes = [] patheffects = emu.applyEffects(self.preeffects) for nid, eid in path: # This is the edge that *got us here* so it has to # be processed first! if eid is not None: constraints = graph.getEdgeProps(eid).get('symbolik_constraints', ()) constraints = emu.applyEffects(constraints) # print 'EDGE GOT CONSTRAINTS',[ str(c) for c in constraints] # FIXME check if constraints are discrete, and possibly skip path! # FIXME: if constraints are Const vs Const, and one Const is a loop var, don't skip! if self.consolve: # If any of the constraints are discrete and false we skip the path [c.reduce() for c in constraints] discs = [c.cons._solve() for c in constraints if c.cons.isDiscrete()] # print 'CONS',constraints # print 'DISCS',discs if not all(discs): # emtpy discs is True... # print('SKIP: %s %s' % (repr(discs),[str(c) for c in constraints ])) skippath = True break # reduce/remove constraints that were discrete and passed constraints = [c for c in constraints if not c.cons.isDiscrete()] patheffects += constraints if skippath: break patheffects += emu.applyEffects(graph.getNodeProps(nid).get('symbolik_effects', ())) opcodes += graph.getNodeProps(nid).get('opcodes', ()) if not skippath: # Store off some info into emu meta for analysis to use emu.setMeta('opcodes', opcodes) yield emu, patheffects
def getSymbolikPaths(self, fva, paths=None, args=None, maxpath=1000): ''' For each path through the function, run all symbolik effects in an emulator instance and yield emu, effects tuples... ''' graph = self.getSymbolikGraph(fva) if args == None: argdef = self.vw.getFunctionArgs( fva ) args = [ Arg(i, width=self.vw.psize) for i in xrange(len(argdef)) ] if paths == None: paths = viv_graph.getCodePaths(graph, maxpath=maxpath) pcnt = 0 for path in paths: if pcnt > maxpath: break pcnt+=1 skippath = False emu = self.getFuncEmu(fva, fargs=args) for fname, funccb in self.funccb.items(): emu.addFunctionCallback(fname, funccb) opcodes = [] patheffects = emu.applyEffects(self.preeffects) pathconstraints = emu.applyEffects(self.preconstraints) for nid, eid in path: # This is the edge that *got us here* so it has to # be processed first! if eid != None: constraints = graph.getEdgeProps(eid).get('symbolik_constraints', ()) constraints = emu.applyEffects(constraints) #[ c.reduce() for c in constraints ] #print 'EDGE GOT CONSTRAINTS',[ str(c) for c in constraints] # FIXME check if constraints are discrete, and possibly skip path! # FIXME: if constraints are Const vs Const, and one Const is a loop var, don't skip! cons = [ c.cons for c in constraints ] if self.consolve: # If any of the constraints are discrete and false we skip the path [ c.reduce() for c in constraints ] discs = [ c.cons.prove() for c in constraints if c.cons.isDiscrete() ] #print 'CONS',constraints #print 'DISCS',discs if not all( discs ): # emtpy discs is True... #print('SKIP: %s %s' % (repr(discs),[str(c) for c in constraints ])) skippath = True break # reduce/remove constraints that were discrete and passed constraints = [ c for c in constraints if not c.cons.isDiscrete() ] cons = [ c.cons for c in constraints ] patheffects.extend(constraints) pathconstraints.extend( cons ) if skippath: break effects = emu.applyEffects( graph.getNodeProps(nid).get('symbolik_effects',()) ) patheffects.extend(effects) opcodes.extend( graph.getNodeProps(nid).get('opcodes',() ) ) if not skippath: # Store off some info into emu meta for analysis to use emu.setMeta('opcodes', opcodes) yield emu, patheffects
def checkGetCodePaths(self, vw, fva): graph = viv_graph.buildFunctionGraph(vw, fva) paths = [path for path in viv_graph.getCodePaths(graph)] self.codepaths = paths self.assertGreater(len(self.codepaths), 150)
def test_graphutil_getcodepaths(self): ''' In this function, order doesn't matter ''' vw = self.firefox_vw g = v_t_graphutil.buildFunctionGraph(vw, 0x140010e60) paths = [ set([ 0x140010e60, 0x140010e6e, 0x140010e7a, 0x140010e7e, 0x140010e9a, 0x140010ea0 ]), set([ 0x140010e60, 0x140010e6e, 0x140010e7a, 0x140010e7e, 0x140010e9a, 0x140010ea0, 0x140010f02, 0x140010f13 ]), set([ 0x140010e60, 0x140010e6e, 0x140010e7a, 0x140010e7e, 0x140010f02, 0x140010f18 ]), set([ 0x140010e60, 0x140010e6e, 0x140010e7e, 0x140010e9a, 0x140010ea0, 0x140010ef2 ]), set([ 0x140010e60, 0x140010e6e, 0x140010e7e, 0x140010e9a, 0x140010ea0, 0x140010ef2, 0x140010f02, 0x140010f13 ]), set([ 0x140010e60, 0x140010e6e, 0x140010e7e, 0x140010ef2, 0x140010f02, 0x140010f18 ]), set([0x140010e60, 0x140010ea0]), ] pathcount = 0 genr = v_t_graphutil.getCodePaths(g, loopcnt=0, maxpath=None) for path in genr: p = set([k[0] for k in path]) self.assertIn(p, paths) pathcount += 1 self.assertEqual(7, pathcount) g = v_t_graphutil.buildFunctionGraph(vw, vw.getFunction(0x1400110a0)) thruCnt = glen(v_t_graphutil.getCodePathsThru(g, 0x1400110a0)) self.assertEqual(21, thruCnt) thruCnt = glen( v_t_graphutil.getCodePathsThru(g, 0x1400110a0, maxpath=2)) self.assertEqual(2, thruCnt) g = v_t_graphutil.buildFunctionGraph(vw, vw.getFunction(0x14001ead0)) toCnt = glen(v_t_graphutil.getCodePathsTo(g, 0x14001ec2a)) self.assertEqual(2, toCnt) toCnt = glen(v_t_graphutil.getCodePathsTo(g, 0x14001ec2a, maxpath=99)) self.assertEqual(2, toCnt) g = v_t_graphutil.buildFunctionGraph(vw, vw.getFunction(0x1400019ab)) fromCnt = glen(v_t_graphutil.getCodePathsFrom(g, 0x1400019ab)) self.assertEqual(2, fromCnt) fromCnt = glen( v_t_graphutil.getCodePathsFrom(g, 0x1400019ab, maxpath=1)) self.assertEqual(1, fromCnt)
def checkGetCodePaths(self, vw, fva): graph = viv_graph.buildFunctionGraph(vw, fva ) paths = [ path for path in viv_graph.getCodePaths(graph) ] self.codepaths = paths self.assertGreater(len(self.codepaths), 150)
def getSymbolikPaths(self, fva, paths=None, args=None, maxpath=1000): ''' For each path through the function, run all symbolik effects in an emulator instance and yield emu, effects tuples... ''' graph = self.getSymbolikGraph(fva) if args == None: argdef = self.vw.getFunctionArgs( fva ) args = [ Arg(i, width=self.vw.psize) for i in xrange(len(argdef)) ] if paths == None: paths = viv_graph.getCodePaths(graph, maxpath=maxpath) #fva = graph.getMeta('fva') # put in place by buildFunctionGraph... pcnt = 0 for path in paths: if pcnt > maxpath: break pcnt+=1 skippath = False emu = self.getFuncEmu(fva, fargs=args) for fname, funccb in self.funccb.items(): emu.addFunctionCallback(fname, funccb) opcodes = [] patheffects = [] pathconstraints = [] for node, edge in path: # This is the edge that *got us here* so it has to # be processed first! if edge != None: constraints = graph.getEdgeInfo(edge, 'symbolik_constraints', ()) constraints = emu.applyEffects(constraints) #[ c.reduce() for c in constraints ] #print 'EDGE GOT CONSTRAINTS',[ str(c) for c in constraints] # FIXME check if constraints are discrete, and possibly skip path! cons = [ c.cons for c in constraints ] if self.consolve: # If any of the constraints are discrete and false we skip the path discs = [ c.cons.prove() for c in constraints if c.cons.isDiscrete() ] if not all( discs ): # emtpy discs is True... #print('SKIP: %s %s' % (repr(discs),[str(c) for c in constraints ])) skippath = True break #if not self._isSat( pathconstraints , cons): #print('NON SAT: 0x%.8x %s %s' % (node, [ str(c) for c in pathconstraints ], [ str(c) for c in cons ] )) #skippath = True #break patheffects.extend(constraints) pathconstraints.extend( cons ) if skippath: break effects = graph.getNodeInfo(node, 'symbolik_effects', ()) effects = emu.applyEffects(effects) patheffects.extend(effects) opcodes.extend( graph.getNodeInfo( node, 'opcodes' ) ) if not skippath: # Store off some info into emu meta for analysis to use emu.setMeta('opcodes', opcodes) yield emu, patheffects