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 run(self): if not __session__.is_set(): print_error("No session opened") return if not HAVE_PEFILE: print_error("Missing dependency, install pefile (`pip install pefile`)") return try: self.pe = pefile.PE(__session__.file.path) except pefile.PEFormatError as e: print_error("Unable to parse PE file: {0}".format(e)) return if len(self.args) == 0: self.help() return if self.args[0] == 'help': self.help() elif self.args[0] == 'imports': self.imports() elif self.args[0] == 'exports': self.exports() elif self.args[0] == 'resources': self.resources()
def run(self): if not __session__.is_set(): print_error("No session opened") return data = urllib.urlencode({'resource' : __session__.file.md5, 'apikey' : KEY}) try: request = urllib2.Request(VIRUSTOTAL_URL, data) response = urllib2.urlopen(request) response_data = response.read() except Exception as e: print_error("Failed: {0}".format(e)) return try: virustotal = json.loads(response_data) except ValueError as e: print_error("Failed: {0}".format(e)) rows = [] if 'scans' in virustotal: for engine, signature in virustotal['scans'].items(): if signature['detected']: signature = signature['result'] else: signature = '' rows.append([engine, signature]) print(table(['Antivirus', 'Signature'], rows))
def run(self): if not __session__.is_set(): print_error("No session opened") return if len(self.args) == 0: self.help() return if self.args[0] == 'ghiro': self.ghiro()
def run(self): if not __session__.is_set(): print_error("No session opened") return if not HAVE_REQUESTS: print_error("Missing dependency, install requests (`pip install requests`)") return def usage(): print ("usage: cuckoo [-H=host] [-p=port]") def help(): usage() print ("") print ("Options:") print ("\t--help (-h)\tShow this help message") print ("\t--host (-H)\tSpecify an host (default: localhost)") print ("\t--port (-p)\tSpecify a port (default: 8090") print ("") try: opts, argv = getopt.getopt(self.args, "hH:p:", ["help", "host=", "port="]) except getopt.GetoptError as e: print (e) usage() return host = "localhost" port = 8090 for opt, value in opts: if opt in ("-h", "--help"): help() return elif opt in ("-H", "--host"): if value: host = value elif opt in ("-p", "--port"): if value: port = value url = "http://{0}:{1}/tasks/create/file".format(host, port) files = dict(file=open(__session__.file.path, "rb")) try: response = requests.post(url, files=files) except requests.ConnectionError: print_error("Unable to connect to Cuckoo API at {0}:{1}".format(host, port)) return print response.text
def auto(self): if not __session__.is_set(): print_error("No session opened") return rules = yara.compile('data/yara/rats.yara') for match in rules.match(__session__.file.path): if 'family' in match.meta: print_info("Automatically detected supported RAT {0}".format(match.rule)) self.get_config(match.meta['family']) return print_info("No known RAT detected")
def keywords(self, data): # Check if $self is in the user input data. if '$self' in data: # Check if there is an open session. if __session__.is_set(): # If a session is opened, replace $self with the path to # the file which is currently being analyzed. data = data.replace('$self', __session__.file.path) else: print("No session opened") return None return data
def __check_session(self): if not __session__.is_set(): print_error("No session opened") return False if not self.pe: try: self.pe = pefile.PE(__session__.file.path) except pefile.PEFormatError as e: print_error("Unable to parse PE file: {0}".format(e)) return False return True
def run(self): if not __session__.is_set(): print_error("No session opened") return if os.path.exists(__session__.file.path): try: # data = open(__session__.file.path, 'r').read() a = apk.APK(__session__.file.path) print a.get_app_name() print a.get_details_permissions() except (IOError, OSError) as e: print_error("Cannot open file: {0}".format(e))
def run(self): if not __session__.is_set(): print_error("No session opened") return if os.path.exists(__session__.file.path): try: data = open(__session__.file.path, 'r').read() except (IOError, OSError) as e: print_error("Cannot open file: {0}".format(e)) strings = re.findall('[\x1f-\x7e]{6,}', data) for s in strings: print(s)
def run(self): if not __session__.is_set(): print_error("No session opened") return if not HAVE_REQUESTS: print_error("Missing dependency, install requests (`pip install requests`)") return url = 'http://{0}:{1}/tasks/create/file'.format(CUCKOO_HOST, CUCKOO_PORT) files = dict(file=open(__session__.file.path, 'rb')) response = requests.post(url, files=files) print response.text
def run(self): if not __session__.is_set(): print_error("No session opened") return if os.path.exists(__session__.file.path): try: # data = open(__session__.file.path, 'r').read() a = apk.APK(__session__.file.path) # d = dvm.DalvikVMFormat(a.get_dex()) print a.get_main_activity() # print a.get_details_permissions() # print d.get_regex_strings("http") except (IOError, OSError) as e: print_error("Cannot open file: {0}".format(e))
def cmd_info(self, *args): if __session__.is_set(): print(table( ['Key', 'Value'], [ ('Name', __session__.file.name), ('Tags', __session__.file.tags), ('Path', __session__.file.path), ('Size', __session__.file.size), ('Type', __session__.file.type), ('MD5', __session__.file.md5), ('SHA1', __session__.file.sha1), ('SHA256', __session__.file.sha256), ('SHA512', __session__.file.sha512), ('SSdeep', __session__.file.ssdeep), ('CRC32', __session__.file.crc32) ] ))
def cmd_delete(self, *args): if __session__.is_set(): while True: choice = raw_input("Are you sure you want to delete this binary? Can't be reverted! [y/n] ") if choice == 'y': break elif choice == 'n': return rows = self.db.find('sha256', __session__.file.sha256) if rows: malware_id = rows[0].id if self.db.delete(malware_id): print_success("File deleted") else: print_error("Unable to delete file") os.remove(get_sample_path(__session__.file.sha256)) __session__.clear()
def cmd_info(self, *args): if __session__.is_set(): print( table( ["Key", "Value"], [ ("Name", __session__.file.name), ("Tags", __session__.file.tags), ("Path", __session__.file.path), ("Size", __session__.file.size), ("Type", __session__.file.type), ("MD5", __session__.file.md5), ("SHA1", __session__.file.sha1), ("SHA256", __session__.file.sha256), ("SHA512", __session__.file.sha512), ("SSdeep", __session__.file.ssdeep), ("CRC32", __session__.file.crc32), ], ) )
def get_config(self, family): if not __session__.is_set(): print_error("No session opened") return try: module = importlib.import_module('modules.rats.{0}'.format(family)) except ImportError: print_error("There is no module for family {0}".format(bold(family))) return config = module.config(__session__.file.data) if not config: print_error("No Configuration Detected") return rows = [] for key, value in config.items(): rows.append([key, value]) rows = sorted(rows, key=lambda entry: entry[0]) print_info("Configuration:") print(table(header=['Key', 'Value'], rows=rows))
def run(self): if not __session__.is_set(): print_error("No session opened") return if not HAVE_EXIF: print_error("Missing dependency, install pyexiftool") return try: with exiftool.ExifTool() as et: metadata = et.get_metadata(__session__.file.path) except OSError: print_error("Exiftool is not installed") return rows = [] for key, value in metadata.items(): rows.append([key, value]) rows = sorted(rows, key=lambda entry: entry[0]) print_info("MetaData:") print(table(header=['Key', 'Value'], rows=rows))
def start(self): # Setup shell auto-complete. def complete(text, state): return (glob.glob(text+'*')+[None])[state] # Auto-complete on tabs. readline.set_completer_delims(' \t\n;') readline.parse_and_bind('tab: complete') readline.set_completer(complete) # Save commands in history file. def save_history(path): readline.write_history_file(path) # If there is an history file, read from it and load the history # so that they can be loaded in the shell. history_path = os.path.expanduser('~/.viperhistory') if os.path.exists(history_path): readline.read_history_file(history_path) # Register the save history at program's exit. atexit.register(save_history, path=history_path) # Main loop. while self.active: # If there is an open session, we include the path to the opened # file in the shell prompt. # TODO: perhaps this block should be moved into the session so that # the generation of the prompt is done only when the session's # status changes. if __session__.is_set(): prompt = cyan('shell ') + white(__session__.file.name) + cyan(' > ') # Otherwise display the basic prompt. else: prompt = cyan('shell > ') # Wait for input from the user. try: data = raw_input(prompt).strip() except KeyboardInterrupt: print("") # Terminate on EOF. except EOFError: self.stop() print("") continue # Parse the input if the user provided any. else: # If there are recognized keywords, we replace them with # their respective value. data = self.keywords(data) # Skip if the input is empty. if not data: continue # If the input starts with an exclamation mark, we treat the # input as a bash command and execute it. # At this point the keywords should be replaced. if data.startswith('!'): os.system(data[1:]) continue # If it's an internal command, we parse the input and split it # between root command and arguments. root, args = self.parse(data) # Check if the command instructs to terminate. if root in ('exit', 'quit'): self.stop() continue try: # If the root command is part of the embedded commands list we # execute it. if root in self.cmd.commands: self.cmd.commands[root]['obj'](*args) # If the root command is part of loaded modules, we initialize # the module and execute it. elif root in __modules__: module = __modules__[root]['obj']() module.set_args(args) module.run() else: print("Command not recognized.") except KeyboardInterrupt: pass except Exception as e: print_error("The command {0} raised an exception:".format(bold(root))) traceback.print_exc()
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 def usage(): print("usage: fuzzy [-v]") def help(): usage() print("") print("Options:") print("\t--help (-h)\tShow this help message") print("\t--verbose (-v)\tPrints verbose logging") print("") arg_verbose = False try: opts, argv = getopt.getopt(self.args[0:], 'hv', ['help', 'verbose']) except getopt.GetoptError as e: print(e) return for opt, value in opts: if opt in ('-h', '--help'): help() return elif opt in ('-v', '--verbose'): arg_verbose = True db = Database() samples = db.find(key='all') matches = [] 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: matches.append(['{0}%'.format(score), sample.name, sample.sha256]) if arg_verbose: print("Match {0}%: {2} [{1}]".format(score, sample.name, sample.sha256)) print_info("{0} relevant matches found".format(bold(len(matches)))) if len(matches) > 0: print(table(header=['Score', 'Name', 'SHA256'], rows=matches))
def cmd_store(self, *args): def usage(): print("usage: store [-h] [-d] [-f <path>] [-t]") def help(): usage() print("") print("Options:") print("\t--help (-h)\tShow this help message") print("\t--delete (-d)\tDelete the original file") print("\t--folder (-f)\tSpecify a folder to import") print("\t--tags (-t)\tSpecify a list of comma-separated tags") print("") try: opts, argv = getopt.getopt(args, 'hdf:t:', ['help', 'delete', 'folder=', 'tags=']) except getopt.GetoptError as e: print(e) usage() return do_delete = False folder = False tags = None for opt, value in opts: if opt in ('-h', '--help'): help() return elif opt in ('-d', '--delete'): do_delete = True elif opt in ('-f', '--folder'): folder = value elif opt in ('-t', '--tags'): tags = value def add_file(obj, tags=None): # Store file to the local repository. new_path = store_sample(obj) if new_path: # Add file to the database. status = self.db.add(obj=obj, tags=tags) print_success("Stored to: {0}".format(new_path)) # Delete the file if requested to do so. if do_delete: try: os.unlink(obj.path) except Exception as e: print_warning("Failed deleting file: {0}".format(e)) # If the user specified the --folder flag, we walk recursively and try # to add all contained files to the local repository. # This is note going to open a new session. # TODO: perhaps disable or make recursion optional? if folder: # Check if the specified folder is valid. if os.path.isdir(folder): # Walk through the folder and subfolders. for dir_name, dir_names, file_names in os.walk(folder): # Add each collected file. for file_name in file_names: file_path = os.path.join(dir_name, file_name) file_obj = File(file_path) # Add file. add_file(file_obj, tags) else: print_error("You specified an invalid folder: {0}".format(folder)) # Otherwise we try to store the currently opened file, if there is any. else: if __session__.is_set(): # Add file. add_file(__session__.file, tags) # Open session to the new file. self.cmd_open(*[__session__.file.sha256]) else: print_error("No session opened")
def scan(self): def usage(): print("usage: yara scan [-a]") def help(): usage() print("") print("Options:") print("\t--help (-h)\tShow this help message") print("\t--rule (-r)\tSpecify a ruleset file path (default will run data/yara/index.yara)") print("\t--all (-a)\tScan all stored files (default if no session is open)") print("") rule_path = '' scan_all = False try: opts, argv = getopt.getopt(self.args[1:], 'r:a', ['rule=', 'all']) except getopt.GetoptError as e: print(e) return for opt, value in opts: if opt in ('-h', '--help'): help() return elif opt in ('-r', '--rule'): rule_path = value elif opt in ('-a', '--all'): scan_all = True # If no custom ruleset is specified, we use the default one. if not rule_path: rule_path = 'data/yara/index.yara' # Check if the selected ruleset actually exists. if not os.path.exists(rule_path): print_error("No valid Yara ruleset at {0}".format(rule_path)) return # Compile all rules from given ruleset. rules = yara.compile(rule_path) files = [] # If there is a session open and the user didn't specifically # request to scan the full repository, we just add the currently # opened file's path. if __session__.is_set() and not scan_all: files.append(__session__.file) # Otherwise we loop through all files in the repository and queue # them up for scan. else: print_info("Scanning all stored files...") db = Database() samples = db.find(key='all') for sample in samples: files.append(sample) for entry in files: print_info("Scanning {0} ({1})".format(entry.name, entry.sha256)) rows = [] for match in rules.match(get_sample_path(entry.sha256)): for string in match.strings: rows.append([match.rule, string[1], string[0], string[2]]) if rows: header = [ 'Rule', 'String', 'Offset', 'Content' ] print(table(header=header, rows=rows))
def scan(self): def usage(): print("usage: yara scan [-a]") def help(): usage() print("") print("Options:") print("\t--help (-h)\tShow this help message") print("\t--rule (-r)\tSpecify a ruleset file path (default will run data/yara/index.yara)") print("\t--all (-a)\tScan all stored files (default if no session is open)") print("") arg_rule = "" arg_scan_all = False try: opts, argv = getopt.getopt(self.args[1:], "hr:a", ["help", "rule=", "all"]) except getopt.GetoptError as e: print(e) return for opt, value in opts: if opt in ("-h", "--help"): help() return elif opt in ("-r", "--rule"): arg_rule = value elif opt in ("-a", "--all"): arg_scan_all = True # If no custom ruleset is specified, we use the default one. if not arg_rule: arg_rule = "data/yara/index.yara" # Check if the selected ruleset actually exists. if not os.path.exists(arg_rule): print_error("No valid Yara ruleset at {0}".format(arg_rule)) return # Compile all rules from given ruleset. rules = yara.compile(arg_rule) files = [] # If there is a session open and the user didn't specifically # request to scan the full repository, we just add the currently # opened file's path. if __session__.is_set() and not arg_scan_all: files.append(__session__.file) # Otherwise we loop through all files in the repository and queue # them up for scan. else: print_info("Scanning all stored files...") db = Database() samples = db.find(key="all") for sample in samples: files.append(sample) for entry in files: print_info("Scanning {0} ({1})".format(entry.name, entry.sha256)) # Check if the entry has a path attribute. This happens when # there is a session open. We need to distinguish this just for # the cases where we're scanning an opened file which has not been # stored yet. if hasattr(entry, "path"): entry_path = entry.path # This should be triggered only when scanning the full repository. else: entry_path = get_sample_path(entry.sha256) rows = [] for match in rules.match(entry_path): for string in match.strings: rows.append([match.rule, string[1], string[0], string[2]]) if rows: header = ["Rule", "String", "Offset", "Content"] print(table(header=header, rows=rows))
def cmd_tags(self, *args): def usage(): print("usage: tags [-h] [-a=tags] [-d=tag]") def help(): usage() print("") print("Options:") print("\t--help (-h)\tShow this help message") print("\t--add (-a)\tAdd tags to the opened file (comma separated)") print("\t--delete (-d)\tDelete a tag from the opened file") print("") try: opts, argv = getopt.getopt(args, "ha:d:", ["help", "add=", "delete="]) except getopt.GetoptError as e: print(e) usage() return arg_add = None arg_delete = None for opt, value in opts: if opt in ("-h", "--help"): help() return elif opt in ("-a", "--add"): arg_add = value elif opt in ("-d", "--delete"): arg_delete = value # This command requires a session to be opened. if not __session__.is_set(): print_error("No session opened") 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 not arg_add and not arg_delete: print_error("You need to specify an option, either add or delete") return if arg_add: # Add specified tags to the database's entry belonging to # the opened file. db = Database() db.add_tags(__session__.file.sha256, arg_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...") __session__.set(__session__.file.path) if arg_delete: # TODO pass
def cmd_store(self, *args): def usage(): print("usage: store [-h] [-d] [-f <path>] [-s <size>] [-y <type>] [-n <name>] [-t]") def help(): usage() print("") print("Options:") print("\t--help (-h)\tShow this help message") print("\t--delete (-d)\tDelete the original file") print("\t--folder (-f)\tSpecify a folder to import") print("\t--file-size (-s)\tSpecify a maximum file size") print("\t--file-type (-y)\tSpecify a file type pattern") print("\t--file-name (-n)\tSpecify a file name pattern") print("\t--tags (-t)\tSpecify a list of comma-separated tags") print("") try: opts, argv = getopt.getopt( args, "hdf:s:y:n:t:", ["help", "delete", "folder=", "file-size=", "file-type=", "file-name=", "tags="] ) except getopt.GetoptError as e: print(e) usage() return arg_delete = False arg_folder = False arg_file_size = None arg_file_type = None arg_file_name = None arg_tags = None for opt, value in opts: if opt in ("-h", "--help"): help() return elif opt in ("-d", "--delete"): arg_delete = True elif opt in ("-f", "--folder"): arg_folder = value elif opt in ("-s", "--file-size"): arg_file_size = value elif opt in ("-y", "--file-type"): arg_file_type = value elif opt in ("-n", "--file-name"): arg_file_name = value elif opt in ("-t", "--tags"): arg_tags = value def add_file(obj, tags=None): if get_sample_path(obj.sha256): print_warning('Skip, file "{0}" appears to be already stored'.format(obj.name)) return False # Store file to the local repository. new_path = store_sample(obj) if new_path: # Add file to the database. status = self.db.add(obj=obj, tags=tags) print_success('Stored file "{0}" to {1}'.format(obj.name, new_path)) # Delete the file if requested to do so. if arg_delete: try: os.unlink(obj.path) except Exception as e: print_warning("Failed deleting file: {0}".format(e)) return True # If the user specified the --folder flag, we walk recursively and try # to add all contained files to the local repository. # This is note going to open a new session. # TODO: perhaps disable or make recursion optional? if arg_folder: # Check if the specified folder is valid. if os.path.isdir(arg_folder): # Walk through the folder and subfolders. for dir_name, dir_names, file_names in os.walk(arg_folder): # Add each collected file. for file_name in file_names: file_path = os.path.join(dir_name, file_name) if not os.path.exists(file_path): continue # Check if the file name matches the provided pattern. if arg_file_name: if not fnmatch.fnmatch(file_name, arg_file_name): # print_warning("Skip, file \"{0}\" doesn't match the file name pattern".format(file_path)) continue # Check if the file type matches the provided pattern. if arg_file_type: if arg_file_type not in File(file_path).type: # print_warning("Skip, file \"{0}\" doesn't match the file type".format(file_path)) continue # Check if file exceeds maximum size limit. if arg_file_size: # Obtain file size. if os.path.getsize(file_path) > arg_file_size: print_warning('Skip, file "{0}" is too big'.format(file_path)) continue file_obj = File(file_path) # Add file. add_file(file_obj, arg_tags) else: print_error("You specified an invalid folder: {0}".format(arg_folder)) # Otherwise we try to store the currently opened file, if there is any. else: if __session__.is_set(): # Add file. if add_file(__session__.file, arg_tags): # Open session to the new file. self.cmd_open(*[__session__.file.sha256]) else: print_error("No session opened")