def get_workspace(path, format): import viv_utils logger.debug("generating vivisect workspace for: %s", path) if format == "auto": if not is_supported_file_type(path): raise UnsupportedFormatError() vw = viv_utils.getWorkspace(path) elif format == "pe": vw = viv_utils.getWorkspace(path) elif format == "sc32": vw = get_shellcode_vw(path, arch="i386") elif format == "sc64": vw = get_shellcode_vw(path, arch="amd64") logger.debug("%s", get_meta_str(vw)) return vw
def configure(self): parser = self.get_OptionParser() (self.options, self.args) = parser.parse_args() self.set_logging_level() if self.options.list_plugins: self.print_plugin_list() exit(0) TRY_HELP_MSG = "Try '%s -h' for more information" % parser.get_prog_name( ) # TODO handle multiple files? if len(self.args) != 1: parser.error("Please provide a valid file path\n%s" % TRY_HELP_MSG) self.sample_file_path = self.args[0] # TODO handle directories? if not os.path.isfile(self.sample_file_path): parser.error("'%s' is not a file\n%s" % (self.sample_file_path, TRY_HELP_MSG)) if not os.path.exists(self.sample_file_path): parser.error("File '%s' does not exist\n%s" % (self.sample_file_path, TRY_HELP_MSG)) self.vivisect_workspace = viv_utils.getWorkspace(self.sample_file_path) self.functions_to_analyze = self.select_functions() self.selected_plugins = self.select_plugins()
def sample_39c05b15e9834ac93f206bc114d0a00c357c888db567ba8f5345da0529cbed41(): path = os.path.join( CD, "data", "39c05b15e9834ac93f206bc114d0a00c357c888db567ba8f5345da0529cbed41.dll_", ) return Sample(viv_utils.getWorkspace(path), path)
def configure(self): parser = self.get_OptionParser() (self.options, self.args) = parser.parse_args() self.set_logging_level() if self.options.list_plugins: self.print_plugin_list() sys.exit(0) TRY_HELP_MSG = "Try '%s -h' for more information" % parser.get_prog_name() # TODO handle multiple files? if len(self.args) != 1: parser.error("Please provide a valid file path\n%s" % TRY_HELP_MSG) self.sample_file_path = self.args[0] # TODO handle directories? if not os.path.isfile(self.sample_file_path): parser.error("'%s' is not a file\n%s" % (self.sample_file_path, TRY_HELP_MSG)) if not os.path.exists(self.sample_file_path): parser.error("File '%s' does not exist\n%s" % (self.sample_file_path, TRY_HELP_MSG)) self.vivisect_workspace = viv_utils.getWorkspace(self.sample_file_path) self.functions_to_analyze = self.select_functions() self.selected_plugins = self.select_plugins()
def main(): # default to INFO, unless otherwise changed logging.basicConfig(level=logging.WARNING) parser = make_parser() options, args = parser.parse_args() set_logging_level(options.debug, options.verbose) if options.list_plugins: print_plugin_list() sys.exit(0) sample_file_path = parse_sample_file_path(parser, args) min_length = parse_min_length_option(options.min_length) if options.all_strings: floss_logger.info("Extracting static strings...") print_all_strings(sample_file_path, min_length=min_length, quiet=options.quiet) with open(sample_file_path, "rb") as f: magic = f.read(2) if magic != "MZ": floss_logger.error("FLOSS currently supports the following formats: PE") return floss_logger.info("Generating vivisect workspace") vw = viv_utils.getWorkspace(sample_file_path) selected_functions = select_functions(vw, options.functions) floss_logger.debug("Selected the following functions: %s", ", ".join(map(hex, selected_functions))) selected_plugin_names = select_plugins(options.plugins) floss_logger.debug("Selected the following plugins: %s", ", ".join(map(str, selected_plugin_names))) selected_plugins = filter(lambda p: str(p) in selected_plugin_names, get_all_plugins()) time0 = time() floss_logger.info("Identifying decoding functions...") decoding_functions_candidates = im.identify_decoding_functions(vw, selected_plugins, selected_functions) if not options.quiet: print_identification_results(sample_file_path, decoding_functions_candidates) floss_logger.info("Decoding strings...") function_index = viv_utils.InstructionFunctionIndex(vw) decoded_strings = decode_strings(vw, function_index, decoding_functions_candidates) print_decoding_results(decoded_strings, min_length, options.group_functions, quiet=options.quiet) floss_logger.info("Extracting stackstrings...") print_stack_strings(stackstrings.extract_stackstrings(vw, selected_functions), min_length, quiet=options.quiet) if options.ida_python_file: floss_logger.info("Creating IDA script...") create_script(sample_file_path, options.ida_python_file, decoded_strings) time1 = time() if not options.quiet: print("Finished execution after %f seconds" % (time1 - time0))
def get_workspace(path, format, sigpaths): """ load the program at the given path into a vivisect workspace using the given format. also apply the given FLIRT signatures. supported formats: - pe - elf - shellcode 32-bit - shellcode 64-bit - auto this creates and analyzes the workspace; however, it does *not* save the workspace. this is the responsibility of the caller. """ # lazy import enables us to not require viv if user wants SMDA, for example. import viv_utils logger.debug("generating vivisect workspace for: %s", path) if format == "auto": if not is_supported_format(path): raise UnsupportedFormatError() # don't analyze, so that we can add our Flirt function analyzer first. vw = viv_utils.getWorkspace(path, analyze=False, should_save=False) elif format in {"pe", "elf"}: vw = viv_utils.getWorkspace(path, analyze=False, should_save=False) elif format == "sc32": # these are not analyzed nor saved. vw = viv_utils.getShellcodeWorkspaceFromFile(path, arch="i386", analyze=False) elif format == "sc64": vw = viv_utils.getShellcodeWorkspaceFromFile(path, arch="amd64", analyze=False) else: raise ValueError("unexpected format: " + format) viv_utils.flirt.register_flirt_signature_analyzers(vw, sigpaths) vw.analyze() logger.debug("%s", get_meta_str(vw)) return vw
def __init__(self, sample_file_path): viv_utils.LoggingObject.__init__(self) self.vivisect_workspace = viv_utils.getWorkspace(sample_file_path) self.function_index = viv_utils.InstructionFunctionIndex( self.vivisect_workspace) # TODO do we need a set for the decoded strings? self.decoded_strings = set([])
def search(): """ Attempts to find potential device names in the currently opened binary, it starts by searching for Unicode device names, if this fails then it utilises FLOSS to search for stack based and obfuscated strings. """ if not find_unicode_device_name(): print( "Unicode device name not found, attempting to find obfuscated and stack based strings." ) try: import floss import floss.identification_manager import floss.main import floss.stackstrings import viv_utils except ImportError: print( "Please install FLOSS to continue, see: https://github.com/fireeye/flare-floss/" ) return logging.basicConfig( ) #To avoid logger handler not found errors, from https://github.com/fireeye/flare-floss/blob/66f67a49a38ae028a5e86f1de743c384d5271901/scripts/idaplugin.py#L154 logging.getLogger('vtrace.platforms.win32').setLevel(logging.ERROR) sample_file_path = idc.GetInputFile() try: vw = viv_utils.getWorkspace(sample_file_path, should_save=False) except Exception as e: print("Vivisect failed to load the input file: {0}".format( e.message)) return functions = set(vw.getFunctions()) plugins = floss.main.get_all_plugins() device_names = set() stack_strings = floss.stackstrings.extract_stackstrings(vw, functions, 4, no_filter=True) for i in stack_strings: device_names.add(i) dec_func_candidates = floss.identification_manager.identify_decoding_functions( vw, plugins, functions) decoded_strings = floss.main.decode_strings(vw, dec_func_candidates, 4, no_filter=True) if len(decoded_strings) > 0: for i in decoded_strings: device_names.add(str(i.s)) print("Potential device names from obfuscated or stack strings:") for i in device_names: print(i) else: print("No obfuscated or stack strings found :(")
def main(argv=None): """ :param argv: optional command line arguments, like sys.argv[1:] :return: 0 on success, non-zero on failure """ logging.basicConfig(level=logging.WARNING) parser = make_parser() if argv is not None: options, args = parser.parse_args(argv[1:]) else: options, args = parser.parse_args() set_logging_level(options.debug, options.verbose) if options.list_plugins: print_plugin_list() return 0 sample_file_path = parse_sample_file_path(parser, args) min_length = parse_min_length_option(options.min_length) if not is_workspace_file(sample_file_path): with open(sample_file_path, "rb") as f: magic = f.read(2) if not options.no_static_strings and not options.functions: floss_logger.info("Extracting static strings...") print_static_strings(sample_file_path, min_length=min_length, quiet=options.quiet) if options.no_decoded_strings and options.no_stack_strings: # we are done return 0 if magic not in SUPPORTED_FILE_MAGIC: floss_logger.error("FLOSS currently supports the following formats for string decoding and stackstrings: PE") return 1 if os.path.getsize(sample_file_path) > MAX_FILE_SIZE: floss_logger.error("FLOSS cannot extract obfuscated strings from files larger than %d bytes" % (MAX_FILE_SIZE)) return 1 floss_logger.info("Generating vivisect workspace...") else: floss_logger.info("Loading existing vivisect workspace...") # expert profile settings if options.expert: options.save_workspace = True options.group_functions = True options.quiet = False try: vw = viv_utils.getWorkspace(sample_file_path, should_save=options.save_workspace) except Exception, e: floss_logger.error("Vivisect failed to load the input file: {0}".format(e.message), exc_info=options.verbose) return 1
def main(argv=None): """ :param argv: optional command line arguments, like sys.argv[1:] :return: 0 on success, non-zero on failure """ logging.basicConfig(level=logging.WARNING) parser = make_parser() if argv is not None: options, args = parser.parse_args(argv[1:]) else: options, args = parser.parse_args() set_logging_level(options.debug, options.verbose) if options.list_plugins: print_plugin_list() return 0 sample_file_path = parse_sample_file_path(parser, args) min_length = parse_min_length_option(options.min_length) if not is_workspace_file(sample_file_path): with open(sample_file_path, "rb") as f: magic = f.read(2) if not options.no_static_strings: floss_logger.info("Extracting static strings...") print_static_strings(sample_file_path, min_length=min_length, quiet=options.quiet) if options.no_decoded_strings and options.no_stack_strings: # we are done return 0 if magic not in SUPPORTED_FILE_MAGIC: floss_logger.error("FLOSS currently supports the following formats for string decoding and stackstrings: PE") return 1 if os.path.getsize(sample_file_path) > MAX_FILE_SIZE: floss_logger.error("FLOSS cannot extract obfuscated strings from files larger than %d bytes" % (MAX_FILE_SIZE)) return 1 floss_logger.info("Generating vivisect workspace...") else: floss_logger.info("Loading existing vivisect workspace...") # expert profile settings if options.expert: options.save_workspace = True options.group_functions = True options.quiet = False try: vw = viv_utils.getWorkspace(sample_file_path, should_save=options.save_workspace) except Exception, e: floss_logger.error("Vivisect failed to load the input file: {0}".format(e.message), exc_info=options.verbose) return 1
def get_workspace(path, format, should_save=True): import viv_utils logger.debug("generating vivisect workspace for: %s", path) if format == "auto": if not is_supported_file_type(path): raise UnsupportedFormatError() vw = viv_utils.getWorkspace(path, should_save=should_save) elif format == "pe": vw = viv_utils.getWorkspace(path, should_save=should_save) elif format == "sc32": vw = get_shellcode_vw(path, arch="i386", should_save=should_save) elif format == "sc64": vw = get_shellcode_vw(path, arch="amd64", should_save=should_save) else: raise ValueError("unexpected format: " + format) logger.debug("%s", get_meta_str(vw)) return vw
def test_select_all_functions(samples_path): file_path = os.path.join(samples_path, "6ee35da59f92f71e757d4d5b964ecf00") vivisect_workspace = viv_utils.getWorkspace(file_path) sys.argv = [sys.argv[0], file_path] sdc = floss_main.StringDecoderConfig() sdc.configure() assert cmp(vivisect_workspace.getFunctions(), sdc.select_functions()) == 0
def load_workspace(sample_file_path, save_workspace): if is_workspace_file(sample_file_path): floss_logger.info("Loading existing vivisect workspace...") else: if not is_supported_file_type(sample_file_path): raise LoadNotSupportedError("FLOSS currently supports the following formats for string decoding and " "stackstrings: PE\nYou can analyze shellcode using the -s switch. See the " "help (-h) for more information.") floss_logger.info("Generating vivisect workspace...") return viv_utils.getWorkspace(sample_file_path, should_save=save_workspace)
def test_FAG_get_caller_vas(samples_path): file_path = os.path.join(samples_path, "6ee35da59f92f71e757d4d5b964ecf00.viv") vivisect_workspace = viv_utils.getWorkspace(file_path) f*g = FunctionArgumentGetter(vivisect_workspace) caller_vas = f*g.get_caller_vas(0x40166C) answer = set([0x401698, 0x4018AD, 0x401CE0]) assert answer.issubset(caller_vas) and caller_vas.issubset(answer)
def extract_strings(sample_path): """ Deobfuscate strings from sample_path """ vw = viv_utils.getWorkspace(sample_path) function_index = viv_utils.InstructionFunctionIndex(vw) decoding_functions_candidates = identify_decoding_functions(vw) decoded_strings = floss_main.decode_strings(vw, function_index, decoding_functions_candidates) decoded_stackstrings = stackstrings.extract_stackstrings(vw) decoded_strings.extend(decoded_stackstrings) return [ds.s for ds in decoded_strings]
def load_workspace(sample_file_path, save_workspace): # inform user that getWorkspace implicitly loads saved workspace if .viv file exists if is_workspace_file(sample_file_path) or os.path.exists("%s.viv" % sample_file_path): floss_logger.info("Loading existing vivisect workspace...") else: if not is_supported_file_type(sample_file_path): raise LoadNotSupportedError("FLOSS currently supports the following formats for string decoding and " "stackstrings: PE\nYou can analyze shellcode using the -s switch. See the " "help (-h) for more information.") floss_logger.info("Generating vivisect workspace...") return viv_utils.getWorkspace(sample_file_path, should_save=save_workspace)
def extract_strings(sample_path): """ Deobfuscate strings from sample_path """ vw = viv_utils.getWorkspace(sample_path) function_index = viv_utils.InstructionFunctionIndex(vw) decoding_functions_candidates = identify_decoding_functions(vw) decoded_strings = floss_main.decode_strings(vw, function_index, decoding_functions_candidates) selected_functions = floss_main.select_functions(vw, None) decoded_stackstrings = stackstrings.extract_stackstrings(vw, selected_functions) decoded_strings.extend(decoded_stackstrings) return [ds.s for ds in decoded_strings]
def _test_FunctionArgumentGetter_get_function_end(samples_path): file_path = os.path.join(samples_path, "6ee35da59f92f71e757d4d5b964ecf00.viv") vivisect_workspace = viv_utils.getWorkspace(file_path) f*g = FunctionArgumentGetter(vivisect_workspace) answer = {0x4018AD: 0x401CDF, 0x401CE0: 0x402108} ends = {} for function_start in answer.keys(): function_end = f*g.get_function_end(function_start) ends[function_start] = function_end assert cmp(answer, ends) == 0
def test_FAG_get_all_function_contexts_return_addresses(samples_path): file_path = os.path.join(samples_path, "6ee35da59f92f71e757d4d5b964ecf00.viv") vivisect_workspace = viv_utils.getWorkspace(file_path) emu = vivisect_workspace.getEmulator() f*g = FunctionArgumentGetter(vivisect_workspace) answer = [0x40241B, 0x4023E5] all_return_addresses = [] for function_context in f*g.get_all_function_contexts(0x0040424E): all_return_addresses.append(function_context.return_address) assert set(answer) == set(all_return_addresses)
def _main(bin_path, fva): logging.basicConfig(level=logging.DEBUG) vw = viv_utils.getWorkspace(bin_path) emu = vw.getEmulator() d = viv_utils.emulator_drivers.FunctionRunnerEmulatorDriver(emu) m = AMonitor(vw) d.add_monitor(m) logging.getLogger("trace").debug("%s %s %s %s", vw, emu, d, m) d.runFunction(int(fva, 0x10), maxhit=1)
def _test_detection(self, test_path): try: expected_functions = set(self.spec["Decoding routines"][self.platform][self.arch]) except KeyError: expected_functions = set([]) if not expected_functions: return vw = viv_utils.getWorkspace(test_path) fs = map(lambda p: p[0], identify_decoding_functions(vw).get_top_candidate_functions()) found_functions = set(fs) if not (expected_functions <= found_functions): raise FLOSSDecodingFunctionNotFound(expected_functions, found_functions)
def test_FAG_get_context_via_monitor_return_addresses(samples_path): file_path = os.path.join(samples_path, "6ee35da59f92f71e757d4d5b964ecf00.viv") vivisect_workspace = viv_utils.getWorkspace(file_path) emu = vivisect_workspace.getEmulator() f*g = FunctionArgumentGetter(vivisect_workspace) caller_va = 0x401698 function_va = 0x40166C all_return_addresses = [] for function_context in f*g.get_contexts_via_monitor(caller_va, function_va): all_return_addresses.append(function_context.return_address) answer = set([0x4016C8, 0x4016D3]) assert answer == set(all_return_addresses)
def _test_detection(self, test_path): try: expected_functions = set(self.spec["Decoding routines"][self.platform][self.arch]) except KeyError: expected_functions = set([]) if not expected_functions: return vw = viv_utils.getWorkspace(test_path) top_functions, _ = identify_decoding_functions(vw) found_functions = set(top_functions) if not (expected_functions <= found_functions): raise FLOSSDecodingFunctionNotFound(expected_functions, found_functions)
def _test_strings(self, test_path): expected_strings = set(self.spec["Decoded strings"]) if not expected_strings: return arch = self.spec.get("Shellcode Architecture") if arch in ("i386", "amd64"): vw = viv_utils.getShellcodeWorkspaceFromFile(test_path, arch) found_strings = set(extract_strings(vw)) else: # default assumes pe vw = viv_utils.getWorkspace(test_path) found_strings = set(extract_strings(vw)) if not (expected_strings <= found_strings): raise FLOSSStringsNotExtracted(expected_strings, found_strings)
def test_FAG_get_context_via_monitor_return_addresses(samples_path): file_path = os.path.join(samples_path, "6ee35da59f92f71e757d4d5b964ecf00.viv") vivisect_workspace = viv_utils.getWorkspace(file_path) emu = vivisect_workspace.getEmulator() f*g = FunctionArgumentGetter(vivisect_workspace) caller_va = 0x401698 function_va = 0x40166C all_return_addresses = [] for function_context in f*g.get_contexts_via_monitor( caller_va, function_va): all_return_addresses.append(function_context.return_address) answer = set([0x4016C8, 0x4016D3]) assert answer == set(all_return_addresses)
def _test_strings(self, test_path): expected_strings = set(self.spec["Decoded strings"]) if not expected_strings: return test_shellcode = self.spec.get("Test shellcode") if test_shellcode: with open(test_path, "rb") as f: shellcode_data = f.read() vw = viv_utils.getShellcodeWorkspace(shellcode_data) # TODO provide arch from test.yml found_strings = set(extract_strings(vw)) else: vw = viv_utils.getWorkspace(test_path) found_strings = set(extract_strings(vw)) if not (expected_strings <= found_strings): raise FLOSSStringsNotExtracted(expected_strings, found_strings)
def search(): """ Attempts to find potential device names in the currently opened binary, it starts by searching for unicode device names, if this fails then it utilises FLOSS to search for stack based and obsfucated strings. """ if not find_unicode_device_name(): print "Unicode device name not found, attempting to find obsfucated and stack based strings." try: import floss import floss.identification_manager import floss.main import floss.stackstrings import viv_utils except: print "Please install FLOSS to continue, see: https://github.com/fireeye/flare-floss/" sample_file_path = idc.GetInputFile() try: vw = viv_utils.getWorkspace(sample_file_path, should_save=False) except Exception, e: print("Vivisect failed to load the input file: {0}".format( e.message)) return functions = set(vw.getFunctions()) plugins = floss.main.get_all_plugins() device_names = set() stack_strings = floss.stackstrings.extract_stackstrings(vw, functions) for i in stack_strings: device_names.add(i) dec_func_candidates = floss.identification_manager.identify_decoding_functions( vw, plugins, functions) func_index = viv_utils.InstructionFunctionIndex(vw) decoded_strings = floss.main.decode_strings(vw, func_index, dec_func_candidates) if len(decoded_strings) > 0: for i in decoded_strings: device_names.add(str(i.s)) print "Potential device names from obsfucated or stack strings:" for i in device_names: print i else: print "No obsfucated or stack strings found :("
def _main(bin_path, ofva): fva = int(ofva, 0x10) logging.basicConfig(level=logging.DEBUG) vw = viv_utils.getWorkspace(bin_path) index = viv_utils.InstructionFunctionIndex(vw) # optimization: avoid re-processing the same function repeatedly called_fvas = set([]) for callerva in vw.getCallers(fva): callerfva = index[callerva] # the address of the function that contains this instruction if callerfva in called_fvas: continue emulate_function(vw, index[callerva], fva) called_fvas.add(callerfva) return
def load_vw( sample_path: str, format: str, sigpaths: str, should_save_workspace: bool = False, ) -> VivWorkspace: if format not in ("sc32", "sc64"): if not is_supported_file_type(sample_path): raise WorkspaceLoadError( "FLOSS currently supports the following formats for string decoding and stackstrings: PE\n" "You can analyze shellcode using the --format sc32|sc64 switch. See the help (-h) for more information." ) # get shellcode type based on sample file extension if format == "auto" and sample_path.endswith(EXTENSIONS_SHELLCODE_32): format = "sc32" elif format == "auto" and sample_path.endswith(EXTENSIONS_SHELLCODE_64): format = "sc64" if format == "sc32": vw = viv_utils.getShellcodeWorkspaceFromFile(sample_path, arch="i386", analyze=False) elif format == "sc64": vw = viv_utils.getShellcodeWorkspaceFromFile(sample_path, arch="amd64", analyze=False) else: vw = viv_utils.getWorkspace(sample_path, analyze=False, should_save=False) viv_utils.flirt.register_flirt_signature_analyzers(vw, sigpaths) vw.analyze() if should_save_workspace: logger.debug("saving workspace") try: vw.saveWorkspace() except IOError: logger.info("source directory is not writable, won't save intermediate workspace") else: logger.debug("not saving workspace") return vw
def _main(bin_path, ofva): fva = int(ofva, 0x10) logging.basicConfig(level=logging.DEBUG) vw = viv_utils.getWorkspace(bin_path) index = viv_utils.InstructionFunctionIndex(vw) # optimization: avoid re-processing the same function repeatedly called_fvas = set([]) for callerva in vw.getCallers(fva): callerfva = index[ callerva] # the address of the function that contains this instruction if callerfva in called_fvas: continue emulate_function(vw, index[callerva], fva) called_fvas.add(callerfva) return
def main(argv=None): if argv is None: argv = sys.argv[1:] parser = argparse.ArgumentParser(description="FLIRT match each function") parser.add_argument("sample", type=str, help="Path to sample to analyze") parser.add_argument( "-F", "--function", type=lambda x: int(x, 0x10), help="match a specific function by VA, rather than add functions", ) parser.add_argument( "--signature", action="append", dest="signatures", type=str, default=[], help= "use the given signatures to identify library functions, file system paths to .sig/.pat files.", ) parser.add_argument("-d", "--debug", action="store_true", help="Enable debugging output on STDERR") parser.add_argument("-q", "--quiet", action="store_true", help="Disable all output but errors") args = parser.parse_args(args=argv) if args.quiet: logging.basicConfig(level=logging.ERROR) logging.getLogger().setLevel(logging.ERROR) elif args.debug: logging.basicConfig(level=logging.DEBUG) logging.getLogger().setLevel(logging.DEBUG) else: logging.basicConfig(level=logging.INFO) logging.getLogger().setLevel(logging.INFO) # disable vivisect-related logging, it's verbose and not relevant for capa users capa.main.set_vivisect_log_level(logging.CRITICAL) analyzers = [] for sigpath in args.signatures: sigs = capa.main.load_flirt_signature(sigpath) with capa.main.timing("flirt: compiling sigs"): matcher = flirt.compile(sigs) analyzer = viv_utils.flirt.FlirtFunctionAnalyzer(matcher, sigpath) logger.debug("registering viv function analyzer: %s", repr(analyzer)) analyzers.append(analyzer) vw = viv_utils.getWorkspace(args.sample, analyze=True, should_save=False) functions = vw.getFunctions() if args.function: functions = [args.function] for function in functions: logger.debug("matching function: 0x%04x", function) for analyzer in analyzers: name = viv_utils.flirt.match_function_flirt_signatures( analyzer.matcher, vw, function) if name: print("0x%04x: %s" % (function, name)) return 0
if not find_unicode_device_name(): print "Device name not found, attempting to find obsfucated and stack based strings." try: import floss import floss.identification_manager import floss.main import floss.stackstrings import viv_utils except: print "Please install FLOSS to continue, see: https://github.com/fireeye/flare-floss/" sample_file_path = idc.GetInputFile() try: vw = viv_utils.getWorkspace(sample_file_path, should_save=False) except Exception, e: print("Vivisect failed to load the input file: {0}".format(e.message)) sys.exit(1) functions = set(vw.getFunctions()) plugins = floss.main.get_all_plugins() device_names = set() stack_strings = floss.stackstrings.extract_stackstrings(vw, functions) for i in stack_strings: device_names.add(i) decoding_functions_candidates = floss.identification_manager.identify_decoding_functions( vw, plugins, functions) function_index = viv_utils.InstructionFunctionIndex(vw) decoded_strings = floss.main.decode_strings(vw, function_index,
def main(argv=None): """ :param argv: optional command line arguments, like sys.argv[1:] """ logging.basicConfig(level=logging.WARNING) parser = make_parser() if argv is not None: options, args = parser.parse_args(argv) else: options, args = parser.parse_args() set_logging_level(options.debug, options.verbose) if options.list_plugins: print_plugin_list() sys.exit(0) sample_file_path = parse_sample_file_path(parser, args) min_length = parse_min_length_option(options.min_length) with open(sample_file_path, "rb") as f: magic = f.read(2) if options.all_strings: floss_logger.info("Extracting static strings...") print_static_strings(sample_file_path, min_length=min_length, quiet=options.quiet) if magic not in SUPPORTED_FILE_MAGIC: floss_logger.error("FLOSS currently supports the following formats: PE") if not options.all_strings: floss_logger.error("Recommend passing flag `-a` to extract static strings from any file type.") return if os.path.getsize(sample_file_path) > MAX_FILE_SIZE: floss_logger.error("FLOSS cannot emulate files larger than %d bytes" % (MAX_FILE_SIZE)) if not options.all_strings: floss_logger.error("Recommend passing flag `-a` to extract static strings from any sized file.") return floss_logger.info("Generating vivisect workspace") vw = viv_utils.getWorkspace(sample_file_path) selected_functions = select_functions(vw, options.functions) floss_logger.debug("Selected the following functions: %s", ", ".join(map(hex, selected_functions))) selected_plugin_names = select_plugins(options.plugins) floss_logger.debug("Selected the following plugins: %s", ", ".join(map(str, selected_plugin_names))) selected_plugins = filter(lambda p: str(p) in selected_plugin_names, get_all_plugins()) time0 = time() floss_logger.info("Identifying decoding functions...") decoding_functions_candidates = im.identify_decoding_functions(vw, selected_plugins, selected_functions) if not options.quiet: print_identification_results(sample_file_path, decoding_functions_candidates) floss_logger.info("Decoding strings...") function_index = viv_utils.InstructionFunctionIndex(vw) decoded_strings = decode_strings(vw, function_index, decoding_functions_candidates) print_decoding_results(decoded_strings, min_length, options.group_functions, quiet=options.quiet) floss_logger.info("Extracting stackstrings...") print_stack_strings(stackstrings.extract_stackstrings(vw, selected_functions), min_length, quiet=options.quiet) if options.ida_python_file: floss_logger.info("Creating IDA script...") create_script(sample_file_path, options.ida_python_file, decoded_strings) time1 = time() if not options.quiet: print("Finished execution after %f seconds" % (time1 - time0))
if not find_unicode_device_name(): print "Device name not found, attempting to find obsfucated and stack based strings." try: import floss import floss.identification_manager import floss.main import floss.stackstrings import viv_utils except: print "Please install FLOSS to continue, see: https://github.com/fireeye/flare-floss/" sample_file_path = idc.GetInputFile() try: vw = viv_utils.getWorkspace(sample_file_path, should_save=False) except Exception, e: print("Vivisect failed to load the input file: {0}".format(e.message)) sys.exit(1) functions = set(vw.getFunctions()) plugins = floss.main.get_all_plugins() device_names = set() stack_strings = floss.stackstrings.extract_stackstrings(vw, functions) for i in stack_strings: device_names.add(i) decoding_functions_candidates = floss.identification_manager.identify_decoding_functions(vw, plugins, functions) function_index = viv_utils.InstructionFunctionIndex(vw) decoded_strings = floss.main.decode_strings(vw, function_index, decoding_functions_candidates) if len(decoded_strings) > 0:
def sample_bfb9b5391a13d0afd787e87ab90f14f5(): path = os.path.join(CD, "data", "bfb9b5391a13d0afd787e87ab90f14f5.dll_") return Sample(viv_utils.getWorkspace(path), path)
def run(self): db = Database() # Get Options if "min_length" in self.request.POST: min_len = self.request.POST['min_length'] else: min_len = 4 if 'file_id' in self.request.POST: file_id = self.request.POST['file_id'] # Check to see if we already have strings stored. new_strings = db.get_strings(file_id) if new_strings: string_id = new_strings._id else: file_object = db.get_filebyid(file_id) # Always get ASCII and Unicode file_data = file_object.read() ascii_strings = self.ascii_strings(file_data, 4) unicode_strings = self.unicode_strings(file_data, 4) if HAVE_FLOSS: # Advacned Floss needs a file on disk with tempfile.NamedTemporaryFile() as tmp: tmp.write(file_data) file_path = tmp.name if self.is_supported_file_type(file_path): try: vw = viv_utils.getWorkspace(file_path, should_save=False) except Exception: print "ahhhhhhhhhhhhhh" raise # Decode Strings #decoding_functions_candidates = im.identify_decoding_functions(vw, selected_plugins, selected_functions) #function_index = viv_utils.InstructionFunctionIndex(vw) #decoded_strings = decode_strings(vw, function_index, decoding_functions_candidates) # Stack Strings # Generate the final output file string_list = '##### ASCII Strings #####\n {0} \n ##### Unicode Strings #####\n {1}'.format(ascii_strings, unicode_strings) ''' String lists can get larger than the 16Mb bson limit Need to store in GridFS ''' store_data = {'file_id': file_id, 'string_list': string_list} string_id = db.create_file(string_list, 'session_id', 'sha256', '{0}_strings.txt'.format(file_id)) print string_id self.render_type = 'html' self.render_data = '<td><a class="btn btn-success" role="button" href="/download/file/{0}">Download</a></td>'.format( string_id)
def pma_lab_12_04(): path = os.path.join(CD, "data", "Practical Malware Analysis Lab 12-04.exe_") return Sample(viv_utils.getWorkspace(path), path)
def sample_lab21_01(): path = os.path.join(CD, "data", "Practical Malware Analysis Lab 21-01.exe_") return Sample(viv_utils.getWorkspace(path), path)
def sample_c91887d861d9bd4a5872249b641bc9f9(): path = os.path.join(CD, "data", "c91887d861d9bd4a5872249b641bc9f9.exe_") return Sample(viv_utils.getWorkspace(path), path)