def test_minimal(self): for path in (('linux','amd64','static64.llvm.elf'), ('linux','i386','static32.llvm.elf')): logger.warn("======== %r ========", path) fn = helpers.getTestPath(*path) e = Elf.Elf(file(fn)) vw = viv_cli.VivCli() vw.loadFromFile(fn)
def test_files(self): results = [] for name, test_data, path in self.data: logger.warning("======== %r ========", name) start = time.time() fn = helpers.getTestPath(*path) vw = viv_cli.VivCli() vw.loadFromFile(fn) do_analyze(vw) logger.debug("testing %r (%r)...", name, fn) retval = self.do_file(vw, test_data, name) results.append(retval) durn = time.time() - start logger.warning( f'============= {name} took {durn} seconds ===============') self.do_check_elfplt(vw) failed = 0 for fidx, tres in enumerate(results): for testname, testdata in tres.items(): if testdata != (0, 0): failed += testdata[0] + testdata[1] fname = self.data[fidx][0] failed_old, failed_new = testdata logger.error('%s: %s: missing: %r new: %r (%r)', fname, testname, failed_old, failed_new, fname) self.assertEqual(failed, 0, msg="ELF Tests Failed (see error log)")
def remotemain(appsrv): # The "appsrv" is a remote workspace... vw = viv_cli.VivCli() vw.initWorkspaceClient(appsrv) # If we are interactive, lets turn on extended output... viv_qt_main.main(vw)
def getTestWorkspace(*paths): testdir = os.getenv('VIVTESTFILES') if not testdir: raise unittest.SkipTest('VIVTESTFILES env var not found!') fpath = os.path.join(testdir, *paths) vw = v_cli.VivCli() vw.loadFromFile(fpath) vw.analyze() return vw
def DISABLEtest_minimal(self): ''' Until we've got soe decent tests for this, all this does is prolong the test time ''' for path in (('linux','amd64','static64.llvm.elf'), ('linux','i386','static32.llvm.elf')): logger.warning("======== %r ========", path) fn = helpers.getTestPath(*path) e = Elf.Elf(open(fn, 'rb')) vw = viv_cli.VivCli() vw.loadFromFile(fn)
def test_blob(self): fn = helpers.getTestPath(*path) vw = viv_cli.VivCli() vw.config.viv.parsers.blob.arch = 'arm' vw.config.viv.parsers.blob.baseaddr = 0x200000 vw.loadFromFile(fn) vw.makeFunction(0x200001) vw.makeFunction(0x200008) self.assertEqual(vw.getFunction(0x200007), 0x200000) self.assertEqual(vw.getFunction(0x200018), 0x200008)
def snap(self, vw): ''' Checkpoint a workspace. Yields a new workspace that can be editted as the test needs, and once the context handler ends, all changes will tossed To be used with some caution, as it does create a duplicate workspace. ''' safe = v_cli.VivCli() events = list(vw.exportWorkspace()) safe.importWorkspace(events) yield safe
def test_srec(self): fn = helpers.getTestPath(*path) vw = viv_cli.VivCli() vw.config.viv.parsers.srec.arch = 'msp430' vw.loadFromFile(fn) vw.makeFunction(0x4000) self.assertEqual(vw.getFunction(0x4000), 0x4000) self.assertEqual(vw.getFunction(0x4050), 0x4000) self.assertEqual(vw.getFunction(0x4060), 0x405e) self.assertEqual(vw.getFunction(0x4068), 0x405e)
def main(): parser = argparse.ArgumentParser(prog='vivbin', usage='%(prog)s [options] <workspace|binaries...>') parser.add_argument('-M', '--module', dest='modname', default=None, action='store', help='run the file listed as an analysis module in non-gui mode and exit') parser.add_argument('-A', '--skip-analysis', dest='doanalyze', default=True, action='store_false', help='Do *not* do an initial auto-analysis pass') parser.add_argument('-B', '--bulk', dest='bulk', default=False, action='store_true', help='Do *not* start the gui, just load, analyze and save') parser.add_argument('-C', '--cprofile', dest='cprof', default=False, action='store_true', help='Output vivisect performace profiling (cProfile) info') parser.add_argument('-O', '--option', dest='option', default=None, action='store', help='<secname>.<optname>=<optval> (optval must be json syntax)') parser.add_argument('-p', '--parser', dest='parsemod', default=None, action='store', help='Manually specify the parser module (pe/elf/blob/...)') parser.add_argument('-s', '--storage', dest='storage_name', default=None, action='store', help='Specify a storage module by name') parser.add_argument('-v', '--verbose', dest='verbose', default=False, action='store_true', help='Enable verbose mode') parser.add_argument('-V', '--version', dest='version', default=None, action='store', help='Add file version (if available) to save file name') parser.add_argument('file', nargs='*') args = parser.parse_args() vw = viv_cli.VivCli() vw.verbose = args.verbose if args.option is not None: if args.option in ('-h','?'): print(vw.config.reprConfigPaths()) sys.exit(-1) try: vw.config.parseConfigOption(args.option) except e_config.ConfigNoAssignment, e: print(vw.config.reprConfigPaths() + "\n") print(e) print("syntax: \t-O <secname>.<optname>=<optval> (optval must be json syntax)") sys.exit(-1) except Exception, e: print(vw.config.reprConfigPaths()) print("With entry: %s" % args.option) print(e) sys.exit(-1)
def setUpClass(cls): super(ELFTests, cls).setUpClass() cls.tests = [] for test in data: name, test_data, path = test logger.warn("======== %r ========", name) fn = helpers.getTestPath(*path) e = Elf.Elf(file(fn)) vw = viv_cli.VivCli() vw.loadFromFile(fn) #vw.analyze() vae.analyze(vw) vagr.analyze(vw) vaeep.analyze(vw) vagp.analyze(vw) cls.tests.append((name, test_data, fn, e, vw)) cls.maxDiff = None
def _menuToolsCodeDiff(self): fname = QtGui.QFileDialog.getOpenFileName( self, 'Select Second Workspace (.viv)') if fname == None: return fname = str(fname) import vivisect.codediff as viv_codediff import vivisect.qt.codediff as vqt_codediff vw2 = viv_cli.VivCli() self.vw.vprint('Loading second workspace: %s...' % fname) vw2.loadWorkspace(fname) # Make our code diff guy... cdiff = viv_codediff.CodeDiff(self.vw, vw2) # Create the codediff view self.dview = vqt_codediff.VQCodeDiffView(cdiff, self) self.dview.show()
def main(): parser = argparse.ArgumentParser( prog='vivbin', usage='%(prog)s [options] <workspace|binaries...>') parser.add_argument( '-M', '--module', dest='modname', default=None, action='store', help= 'run the file listed as an analysis module in non-gui mode and exit') parser.add_argument('-A', '--skip-analysis', dest='doanalyze', default=True, action='store_false', help='Do *not* do an initial auto-analysis pass') parser.add_argument( '-B', '--bulk', dest='bulk', default=False, action='store_true', help='Do *not* start the gui, just load, analyze and save') parser.add_argument( '-C', '--cprofile', dest='cprof', default=False, action='store_true', help='Output vivisect performace profiling (cProfile) info') parser.add_argument( '-O', '--option', dest='option', default=None, action='store', help='<secname>.<optname>=<optval> (optval must be json syntax)') parser.add_argument( '-p', '--parser', dest='parsemod', default=None, action='store', help='Manually specify the parser module (pe/elf/blob/...)') parser.add_argument('-s', '--storage', dest='storage_name', default=None, action='store', help='Specify a storage module by name') parser.add_argument('-v', '--verbose', dest='verbose', default=False, action='count', help='Enable verbose mode (multiples matter: -vvvv)') parser.add_argument( '-V', '--version', dest='version', default=None, action='store', help='Add file version (if available) to save file name') parser.add_argument('-c', '--config', dest='config', default=None, action='store_true', help='Path to a directory to use for config data') parser.add_argument('-a', '--autosave', dest='autosave', default=False, action='store_true', help='Autosave configuration data') parser.add_argument('file', nargs='*') args = parser.parse_args() vw = viv_cli.VivCli(confdir=args.config, autosave=args.autosave) # setup logging vw.verbose = min(args.verbose, 4) logger.setLevel(loglevels[vw.verbose]) if args.option is not None: if args.option in ('-h', '?'): logger.critical(vw.config.reprConfigPaths()) sys.exit(-1) try: vw.config.parseConfigOption(args.option) except e_config.ConfigNoAssignment as e: logger.critical(vw.config.reprConfigPaths() + "\n") logger.critical(e) logger.critical( "syntax: \t-O <secname>.<optname>=<optval> (optval must be json syntax)" ) sys.exit(-1) except Exception as e: logger.critical(vw.config.reprConfigPaths()) logger.critical("With entry: %s", args.option) logger.critical(e) sys.exit(-1) if args.storage_name is not None: vw.setMeta("StorageModule", args.storage_name) # If we're not gonna load files, no analyze if args.file is None: args.doanalyze = False # Load in any additional files... needanalyze = False if args.file is not None: for fname in args.file: if args.parsemod is None: args.parsemod = viv_parsers.guessFormatFilename(fname) start = time.time() if args.parsemod == 'viv': vw.loadWorkspace(fname) else: needanalyze = True vw.loadFromFile(fname, fmtname=args.parsemod) end = time.time() logger.info('Loaded (%.4f sec) %s', (end - start), fname) if args.bulk: if args.doanalyze: if args.cprof: cProfile.run("vw.analyze()") else: start = time.time() vw.analyze() end = time.time() logger.debug("ANALYSIS TIME: %s", (end - start)) if args.modname is not None: with open(args.modname, 'rb') as f: module = imp.load_module("custom_analysis", f, args.modname, ('.py', 'U', 1)) module.analyze(vw) logger.info('stats: %r', vw.getStats()) logger.info("Saving workspace: %s", vw.getMeta('StorageName')) vw.saveWorkspace() else: import vivisect.qt.main as viv_qt_main # If we are interactive, lets turn on extended output... if args.doanalyze and needanalyze: e_threads.firethread(vw.analyze)() viv_qt_main.main(vw)
def processMem(mem=None, filename=None): if mem == None: mem = file(filename + '.mem').read() fw_l = mem.split('\n') names = [] strings = [] instrs = [] segment = [] segments = [segment] segaddrbase = [0] prevaddr = 0 prevbytelen = 0 for line in fw_l: line = line.strip() if line[:5].endswith(':'): # instruction or string addr = int(line[:4], 16) bytez = line[7:] bytezlen = len(bytez) #print " len: %s" % bytezlen if bytez.endswith('"'): # string print "STRING: " + line bytez = bytez[:-1] + '\x00' strings.append((addr, len(bytez), bytez)) elif 40 <= bytezlen <= 59 and bytez[0] == bytez[5] == bytez[ 10] == ' ': # MEMORY line bytez = bytez[1:40].replace(' ', '').decode('hex') elif bytezlen == 2: # MEMORY line of all NULL: bytez = '\0' * 16 else: # line of ASM. scraping out just the hex nbytes = '' try: for bits in bytez.split(' '): int(bits, 16) nbytes += bits #print "-=-= " + nbytes except: pass bytez = nbytes.replace(' ', '') #print repr(bytez) bytez = bytez.decode('hex') if addr != prevaddr + prevbytelen: print "New Segment: %x != %x + %x" % (addr, prevaddr, prevbytelen) segment = [] segments.append(segment) segaddrbase.append(addr) #print repr(bytez) segment.append(bytez) prevbytelen = len(bytez) prevaddr = addr elif line[:6].endswith('<'): # symbol name, function beginning name = line[6:] name = name[:name.find('>')] addr = int(line[:4], 16) print " NAME: %s = %x" % (name, addr) names.append((addr, name)) # now let's write us some ihex! ih = intelhex.IntelHex() # ihex files are broken into different segments, which we'll use # when creating our vivisect workspace. for sidx in range(len(segments)): addr = segaddrbase[sidx] segment = segments[sidx] ih.puts(addr, ''.join(segment)) # save it to a file (viv's ihex loader likes it that way) ih.tofile(filename, 'hex') # now on to populating our Vivisect Workspace # create the workspace: vw = viv_cli.VivCli() # make sure the ihex parser config settings are correct for msp430 vw.config.viv.parsers.ihex.arch = 'msp430' # now load the ihex we've created vw.loadFromFile(filename) # we've loaded up the binary, but if we've discovered any names, let's apply them here. for addr, name in names: vw.makeName(addr, name) # now we kick off "autoanalysis" vw.analyze() # and save the workspace to file vw.saveWorkspace() # now let's write us an r2 startup file with open(filename + '.r2', 'w') as r2_file: r2_file.write("e asm.arch=msp430\n") for (addr, name) in names: r2_file.write("f %s%s @ 0x%x\n" % ('' if name == 'main' else 'loc.', name, addr)) for (addr, size, bytez) in strings: r2_file.write("Cs 0x%x @0x%x\n" % (size, addr)) r2_file.write("f str.%s @ 0x%x\n" % (clean_name(bytez), addr)) # doesn't really matter that we return anything, our job is done. # this is for interactive work (go ipython!) return vw, ih, names
def getOtherWorkspace(wsname): vw = viv_cli.VivCli() vw.loadWorkspace(name) return vw
def getServerWorkspace(server, wsname): vw = v_cli.VivCli() cliproxy = VivServerClient(vw, server, wsname) vw.initWorkspaceClient(cliproxy) return vw
def main(): parser = argparse.ArgumentParser( prog='vivbin', usage='%(prog)s [options] <workspace|binaries...>') parser.add_argument( '-M', '--module', dest='modname', default=None, action='store', help= 'run the file listed as an analysis module in non-gui mode and exit') parser.add_argument('-A', '--skip-analysis', dest='doanalyze', default=True, action='store_false', help='Do *not* do an initial auto-analysis pass') parser.add_argument( '-B', '--bulk', dest='bulk', default=False, action='store_true', help='Do *not* start the gui, just load, analyze and save') parser.add_argument( '-C', '--cprofile', dest='cprof', default=False, action='store_true', help='Output vivisect performace profiling (cProfile) info') parser.add_argument( '-O', '--option', dest='option', default=None, action='store', help='<secname>.<optname>=<optval> (optval must be json syntax)') parser.add_argument( '-p', '--parser', dest='parsemod', default=None, action='store', help='Manually specify the parser module (pe/elf/blob/...)') parser.add_argument('-s', '--storage', dest='storage_name', default=None, action='store', help='Specify a storage module by name') parser.add_argument('-v', '--verbose', dest='verbose', default=False, action='store_true', help='Enable verbose mode') parser.add_argument( '-V', '--version', dest='version', default=None, action='store', help='Add file version (if available) to save file name') parser.add_argument('file', nargs='*') args = parser.parse_args() vw = viv_cli.VivCli() vw.verbose = args.verbose if args.option is not None: vw.config.parseConfigOption(args.option) if args.storage_name is not None: vw.setMeta("StorageModule", args.storage_name) # If we're not gonna load files, no analyze if args.file is None: args.doanalyze = False # Load in any additional files... needanalyze = False if args.file is not None: for fname in args.file: if args.parsemod == None: args.parsemod = viv_parsers.guessFormatFilename(fname) start = time.time() if args.parsemod == 'viv': vw.loadWorkspace(fname) else: needanalyze = True vw.loadFromFile(fname, fmtname=args.parsemod) end = time.time() print('Loaded (%.4f sec) %s' % (end - start, fname)) if args.bulk: if args.doanalyze: if args.cprof: cProfile.run("vw.analyze()") else: start = time.time() vw.analyze() end = time.time() print "ANALYSIS TIME: %s" % (end - start) if args.modname is not None: module = imp.load_module("custom_analysis", file(modname, "rb"), modname, ('.py', 'U', 1)) module.analyze(vw) print('stats: %r' % (vw.getStats(), )) print("Saving workspace: %s" % (vw.getMeta('StorageName'))) vw.saveWorkspace() else: import vivisect.qt.main as viv_qt_main # If we are interactive, lets turn on extended output... vw.verbose = True if args.doanalyze and needanalyze: e_threads.firethread(vw.analyze)() viv_qt_main.main(vw)
@vq_main.idlethread def runqt(vw, closeme=None): ''' Use this API to instantiate a QT main window and show it when there is already a main thread running... ''' mw = VQVivMainWindow(vw) viv_extensions.loadExtensions(vw, mw) mw.show() if closeme: closeme.close() return mw def main(vw): vq_main.startup(css=vq_colors.qt_matrix) mw = VQVivMainWindow(vw) viv_extensions.loadExtensions(vw, mw) mw.show() vq_main.main() if __name__ == '__main__': vw = viv_cli.VivCli() if len(sys.argv) == 2: vw.loadWorkspace(sys.argv[1]) main(vw)
def setUpClass(cls): super(PETests, cls).setUpClass() cls.psexec_fn = helpers.getTestPath('windows', 'i386', 'PsExec.exe') cls.vw_psexec = viv_cli.VivCli() cls.vw_psexec.loadFromFile(cls.psexec_fn) cls.vw_psexec.analyze()