def size_cluster(self): db = Database() samples = db.find(key='all') cluster = {} for sample in samples: sample_path = get_sample_path(sample.sha256) if not os.path.exists(sample_path): continue try: cur_size = os.path.getsize(sample_path) except Exception as e: self.log('error', "Error {0} for sample {1}".format(e, sample.sha256)) continue if cur_size not in cluster: cluster[cur_size] = [] cluster[cur_size].append([sample.md5, sample.name]) for cluster_name, cluster_members in cluster.items(): # Skipping clusters with only one entry. if len(cluster_members) == 1: continue self.log('info', "Cluster size {0} with {1} elements".format(bold(cluster_name), len(cluster_members))) self.log('table', dict(header=['MD5', 'Name'], rows=cluster_members))
def run(self): super(Strings, self).run() if self.args is None: return if not (self.args.all or self.args.files or self.args.hosts or self.args.network or self.args.interesting): self.log('error', 'At least one of the parameters is required') self.usage() return if self.args.scan: db = Database() samples = db.find(key='all') for sample in samples: sample_path = get_sample_path(sample.sha256) strings = self.get_strings(File(sample_path)) self.process_strings(strings, sample.name) else: if not __sessions__.is_set(): self.log('error', "No open session") return if os.path.exists(__sessions__.current.file.path): strings = self.get_strings(__sessions__.current.file) self.process_strings(strings)
def run(self, *args): try: args = self.parser.parse_args(args) except SystemExit: return if not __sessions__.is_set(): self.log('error', "No open session. This command expects a file to be open.") return if not __project__.name: src_project = "default" else: src_project = __project__.name db = Database() db.copied_id_sha256 = [] res = db.copy(__sessions__.current.file.id, src_project=src_project, dst_project=args.project, copy_analysis=True, copy_notes=True, copy_tags=True, copy_children=args.children) if args.delete: __sessions__.close() for item_id, item_sha256 in db.copied_id_sha256: db.delete_file(item_id) os.remove(get_sample_path(item_sha256)) self.log('info', "Deleted: {}".format(item_sha256)) if res: self.log('success', "Successfully copied sample(s)") return True else: self.log('error', "Something went wrong") return False
def logo(): print(""" _ (_) _ _ _ ____ _____ ____ | | | | | _ \| ___ |/ ___) \ V /| | |_| | ____| | \_/ |_| __/|_____)_| v1.3-dev |_| """) db = Database() count = db.get_sample_count() # Handle the New database format try: db.find('all', None) except: print_error("You need to update your viper database. Run 'python update.py -d'") sys.exit() if __project__.name: name = __project__.name else: name = 'default' print(magenta("You have " + bold(count)) + magenta(" files in your " + bold(name) + magenta(" repository".format(bold(name))))) if cfg.autorun.enabled and len(cfg.autorun.commands) == 0: print_warning("You have enabled autorun but not set any commands in viper.conf.")
def url_download(): url = request.forms.get('url') tags = request.forms.get('tag_list') tags = "url,"+tags if request.forms.get("tor"): upload = network.download(url,tor=True) else: upload = network.download(url,tor=False) if upload == None: return template('error.tpl', error="server can't download from URL") # Set Project project = 'Main' db = Database() tf = tempfile.NamedTemporaryFile() tf.write(upload) if tf == None: return template('error.tpl', error="server can't download from URL") tf.flush() tf_obj = File(tf.name) tf_obj.name = tf_obj.sha256 new_path = store_sample(tf_obj) success = False if new_path: # Add file to the database. success = db.add(obj=tf_obj, tags=tags) if success: #redirect("/project/{0}".format(project)) redirect("/file/Main/"+tf_obj.sha256) else: return template('error.tpl', error="Unable to Store The File,already in database")
def run(self): if not __session__.is_set(): print_error("No session opened") return if not HAVE_PYDEEP: print_error("Missing dependency, install pydeep (`pip install pydeep`)") return if not __session__.file.ssdeep: print_error("No ssdeep hash available for opened file") return db = Database() samples = db.find(key='all') for sample in samples: if sample.sha256 == __session__.file.sha256: continue if not sample.ssdeep: continue score = pydeep.compare(__session__.file.ssdeep, sample.ssdeep) if score > 40: print("Match {0}%: {1}".format(score, sample.sha256))
def get_file(file_hash): key = '' if len(file_hash) == 32: key = 'md5' elif len(file_hash) == 64: key = 'sha256' else: return HTTPError(400, 'Invalid hash format (use md5 or sha256)') db = Database() rows = db.find(key=key, value=file_hash) if not rows: raise HTTPError(404, 'File not found in the database') path = get_sample_path(rows[0].sha256) if not path: raise HTTPError(404, 'File not found in the repository') response.content_length = os.path.getsize(path) response.content_type = 'application/octet-stream; charset=UTF-8' data = '' for chunk in File(path).get_chunks(): data += chunk return data
def logo(): print(""" _ (_) _ _ _ ____ _____ ____ | | | | | _ \| ___ |/ ___) \ V /| | |_| | ____| | \_/ |_| __/|_____)_| v{} |_| """.format(__version__)) db = Database() count = db.get_sample_count() try: db.find('all') except Exception: print_error("You need to update your Viper database. Run 'python update.py -d'") sys.exit() if __project__.name: name = __project__.name else: name = 'default' print(magenta("You have " + bold(count)) + magenta(" files in your " + bold(name)) + magenta(" repository"))
def delete_file(file_hash): success = False key = '' if len(file_hash) == 32: key = 'md5' elif len(file_hash) == 64: key = 'sha256' else: return HTTPError(400, 'Invalid hash format (use md5 or sha256)') db = Database() rows = db.find(key=key, value=file_hash) if not rows: raise HTTPError(404, 'File not found in the database') if rows: malware_id = rows[0].id path = get_sample_path(rows[0].sha256) if db.delete(malware_id): success = True else: raise HTTPError(404, 'File not found in repository') path = get_sample_path(rows[0].sha256) if not path: raise HTTPError(404, 'File not found in file system') else: success=os.remove(path) if success: return jsonize({'message' : 'deleted'}) else: return HTTPError(500, 'Unable to delete file')
def add_file(self, file_path, tags, parent): obj = File(file_path) new_path = store_sample(obj) if new_path: # Add file to the database. db = Database() db.add(obj=obj, tags=tags, parent_sha=parent) return obj.sha256
def peid(self): def get_signatures(): with file(os.path.join(VIPER_ROOT, 'data/peid/UserDB.TXT'), 'rt') as f: sig_data = f.read() signatures = peutils.SignatureDatabase(data=sig_data) return signatures def get_matches(pe, signatures): matches = signatures.match_all(pe, ep_only=True) return matches if not self.__check_session(): return signatures = get_signatures() peid_matches = get_matches(self.pe, signatures) if peid_matches: self.log('info', "PEiD Signatures:") for sig in peid_matches: if type(sig) is list: self.log('item', sig[0]) else: self.log('item', sig) else: self.log('info', "No PEiD signatures matched.") if self.args.scan and peid_matches: self.log('info', "Scanning the repository for matching samples...") db = Database() samples = db.find(key='all') matches = [] for sample in samples: if sample.sha256 == __sessions__.current.file.sha256: continue sample_path = get_sample_path(sample.sha256) if not os.path.exists(sample_path): continue try: cur_pe = pefile.PE(sample_path) cur_peid_matches = get_matches(cur_pe, signatures) except: continue if peid_matches == cur_peid_matches: matches.append([sample.name, sample.sha256]) self.log('info', "{0} relevant matches found".format(bold(len(matches)))) if len(matches) > 0: self.log('table', dict(header=['Name', 'SHA256'], rows=matches))
def _add_file(file_path, name, tags, parent_sha): obj = File(file_path) new_path = store_sample(obj) if new_path: db = Database() db.add(obj=obj, name=name, tags=tags, parent_sha=parent_sha) return obj.sha256 else: return None
def cmd_projects(self, *args): parser = argparse.ArgumentParser( prog="projects", description="Open a file", epilog="List or switch existing projects") group = parser.add_mutually_exclusive_group() group.add_argument('-l', '--list', action="store_true", help="List all existing projects") group.add_argument('-s', '--switch', metavar='project_name', help="Switch to the specified project") try: args = parser.parse_args(args) except: return projects_path = os.path.join(os.getcwd(), 'projects') if not os.path.exists(projects_path): print_info("The projects directory does not exist yet") return if args.list: print_info("Projects Available:") rows = [] for project in os.listdir(projects_path): project_path = os.path.join(projects_path, project) if os.path.isdir(project_path): current = '' if __project__.name and project == __project__.name: current = 'Yes' rows.append([ project, time.ctime(os.path.getctime(project_path)), current ]) print( table(header=['Project Name', 'Creation Time', 'Current'], rows=rows)) elif args.switch: if __sessions__.is_set(): __sessions__.close() print_info("Closed opened session") __project__.open(args.switch) print_info("Switched to project {0}".format(bold(args.switch))) # Need to re-initialize the Database to open the new SQLite file. self.db = Database() else: parser.print_usage()
def pehash(self): if not HAVE_PEHASH: self.log('error', "PEhash is missing. Please copy PEhash to the modules directory of Viper") return current_pehash = None if __sessions__.is_set(): current_pehash = calculate_pehash(__sessions__.current.file.path) self.log('info', "PEhash: {0}".format(bold(current_pehash))) if self.args.all or self.args.cluster or self.args.scan: db = Database() samples = db.find(key='all') rows = [] for sample in samples: sample_path = get_sample_path(sample.sha256) pe_hash = calculate_pehash(sample_path) if pe_hash: rows.append((sample.name, sample.md5, pe_hash)) if self.args.all: self.log('info', "PEhash for all files:") header = ['Name', 'MD5', 'PEhash'] self.log('table', dict(header=header, rows=rows)) elif self.args.cluster: self.log('info', "Clustering files by PEhash...") cluster = {} for sample_name, sample_md5, pe_hash in rows: cluster.setdefault(pe_hash, []).append([sample_name, sample_md5]) for item in cluster.items(): if len(item[1]) > 1: self.log('info', "PEhash cluster {0}:".format(bold(item[0]))) self.log('table', dict(header=['Name', 'MD5'], rows=item[1])) elif self.args.scan: if __sessions__.is_set() and current_pehash: self.log('info', "Finding matching samples...") matches = [] for row in rows: if row[1] == __sessions__.current.file.md5: continue if row[2] == current_pehash: matches.append([row[0], row[1]]) if matches: self.log('table', dict(header=['Name', 'MD5'], rows=matches)) else: self.log('info', "No matches found")
def pehash(self): if not HAVE_PEHASH: self.log('error', "PEhash is missing. Please copy PEhash to the modules directory of Viper") return current_pehash = None if __sessions__.is_set(): current_pehash = calculate_pehash(data=__sessions__.current.file.data) self.log('info', "PEhash: {0}".format(bold(current_pehash))) if self.args.all or self.args.cluster or self.args.scan: db = Database() samples = db.find(key='all') rows = [] for sample in samples: sample_path = get_sample_path(sample.sha256) pe_hash = calculate_pehash(sample_path) if pe_hash: rows.append((sample.name, sample.md5, pe_hash)) if self.args.all: self.log('info', "PEhash for all files:") header = ['Name', 'MD5', 'PEhash'] self.log('table', dict(header=header, rows=rows)) elif self.args.cluster: self.log('info', "Clustering files by PEhash...") cluster = {} for sample_name, sample_md5, pe_hash in rows: cluster.setdefault(pe_hash, []).append([sample_name, sample_md5]) for item in cluster.items(): if len(item[1]) > 1: self.log('info', "PEhash cluster {0}:".format(bold(item[0]))) self.log('table', dict(header=['Name', 'MD5'], rows=item[1])) elif self.args.scan: if __sessions__.is_set() and current_pehash: self.log('info', "Finding matching samples...") matches = [] for row in rows: if row[1] == __sessions__.current.file.md5: continue if row[2] == current_pehash: matches.append([row[0], row[1]]) if matches: self.log('table', dict(header=['Name', 'MD5'], rows=matches)) else: self.log('info', "No matches found")
def open_db(project): # Check for valid project if project == 'default': __project__.open(project) return Database() else: try: __project__.open(project) return Database() except Exception: return False
def compiletime(self): def get_compiletime(pe): return datetime.datetime.fromtimestamp( pe.FILE_HEADER.TimeDateStamp) if not self.__check_session(): return compile_time = get_compiletime(self.pe) self.log('info', "Compile Time: {0}".format(bold(compile_time))) if self.args.scan: self.log('info', "Scanning the repository for matching samples...") db = Database() samples = db.find(key='all') matches = [] for sample in samples: if sample.sha256 == __sessions__.current.file.sha256: continue sample_path = get_sample_path(sample.sha256) if not os.path.exists(sample_path): continue try: cur_pe = pefile.PE(sample_path) cur_compile_time = get_compiletime(cur_pe) except: continue if compile_time == cur_compile_time: matches.append([sample.name, sample.md5, cur_compile_time]) else: if self.args.window: if cur_compile_time > compile_time: delta = (cur_compile_time - compile_time) elif cur_compile_time < compile_time: delta = (compile_time - cur_compile_time) delta_minutes = int(delta.total_seconds()) / 60 if delta_minutes <= self.args.window: matches.append( [sample.name, sample.md5, cur_compile_time]) self.log('info', "{0} relevant matches found".format(bold(len(matches)))) if len(matches) > 0: self.log( 'table', dict(header=['Name', 'MD5', 'Compile Time'], rows=matches))
def _search_local_hashes(self, event, open_session=True): local = [] samples_count = 0 if isinstance(event, MISPEvent): misp_event = event elif event.get('Event') is None: self.log('error', event) return else: misp_event = MISPEvent() misp_event.load(event) if not hasattr(misp_event, 'id'): # The event doesn't exists upstream, breaking. return for a in misp_event.attributes + [ attribute for obj in misp_event.objects for attribute in obj.attributes ]: row = None if a.type == 'malware-sample': samples_count += 1 if a.type in ('md5', 'sha1', 'sha256'): row = Database().find(key=a.type, value=a.value) elif a.type in ('filename|md5', 'filename|sha1', 'filename|sha256'): row = Database().find(key=a.type.split('|')[1], value=a.value.split('|')[1]) elif a.type == 'malware-sample': row = Database().find(key='md5', value=a.value.split('|')[1]) if row: local.append(row[0]) self.log( 'info', 'Event {} contains {} samples.'.format(misp_event.id, samples_count)) if not open_session: return shas = set([l.sha256 for l in local]) if len(shas) == 1: __sessions__.new(get_sample_path(shas.pop()), MispEvent(misp_event, self.offline_mode)) elif len(shas) > 1: self.log('success', 'The following samples are in this viper instance:') __sessions__.new( misp_event=MispEvent(misp_event, self.offline_mode)) for s in shas: self.log('item', s) else: __sessions__.new( misp_event=MispEvent(misp_event, self.offline_mode)) self.log('info', 'No known (in Viper) samples in that event.')
def add_file(): tags = request.forms.get('tag_list') uploads = request.files.getlist('file') # Set Project project = request.forms.get('project') if project in project_list(): __project__.open(project) else: __project__.open('../') project = 'Main' db = Database() file_list = [] # Write temp file to disk with upload_temp() as temp_dir: for upload in uploads: file_path = os.path.join(temp_dir, upload.filename) with open(file_path, 'w') as tmp_file: tmp_file.write(upload.file.read()) # Zip Files if request.forms.get('unzip'): zip_pass = request.forms.get('zip_pass') try: with ZipFile(file_path) as zf: zf.extractall(temp_dir, pwd=zip_pass) for root, dirs, files in os.walk(temp_dir, topdown=False): for name in files: if not name == upload.filename: file_list.append(os.path.join(root, name)) except Exception as e: return template('error.tpl', error="Error with zipfile - {0}".format(e)) # Non zip files else: file_list.append(file_path) # Add each file for new_file in file_list: print new_file obj = File(new_file) new_path = store_sample(obj) success = True if new_path: # Add file to the database. success = db.add(obj=obj, tags=tags) if not success: return template( 'error.tpl', error="Unable to Store The File: {0}".format( upload.filename)) redirect("/project/{0}".format(project))
def cmd_tags(self, *args): parser = argparse.ArgumentParser( prog="tags", description="Modify tags of the opened file") parser.add_argument( '-a', '--add', help="Add tags to the opened file (comma separated)") parser.add_argument('-d', '--delete', help="Delete a tag from the opened file") try: args = parser.parse_args(args) except: return # This command requires a session to be opened. if not __sessions__.is_set(): print_error("No session opened") parser.print_usage() return # If no arguments are specified, there's not much to do. # However, it could make sense to also retrieve a list of existing # tags from this command, and not just from the "find" command alone. if args.add is None and args.delete is None: parser.print_usage() return # TODO: handle situation where addition or deletion of a tag fail. if args.add: # Add specified tags to the database's entry belonging to # the opened file. db = Database() db.add_tags(__sessions__.current.file.sha256, args.add) print_info("Tags added to the currently opened file") # We refresh the opened session to update the attributes. # Namely, the list of tags returned by the "info" command # needs to be re-generated, or it wouldn't show the new tags # until the existing session is closed a new one is opened. print_info("Refreshing session to update attributes...") __sessions__.new(__sessions__.current.file.path) if args.delete: # Delete the tag from the database. Database().delete_tag(args.delete) # Refresh the session so that the attributes of the file are # updated. print_info("Refreshing session to update attributes...") __sessions__.new(__sessions__.current.file.path)
def parse_message(self, message_folder): db = Database() email_header = os.path.join(message_folder, 'InternetHeaders.txt') email_body = os.path.join(message_folder, 'Message.txt') envelope = headers = email_text = '' if os.path.exists(email_header): envelope, headers = self.email_headers(email_header) if os.path.exists(email_body): email_text = open(email_body, 'rb').read() tags = 'pst, {0}'.format(message_folder) if os.path.exists(os.path.join(message_folder, 'Attachments')): for filename in os.listdir( os.path.join(message_folder, 'Attachments')): if os.path.isfile( os.path.join(message_folder, 'Attachments', filename)): obj = File( os.path.join(message_folder, 'Attachments', filename)) sha256 = hashlib.sha256( open( os.path.join(message_folder, 'Attachments', filename), 'rb').read()).hexdigest() new_path = store_sample(obj) if new_path: # Add file to the database. db.add(obj=obj, tags=tags) # Add Email Details as a Note # To handle duplicates we use multiple notes headers_body = 'Envelope: \n{0}\nHeaders: \n{1}\n'.format( envelope, headers) db.add_note(sha256, 'Headers', headers_body) # Add a note with email body db.add_note(sha256, 'Email Body', string_clean(email_text))
def run(self): super(Fuzzy, self).run() if not __sessions__.is_set(): self.log('error', "No session opened") return if not HAVE_PYDEEP: self.log( 'error', "Missing dependency, install pydeep (`pip install pydeep`)") return if not __sessions__.current.file.ssdeep: self.log('error', "No ssdeep hash available for opened file") return arg_verbose = False if self.args and self.args.verbose: arg_verbose = True db = Database() samples = db.find(key='all') matches = [] for sample in samples: if sample.sha256 == __sessions__.current.file.sha256: continue if not sample.ssdeep: continue score = pydeep.compare(__sessions__.current.file.ssdeep, sample.ssdeep) if score > 40: matches.append( ['{0}%'.format(score), sample.name, sample.sha256]) if arg_verbose: self.log( 'info', "Match {0}%: {2} [{1}]".format(score, sample.name, sample.sha256)) self.log('info', "{0} relevant matches found".format(bold(len(matches)))) if len(matches) > 0: self.log('table', dict(header=['Score', 'Name', 'SHA256'], rows=matches))
def run(self, *args): try: args = self.parser.parse_args(args) except SystemExit: return if not __sessions__.is_set(): self.log( 'error', "No open session. This command expects a file to be open.") return db = Database() # check if the file is already stores, otherwise exit malware = db.find(key='sha256', value=__sessions__.current.file.sha256) if not malware: self.log( 'error', "The opened file doesn't appear to be in the database, have you stored it yet?" ) return if args.list: # Retrieve all analysis for the currently opened file. analysis_list = malware[0].analysis if not analysis_list: self.log('info', "No analysis available for this file yet") return # Populate table rows. rows = [[analysis.id, analysis.cmd_line, analysis.stored_at] for analysis in analysis_list] # Display list of existing results. self.log( 'table', dict(header=['ID', 'Cmd Line', 'Saved On (UTC)'], rows=rows)) elif args.view: # Retrieve analysis with the specified ID and print it. result = db.get_analysis(args.view) if result: self.log('info', bold('Cmd Line: ') + result.cmd_line) for line in json.loads(result.results): self.log(line['type'], line['data']) else: self.log('info', "There is no analysis with ID {0}".format(args.view))
def compiletime(self): def get_compiletime(pe): return datetime.datetime.fromtimestamp(pe.FILE_HEADER.TimeDateStamp) if not self.__check_session(): return compile_time = get_compiletime(self.pe) self.log('info', "Compile Time: {0}".format(bold(compile_time))) if self.args.scan: self.log('info', "Scanning the repository for matching samples...") db = Database() samples = db.find(key='all') matches = [] for sample in samples: if sample.sha256 == __sessions__.current.file.sha256: continue sample_path = get_sample_path(sample.sha256) if not os.path.exists(sample_path): continue try: cur_pe = pefile.PE(sample_path) cur_compile_time = get_compiletime(cur_pe) except: continue if compile_time == cur_compile_time: matches.append([sample.name, sample.md5, cur_compile_time]) else: if self.args.window: if cur_compile_time > compile_time: delta = (cur_compile_time - compile_time) elif cur_compile_time < compile_time: delta = (compile_time - cur_compile_time) delta_minutes = int(delta.total_seconds()) / 60 if delta_minutes <= self.args.window: matches.append([sample.name, sample.md5, cur_compile_time]) self.log('info', "{0} relevant matches found".format(bold(len(matches)))) if len(matches) > 0: self.log('table', dict(header=['Name', 'MD5', 'Compile Time'], rows=matches))
def run(self): # TODO: this function needs to be refactored. super(Strings, self).run() if self.args is None: return arg_all = self.args.all arg_hosts = self.args.hosts arg_scan = self.args.scan regexp = '[\x20\x30-\x39\x41-\x5a\x61-\x7a\-\.:]{4,}' if arg_scan: db = Database() samples = db.find(key='all') rows = [] for sample in samples: sample_path = get_sample_path(sample.sha256) strings = re.findall(regexp, File(sample_path).data) results = self.extract_hosts(strings) if results: self.log('info', sample.name) for result in results: self.log('item', result) else: if not __sessions__.is_set(): self.log('error', "No open session") return if os.path.exists(__sessions__.current.file.path): strings = re.findall(regexp, __sessions__.current.file.data) if arg_all: for entry in strings: self.log('', entry) elif arg_hosts: results = self.extract_hosts(strings) for result in results: self.log('item', result) if not arg_all and not arg_hosts and not arg_scan: self.log('error', 'At least one of the parameters is required') self.usage()
def file_info(file_hash, project=False): contents = {} if project in project_list(): __project__.open(project) contents['project'] = project else: __project__.open('../') contents['project'] = 'Main' # Open the Database db = Database() # Open a session try: path = get_sample_path(file_hash) __sessions__.new(path) except: return template('error.tpl', error="{0} Does not match any hash in the Database".format(file_hash)) # Get the file info contents['file_info'] = [ __sessions__.current.file.name, __sessions__.current.file.tags, __sessions__.current.file.path, __sessions__.current.file.size, __sessions__.current.file.type, __sessions__.current.file.mime, __sessions__.current.file.md5, __sessions__.current.file.sha1, __sessions__.current.file.sha256, __sessions__.current.file.sha512, __sessions__.current.file.ssdeep, __sessions__.current.file.crc32 ] # Get Any Notes note_list = [] malware = db.find(key='sha256', value=file_hash) if malware: notes = malware[0].note if notes: rows = [] for note in notes: note_list.append([note.title, note.body, note.id]) contents['notes'] = note_list # Close the session __sessions__.close() # Return the page return template('file.tpl', **contents)
def tags(): # Set DB db = Database() # Search or Delete if request.method == 'GET': action = request.query.action value = request.query.value.strip() if value: if action == 'delete': # Delete individual tags is not in viper yet pass elif action == 'search': # This will search all projects # Get project list projects = project_list() # Add Main db to list. projects.append('../') # Search All projects p_list = [] results = {} for project in projects: __project__.open(project) # Init DB db = Database() #get results proj_results = [] rows = db.find(key='tag', value=value) for row in rows: if project == '../': project = 'Main' proj_results.append([row.name, row.sha256]) results[project] = proj_results p_list.append(project) # Return the search template return template('search.tpl', projects=p_list, results=results) else: return template('error.tpl', error="'{0}' Is not a valid tag action".format(action)) # Add New Tags if request.method == 'POST': file_hash = request.forms.get('sha256') project = request.forms.get('project') if file_hash and project: tags = request.forms.get('tags') db.add_tags(file_hash, tags) redirect('/file/{0}/{1}'.format(project, file_hash))
def run(self, *args): try: args = self.parser.parse_args(args) except SystemExit: return if __sessions__.is_set(): if not __sessions__.current.file.id: self.log( 'error', "The opened file does not have an ID, have you stored it yet?" ) return self.log( 'info', "Current name is: {}".format( bold(__sessions__.current.file.name))) new_name = input("New name: ") if not new_name: self.log('error', "File name can't be empty!") return Database().rename(__sessions__.current.file.id, new_name) self.log('info', "Refreshing session to update attributes...") __sessions__.new(__sessions__.current.file.path) else: self.log( 'error', "No open session. This command expects a file to be open.")
def new(self, path): session = Session() total = len(self.sessions) session.id = total + 1 # Open a section on the given file. session.file = File(path) # Try to lookup the file in the database. If it is already present # we get file name and row = Database().find(key='sha256', value=session.file.sha256) if row: session.file.name = row[0].name session.file.tags = ', '.join(tag.to_dict()['tag'] for tag in row[0].tag) # Loop through all existing sessions and check whether there's another # session open on the same file and delete it. This is to avoid # duplicates in sessions. # NOTE: in the future we might want to remove this if sessions have # unique attributes (for example, an history just for each of them). for entry in self.sessions: if entry.file.sha256 == session.file.sha256: self.sessions.remove(entry) # Add new session to the list. self.sessions.append(session) # Mark the new session as the current one. self.current = session print_info("Session opened on {0}".format(path))
def module_cmdline(project=None, cmd_line=None, file_hash=None): html = "" cmd = Commands() split_commands = cmd_line.split(';') for split_command in split_commands: split_command = split_command.strip() if not split_command: continue root, args = parse(split_command) try: if root in cmd.commands: cmd.commands[root]['obj'](*args) html += print_output(cmd.output) del (cmd.output[:]) elif root in __modules__: # if prev commands did not open a session open one on the current file if file_hash: __project__.open(project) path = get_sample_path(file_hash) __sessions__.new(path) module = __modules__[root]['obj']() module.set_commandline(args) module.run() html += print_output(module.output) if cfg.modules.store_output and __sessions__.is_set(): Database().add_analysis(file_hash, split_command, module.output) del (module.output[:]) else: html += '<p class="text-danger">{0} is not a valid command</p>'.format(cmd_line) except Exception: html += '<p class="text-danger">We were unable to complete the command {0}</p>'.format(cmd_line) __sessions__.close() return html
def __init__(self): # Open connection to the database. self.db = Database() # Map commands to their related functions. self.commands = dict( help=dict(obj=self.cmd_help, description="Show this help message"), open=dict(obj=self.cmd_open, description="Open a file"), new=dict(obj=self.cmd_new, description="Create new file"), close=dict(obj=self.cmd_close, description="Close the current session"), info=dict(obj=self.cmd_info, description="Show information on the opened file"), notes=dict(obj=self.cmd_notes, description="View, add and edit notes on the opened file"), clear=dict(obj=self.cmd_clear, description="Clear the console"), store=dict(obj=self.cmd_store, description="Store the opened file to the local repository"), delete=dict(obj=self.cmd_delete, description="Delete the opened file"), find=dict(obj=self.cmd_find, description="Find a file"), tags=dict(obj=self.cmd_tags, description="Modify tags of the opened file"), sessions=dict(obj=self.cmd_sessions, description="List or switch sessions"), stats=dict(obj=self.cmd_stats, description="Viper Collection Statistics"), projects=dict(obj=self.cmd_projects, description="List or switch existing projects"), parent=dict(obj=self.cmd_parent, description="Add or remove a parent file"), export=dict(obj=self.cmd_export, description="Export the current session to file or zip"), analysis=dict(obj=self.cmd_analysis, description="View the stored analysis"), rename=dict(obj=self.cmd_rename, description="Rename the file in the database"), )
def post(self, request, *args, **kwargs): # Get the project and hash of the file we want to run a command against project = kwargs.get('project', 'default') file_hash = request.POST.get('file_hash') if len(file_hash) != 64: file_hash = False # Lot of logic here to decide what command you entered. module_name = request.POST.get('module') print("Here: {}".format(module_name)) if module_name == "module": return HttpResponse("<pre>Error: No Module selected!</pre>") module_args = request.POST.get('args') cmd_line = request.POST.get('cmdline') module_history = request.POST.get('moduleHistory', ' ') cmd_string = '' # Order of precedence # moduleHistory, cmd_line, module_name if module_history != ' ': result = Database().get_analysis(module_history) module_results = print_output(json.loads(result.results)) html = '<p class="text-success">Result for "{0}" stored on {1}</p>'.format(result.cmd_line, result.stored_at) html += str(parse_text(module_results)) return HttpResponse('<pre>{0}</pre>'.format(html)) if cmd_line: cmd_string = cmd_line elif module_args: cmd_string = '{0} {1}'.format(module_name, mod_dict[module_name][module_args]) module_results = module_cmdline(project=project, file_hash=file_hash, cmd_line=cmd_string) return HttpResponse('<pre>{0}</pre>'.format(str(parse_text(module_results))))
def __init__(self): super(ClamAV, self).__init__() self.parser.add_argument( '-s', '--socket', help='Specify an unix socket (default: Clamd Unix Socket)') self.parser.add_argument('-a', '--all', action='store_true', help='Scan all files') self.parser.add_argument( '-t', '--tag', action='store_true', help='Tag file(s) with the signature name when detect as malware') self.db = Database()
def autorun_module(file_hash): if not file_hash: return # We need an open session if not __sessions__.is_set(): # Open session __sessions__.new(get_sample_path(file_hash)) for cmd_line in cfg.autorun.commands.split(','): split_commands = cmd_line.split(';') for split_command in split_commands: split_command = split_command.strip() if not split_command: continue root, args = parse(split_command) try: if root in __modules__: module = __modules__[root]['obj']() module.set_commandline(args) module.run() print_info("Running Command {0}".format(split_command)) if cfg.modules.store_output and __sessions__.is_set(): Database().add_analysis(file_hash, split_command, module.output) if cfg.autorun.verbose: print_output(module.output) del (module.output[:]) else: print_error( '{0} is not a valid command. Please check your viper.conf file.' .format(cmd_line)) except: print_error( 'Viper was unable to complete the command {0}'.format( cmd_line)) return
def tags(tag_action=False): # Set DB db = Database() # Search or Delete if request.method == 'GET': action = request.query.action value = request.query.value.strip() if value: if action == 'search': # This will search all projects # Get project list projects = project_list() # Add Main db to list. projects.append('../') # Search All projects p_list = [] results = {} for project in projects: __project__.open(project) # Init DB db = Database() #get results proj_results = [] rows = db.find(key='tag', value=value) for row in rows: if project == '../': project = 'Main' proj_results.append([row.name, row.sha256]) results[project] = proj_results p_list.append(project) # Return the search template return template('search.tpl', projects=p_list, results=results) else: return template( 'error.tpl', error="'{0}' Is not a valid tag action".format(action)) # Add / Delete if request.method == 'POST': file_hash = request.forms.get('sha256') project = request.forms.get('project') tag_name = request.forms.get('tag') if tag_action == 'add': if file_hash and project: tags = request.forms.get('tags') db.add_tags(file_hash, tags) if tag_action == 'del': if file_hash and tag_name: db.delete_tag(tag_name, file_hash) redirect('/file/{0}/{1}'.format(project, file_hash))
def add_file(): tags = request.forms.get('tag_list') upload = request.files.get('file') # Set Project project = request.forms.get('project') if project in project_list(): __project__.open(project) else: __project__.open('../') project = 'Main' db = Database() # Write temp file to disk with upload_temp() as temp_dir: file_path = os.path.join(temp_dir, upload.filename) with open(file_path, 'w') as tmp_file: tmp_file.write(upload.file.read()) file_list = [] # Zip Files if request.forms.get('unzip'): zip_pass = request.forms.get('zip_pass') try: with ZipFile(file_path) as zf: zf.extractall(temp_dir, pwd=zip_pass) for root, dirs, files in os.walk(temp_dir, topdown=False): for name in files: if not name == upload.filename: file_list.append(os.path.join(root, name)) except Exception as e: return template('error.tpl', error="Error with zipfile - {0}".format(e)) # Non zip files else: file_list.append(file_path) # Add each file for new_file in file_list: obj = File(new_file) new_path = store_sample(obj) success = False if new_path: # Add file to the database. success = db.add(obj=obj, tags=tags) if success: redirect("/project/{0}".format(project)) else: return template('error.tpl', error="Unable to Store The File")
def cmd_analysis(self, *args): parser = argparse.ArgumentParser(prog="analysis", description="Show stored module results") group = parser.add_mutually_exclusive_group() group.add_argument('-l', '--list', action='store_true', help="List all module results available for the current file") group.add_argument('-v', '--view', metavar='ANALYSIS ID', type=int, help="View the specified analysis") group.add_argument('-d', '--delete', metavar='ANALYSIS ID', type=int, help="Delete an existing analysis") try: args = parser.parse_args(args) except: return if not __sessions__.is_set(): self.log('error', "No open session") return # check if the file is already stores, otherwise exit malware = Database().find(key='sha256', value=__sessions__.current.file.sha256) if not malware: self.log('error', "The opened file doesn't appear to be in the database, have you stored it yet?") return if args.list: # Retrieve all analysis for the currently opened file. analysis_list = malware[0].analysis if not analysis_list: self.log('info', "No analysis available for this file yet") return # Populate table rows. rows = [[analysis.id, analysis.cmd_line, analysis.stored_at] for analysis in analysis_list] # Display list of existing results. self.log('table', dict(header=['ID', 'Cmd Line', 'Saved On'], rows=rows)) elif args.view: # Retrieve analysis wth the specified ID and print it. result = Database().get_analysis(args.view) if result: self.log('info', bold('Cmd Line: ') + result.cmd_line) for line in json.loads(result.results): self.log(line['type'], line['data']) else: self.log('info', "There is no analysis with ID {0}".format(args.view))
def cmd_tags(self, *args): parser = argparse.ArgumentParser(prog="tags", description="Modify tags of the opened file") parser.add_argument('-a', '--add', help="Add tags to the opened file (comma separated)") parser.add_argument('-d', '--delete', help="Delete a tag from the opened file") try: args = parser.parse_args(args) except: return # This command requires a session to be opened. if not __sessions__.is_set(): self.log("error", "No session opened") parser.print_usage() return # If no arguments are specified, there's not much to do. # However, it could make sense to also retrieve a list of existing # tags from this command, and not just from the "find" command alone. if args.add is None and args.delete is None: parser.print_usage() return # TODO: handle situation where addition or deletion of a tag fail. if args.add: # Add specified tags to the database's entry belonging to # the opened file. db = Database() db.add_tags(__sessions__.current.file.sha256, args.add) self.log("info", "Tags added to the currently opened file") # We refresh the opened session to update the attributes. # Namely, the list of tags returned by the "info" command # needs to be re-generated, or it wouldn't show the new tags # until the existing session is closed a new one is opened. self.log("info", "Refreshing session to update attributes...") __sessions__.new(__sessions__.current.file.path) if args.delete: # Delete the tag from the database. Database().delete_tag(args.delete) # Refresh the session so that the attributes of the file are # updated. self.log("info", "Refreshing session to update attributes...") __sessions__.new(__sessions__.current.file.path)
def parse_message(self, message_folder): db = Database() email_header = os.path.join(message_folder, 'InternetHeaders.txt') email_body = os.path.join(message_folder, 'Message.txt') envelope = headers = email_text = '' if os.path.exists(email_header): envelope, headers = self.email_headers(email_header) if os.path.exists(email_body): email_text = open(email_body, 'rb').read() tags = 'pst, {0}'.format(message_folder) if os.path.exists(os.path.join(message_folder, 'Attachments')): for filename in os.listdir(os.path.join(message_folder, 'Attachments')): if os.path.isfile(os.path.join(message_folder, 'Attachments', filename)): obj = File(os.path.join(message_folder, 'Attachments', filename)) sha256 = hashlib.sha256(open(os.path.join(message_folder, 'Attachments', filename), 'rb').read()).hexdigest() new_path = store_sample(obj) if new_path: # Add file to the database. db.add(obj=obj, tags=tags) # Add Email Details as a Note # To handle duplicates we use multiple notes headers_body = 'Envelope: \n{0}\nHeaders: \n{1}\n'.format(envelope, headers) db.add_note(sha256, 'Headers', headers_body) # Add a note with email body db.add_note(sha256, 'Email Body', string_clean(email_text))
def _search_local_hashes(self, event, open_session=True): local = [] samples_count = 0 if event.get('Event') is None: self.log('error', event) return for a in event['Event']['Attribute']: row = None if a['type'] == 'malware-sample': samples_count += 1 if a['type'] in ('malware-sample', 'filename|md5', 'md5'): h = a['value'] if '|' in a['type']: h = a['value'].split('|')[1] row = Database().find(key='md5', value=h) elif a['type'] in ('sha1', 'filename|sha1'): h = a['value'] if '|' in a['type']: h = a['value'].split('|')[1] row = Database().find(key='sha1', value=h) elif a['type'] in ('sha256', 'filename|sha256'): h = a['value'] if '|' in a['type']: h = a['value'].split('|')[1] row = Database().find(key='sha256', value=h) if row: local.append(row[0]) self.log( 'info', 'Event {} contains {} samples.'.format(event['Event']['id'], samples_count)) if not open_session: return shas = set([l.sha256 for l in local]) if len(shas) == 1: __sessions__.new(get_sample_path(shas.pop()), MispEvent(event)) elif len(shas) > 1: self.log('success', 'The following samples are in this viper instance:') __sessions__.new(misp_event=MispEvent(event)) for s in shas: self.log('item', s) else: __sessions__.new(misp_event=MispEvent(event)) self.log('info', 'No known (in Viper) samples in that event.')
def test_notes_existing(self, capsys): self.cmd['open']['obj']('-f', os.path.join(FIXTURE_DIR, "chromeinstall-8u31.exe")) Database().add_note(__sessions__.current.file.sha256, 'Note test', 'This is the content') self.cmd['notes']['obj']('-l') self.cmd['notes']['obj']('-v', '1') self.cmd['notes']['obj']('-d', '1') out, err = capsys.readouterr() assert re.search(".*1 | Note test.*", out) assert re.search(".*This is the content.*", out)
def add_tags(): tags = request.forms.get('tags') for entry in ['md5', 'sha256', 'ssdeep', 'tag', 'name', 'all']: value = request.forms.get(entry) if value: key = entry break db = Database() rows = db.find(key=key, value=value) if not rows: raise HTTPError(404, 'File not found in the database') for row in rows: malware_sha256=row.sha256 db.add_tags(malware_sha256, tags) return jsonize({'message' : 'added'})
def add_tags(): tags = request.forms.get('tags') for entry in ['md5', 'sha256', 'ssdeep', 'tag', 'name', 'all']: value = request.forms.get(entry) if value: key = entry break db = Database() rows = db.find(key=key, value=value) if not rows: raise HTTPError(404, 'File not found in the database') for row in rows: malware_sha256 = row.sha256 db.add_tags(malware_sha256, tags) return jsonize({'message': 'added'})
def new(self, path=None, misp_event=None): if path is None and misp_event is None: print_error( "You have to open a session on a path or on a misp event.") return session = Session() total = len(self.sessions) session.id = total + 1 if path is not None: if self.is_set() and self.current.misp_event: session.misp_event = self.current.misp_event # Open a section on the given file. session.file = File(path) # Try to lookup the file in the database. If it is already present # we get file name and row = Database().find(key='sha256', value=session.file.sha256) if row: session.file.name = row[0].name session.file.tags = ', '.join(tag.to_dict()['tag'] for tag in row[0].tag) print_info("Session opened on {0}".format(path)) if misp_event is not None: if self.is_set() and self.current.file: session.file = self.current.file refresh = False if self.current is not None and self.current.misp_event is not None \ and self.current.misp_event.event_id == misp_event.event_id: refresh = True session.misp_event = misp_event if refresh: print_info("Session on MISP event {0} refreshed.".format( misp_event.event_id)) else: print_info("Session opened on MISP event {0}.".format( misp_event.event_id)) if session.file is not None: # Loop through all existing sessions and check whether there's another # session open on the same file and delete it. This is to avoid # duplicates in sessions. # NOTE: in the future we might want to remove this if sessions have # unique attributes (for example, an history just for each of them). for entry in self.sessions: if entry.file is not None and entry.file.sha256 == session.file.sha256: self.sessions.remove(entry) # Add new session to the list. self.sessions.append(session) # Mark the new session as the current one. self.current = session
def add_file(file_path, tags, parent): obj = File(file_path) new_path = store_sample(obj) print new_path success = True if new_path: # Add file to the database. db = Database() success = db.add(obj=obj, tags=tags, parent_sha=parent) # AutoRun Modules if cfg.autorun.enabled: autorun_module(obj.sha256) # Close the open session to keep the session table clean __sessions__.close() return obj.sha256 else: # ToDo Remove the stored file if we cant write to DB return
def run(self): super(Template, self).run() if self.args is None: return # Check arguments and scan accordingly if self.args.all: db = Database() samples = db.find(key='all') for sample in samples: self.scan(get_sample_path(sample.sha256)) if self.args.emails: self.log('success', "Found emails: ") self.log('success', str(set(self.emails))) elif __sessions__.is_set(): self.scan(__sessions__.current.file.path) else: self.usage()
def test_notes_existing(self, capsys): commands.Open().run( '-f', os.path.join(FIXTURE_DIR, "chromeinstall-8u31.exe")) Database().add_note(commands.__sessions__.current.file.sha256, 'Note test', 'This is the content') commands.Notes().run('-l') commands.Notes().run('-v', '1') commands.Notes().run('-d', '1') out, err = capsys.readouterr() assert re.search(".*1 | Note test.*", out) assert re.search(".*This is the content.*", out)
def run(self): super(Fuzzy, self).run() if not __sessions__.is_set(): self.log('error', "No session opened") return if not HAVE_PYDEEP: self.log('error', "Missing dependency, install pydeep (`pip install pydeep`)") return if not __sessions__.current.file.ssdeep: self.log('error', "No ssdeep hash available for opened file") return arg_verbose = False if self.args and self.args.verbose: arg_verbose = True db = Database() samples = db.find(key='all') matches = [] for sample in samples: if sample.sha256 == __sessions__.current.file.sha256: continue if not sample.ssdeep: continue score = pydeep.compare(__sessions__.current.file.ssdeep, sample.ssdeep) if score > 40: matches.append(['{0}%'.format(score), sample.name, sample.sha256]) if arg_verbose: self.log('info', "Match {0}%: {2} [{1}]".format(score, sample.name, sample.sha256)) self.log('info', "{0} relevant matches found".format(bold(len(matches)))) if len(matches) > 0: self.log('table', dict(header=['Score', 'Name', 'SHA256'], rows=matches))
def cmd_parent(self, *args): parser = argparse.ArgumentParser(prog='tags', description="Set the Parent for this file.") parser.add_argument('-a', '--add', metavar='SHA256', help="Add parent file by sha256") parser.add_argument('-d', '--delete', action='store_true', help="Delete Parent") parser.add_argument('-o', '--open', action='store_true', help="Open The Parent") try: args = parser.parse_args(args) except: return # This command requires a session to be opened. if not __sessions__.is_set(): self.log('error', "No open session") parser.print_usage() return # If no arguments are specified, there's not much to do. if args.add is None and args.delete is None and args.open is None: parser.print_usage() return db = Database() if not db.find(key='sha256', value=__sessions__.current.file.sha256): self.log('error', "The opened file is not stored in the database. " "If you want to add it use the `store` command.") return if args.add: if not db.find(key='sha256', value=args.add): self.log('error', "the parent file is not found in the database. ") return db.add_parent(__sessions__.current.file.sha256, args.add) self.log('info', "parent added to the currently opened file") self.log('info', "Refreshing session to update attributes...") __sessions__.new(__sessions__.current.file.path) if args.delete: db.delete_parent(__sessions__.current.file.sha256) self.log('info', "parent removed from the currently opened file") self.log('info', "Refreshing session to update attributes...") __sessions__.new(__sessions__.current.file.path) if args.open: # Open a session on the parent if __sessions__.current.file.parent: __sessions__.new(get_sample_path(__sessions__.current.file.parent[-64:])) else: self.log('info', "No parent set for this sample")
def run(self, *args): try: args = self.parser.parse_args(args) except SystemExit: return while True: choice = input("Are you sure? It can't be reverted! [y/n] ") if choice == 'y': break elif choice == 'n': return db = Database() if args.all: if __sessions__.is_set(): __sessions__.close() samples = db.find('all') for sample in samples: db.delete_file(sample.id) os.remove(get_sample_path(sample.sha256)) self.log('info', "Deleted a total of {} files.".format(len(samples))) elif args.find: if __sessions__.find: samples = __sessions__.find for sample in samples: db.delete_file(sample.id) os.remove(get_sample_path(sample.sha256)) self.log('info', "Deleted {} files.".format(len(samples))) else: self.log('error', "No find result") else: if __sessions__.is_set(): rows = db.find('sha256', __sessions__.current.file.sha256) if rows: malware_id = rows[0].id if db.delete_file(malware_id): self.log("success", "File deleted") else: self.log('error', "Unable to delete file") os.remove(__sessions__.current.file.path) __sessions__.close() self.log('info', "Deleted opened file.") else: self.log('error', "No session open, and no --all argument. Nothing to delete.")
def run(self, *args): try: args = self.parser.parse_args(args) except SystemExit: return if not __sessions__.is_set(): self.log('error', "No open session. This command expects a file to be open.") return db = Database() # check if the file is already stores, otherwise exit malware = db.find(key='sha256', value=__sessions__.current.file.sha256) if not malware: self.log('error', "The opened file doesn't appear to be in the database, have you stored it yet?") return if args.list: # Retrieve all analysis for the currently opened file. analysis_list = malware[0].analysis if not analysis_list: self.log('info', "No analysis available for this file yet") return # Populate table rows. rows = [[analysis.id, analysis.cmd_line, analysis.stored_at] for analysis in analysis_list] # Display list of existing results. self.log('table', dict(header=['ID', 'Cmd Line', 'Saved On (UTC)'], rows=rows)) elif args.view: # Retrieve analysis wth the specified ID and print it. result = db.get_analysis(args.view) if result: self.log('info', bold('Cmd Line: ') + result.cmd_line) for line in json.loads(result.results): self.log(line['type'], line['data']) else: self.log('info', "There is no analysis with ID {0}".format(args.view))
def __init__(self): # Open connection to the database. self.db = Database() # Map commands to their related functions. self.commands = dict( help=dict(obj=self.cmd_help, description="Show this help message"), open=dict(obj=self.cmd_open, description="Open a file"), new=dict(obj=self.cmd_new, description="Create new file"), close=dict(obj=self.cmd_close, description="Close the current session"), info=dict(obj=self.cmd_info, description="Show information on the opened file"), notes=dict( obj=self.cmd_notes, description="View, add and edit notes on the opened file"), clear=dict(obj=self.cmd_clear, description="Clear the console"), store=dict( obj=self.cmd_store, description="Store the opened file to the local repository"), delete=dict(obj=self.cmd_delete, description="Delete the opened file"), find=dict(obj=self.cmd_find, description="Find a file"), tags=dict(obj=self.cmd_tags, description="Modify tags of the opened file"), sessions=dict(obj=self.cmd_sessions, description="List or switch sessions"), stats=dict(obj=self.cmd_stats, description="Viper Collection Statistics"), projects=dict(obj=self.cmd_projects, description="List or switch existing projects"), parent=dict(obj=self.cmd_parent, description="Add or remove a parent file"), export=dict( obj=self.cmd_export, description="Export the current session to file or zip"), analysis=dict(obj=self.cmd_analysis, description="View the stored analysis"), rename=dict(obj=self.cmd_rename, description="Rename the file in the database"), )
def logo(): print(""" _ (_) _ _ _ ____ _____ ____ | | | | | _ \| ___ |/ ___) \ V /| | |_| | ____| | \_/ |_| __/|_____)_| v1.2 |_| """) db = Database() count = db.get_sample_count() if __project__.name: name = __project__.name else: name = 'default' print(magenta("You have " + bold(count)) + magenta(" files in your " + bold(name) + magenta(" repository".format(bold(name)))))
def size_all(self): db = Database() samples = db.find(key='all') rows = [] for sample in samples: sample_path = get_sample_path(sample.sha256) if not os.path.exists(sample_path): continue try: cur_size = os.path.getsize(sample_path) except Exception as e: self.log('error', "Error {0} for sample {1}".format(e, sample.sha256)) continue rows.append([sample.md5, sample.name, cur_size]) self.log('table', dict(header=['MD5', 'Name', 'Size (B)'], rows=rows)) return
def edit(self): db = Database() samples = db.find(key='all') filenames = [] for sample in samples: if sample.sha256 == __sessions__.current.file.sha256: continue filenames.append(sample.name) # from http://hetland.org/coding/python/levenshtein.py def levenshtein(a, b): "Calculates the Levenshtein distance between a and b." n, m = len(a), len(b) if n > m: # Make sure n <= m, to use O(min(n,m)) space a,b = b,a n,m = m,n current = range(n+1) for i in range(1,m+1): previous, current = current, [i]+[0]*n for j in range(1,n+1): add, delete = previous[j]+1, current[j-1]+1 change = previous[j-1] if a[j-1] != b[i-1]: change = change + 1 current[j] = min(add, delete, change) return current[n] distance = [] for i in itertools.combinations(filenames, 2): edit = levenshtein(i[0], i[1]) distance.append(edit) print_info("Average Edit distance: {0}".format(sum(distance)/len(distance)))
def landing(p=False): contents = {} if p in project_list(): __project__.open(p) contents['p'] = p else: __project__.open("../") contents['p'] = 'Main' db = Database() # Pagination # 25 per page value = 25 offset = 0 contents['count'] = db.get_sample_count() page = request.query.page if not page: page = 0 offset = int(page) * int(value) contents['act_page'] = page contents['latest'] = db.find('latest', value=value, offset=offset) # return the Template return template('index.tpl', **contents)