def identify_decoding_functions(vw): selected_functions = floss_main.select_functions(vw, None) selected_plugin_names = floss_main.select_plugins(None) selected_plugins = filter(lambda p: str(p) in selected_plugin_names, floss_main.get_all_plugins()) decoding_functions_candidates = im.identify_decoding_functions( vw, selected_plugins, selected_functions) return decoding_functions_candidates
def identify_decoding_functions(vw): selected_functions = floss_main.select_functions(vw, None) selected_plugin_names = floss_main.select_plugins(None) selected_plugins = [ p for p in floss_main.get_all_plugins() if str(p) in selected_plugin_names ] decoding_functions_candidates = im.identify_decoding_functions( vw, selected_plugins, selected_functions) return decoding_functions_candidates
def each(self, target): self.results = { 'warnings': [], 'static_strings': [], 'decoded_strings': [], 'stack_strings': [] } try: data = open(target, "r").read(MAX_FILESIZE) except (IOError, OSError) as e: self.log('error', 'Cannot open file {}'.format(target)) self.results = None return False # Load list of IOC's try: with open(self.interesting_strings_file) as f: self.interesting_strings = f.read().splitlines() self.log( 'info', 'Loaded interesting strings from {}'.format( self.interesting_strings_file)) except: # No IOC file, create an empty list self.log('info', 'No file with interesting strings defined') self.interesting_strings = [] # Load list of ignored strings try: with open(self.ignored_strings_file) as f: self.ignored_strings = f.read().splitlines() self.log( 'info', 'Loaded ignored strings from {}'.format( self.ignored_strings_file)) except: # No IOC file, create an empty list self.log('info', 'No file with ignored strings defined') self.ignored_strings = [] # Extract static strings static_strings = re.findall( "[\x1f-\x7e]{" + str(self.minimum_string_len) + ",}", data) for s in re.findall( "(?:[\x1f-\x7e][\x00]){" + str(self.minimum_string_len) + ",}", data): static_strings.append(s.decode("utf-16le")) if self.maximum_string_len != 0: for i, s in enumerate(static_strings): static_strings[i] = s[:self.maximum_string_len] if self.maximum_strings != 0 and len( static_strings) > self.maximum_strings: self.log( 'warning', 'Maximum number of strings reached ({})'.format( str(self.maximum_strings))) static_strings = static_strings[:self.maximum_strings] static_strings.append("[snip]") try: # Prepare Floss for extracting hidden & encoded strings vw = vivisect.VivWorkspace() vw.loadFromFile(target) vw.analyze() selected_functions = main.select_functions(vw, None) decoding_functions_candidates = id_man.identify_decoding_functions( vw, main.get_all_plugins(), selected_functions) except Exception as e: self.log('error', 'Cannot analyze file {}'.format(target)) self.results = None return False # Decode & extract hidden & encoded strings try: decoded_strings = main.decode_strings( vw, decoding_functions_candidates, self.minimum_string_len) decoded_strs = main.filter_unique_decoded(decoded_strings) stack_strings = stackstrings.extract_stackstrings( vw, selected_functions, self.minimum_string_len) stack_strings = list(stack_strings) decoded_strings = [ x for x in decoded_strs if not x in static_strings ] except Exception as e: self.log('error', 'Cannot extract strings from {}'.format(target)) self.results = None return False # Populate results[] with found strings if len(decoded_strings) or len(stack_strings): self.log('info', 'Found stack or decoded strings') for k, s in enumerate(decoded_strings): buffer = main.sanitize_string_for_printing(s.s) skip = False for ignore in self.ignored_strings: if str(buffer).find(ignore) >= 0: skip = True break if not skip: self.results['decoded_strings'].append(buffer) self.search_ioc(self.results['decoded_strings']) for k, s in enumerate(stack_strings): skip = False for ignore in self.ignored_strings: if str(s.s).find(ignore) >= 0: skip = True break if not skip: self.results['stack_strings'].append(s.s) self.search_ioc(self.results['stack_strings']) # Populate results[] with static strings self.log('info', 'Found static strings') for s in static_strings: skip = False for ignore in self.ignored_strings: if str(s).find(ignore) >= 0: skip = True break if not skip: self.results['static_strings'].append(s) self.search_ioc(self.results['static_strings']) # Deduplicate warnings self.results['warnings'] = list(dict.fromkeys( self.results['warnings'])) return True
def identify_decoding_functions(vw): selected_functions = floss_main.select_functions(vw, None) selected_plugin_names = floss_main.select_plugins(None) selected_plugins = filter(lambda p: str(p) in selected_plugin_names, floss_main.get_all_plugins()) decoding_functions_candidates = im.identify_decoding_functions(vw, selected_plugins, selected_functions) return decoding_functions_candidates
def run(self): """Run Floss on analyzed file. @return: Floss results dict. """ self.key = "strings" self.floss = self.options.get("floss") self.MIN_STRINGLEN = int(self.options.get("min_str_len")) self.MAX_STRINGLEN = self.options.get("max_str_len") self.MAX_STRINGCNT = self.options.get("max_str_cnt") self.MAX_FILESIZE = 16*1024*1024 STRING_TYPES = [ "decoded", "stack", "static" ] strings = {} if self.task["category"] == "file": if not os.path.exists(self.file_path): raise CuckooProcessingError( "Sample file doesn't exist: \"%s\"" % self.file_path ) try: f = File(self.file_path) filename = os.path.basename(self.task["target"]) base_name = os.path.splitext(filename)[0] ext = filename.split(os.path.extsep)[-1].lower() data = open(self.file_path, "r").read(self.MAX_FILESIZE) except (IOError, OSError) as e: raise CuckooProcessingError("Error opening file %s" % e) # Extract static strings static_strings = re.findall("[\x1f-\x7e]{" + str(self.MIN_STRINGLEN) + ",}", data) for s in re.findall("(?:[\x1f-\x7e][\x00]){" + str(self.MIN_STRINGLEN) + ",}", data): static_strings.append(s.decode("utf-16le")) if self.MAX_STRINGLEN != 0: for i, s in enumerate(static_strings): static_strings[i] = s[:self.MAX_STRINGLEN] if self.MAX_STRINGCNT != 0 and len(static_strings) > self.MAX_STRINGCNT: static_strings = static_strings[:self.MAX_STRINGCNT] static_strings.append("[snip]") package = self.task.get("package") if self.floss and (package == "exe" or ext == "exe" or "PE32" in f.get_type()): # Disable floss verbose logging main.set_logging_levels() try: # Prepare Floss for extracting hidden & encoded strings vw = vivisect.VivWorkspace() vw.loadFromFile(self.file_path) vw.analyze() selected_functions = main.select_functions(vw, None) decoding_functions_candidates = id_man.identify_decoding_functions( vw, main.get_all_plugins(), selected_functions ) except Exception as e: raise CuckooProcessingError("Error analyzing file with vivisect: %s" % e) try: # Decode & extract hidden & encoded strings decoded_strings = main.decode_strings( vw, decoding_functions_candidates, self.MIN_STRINGLEN ) decoded_strs = main.filter_unique_decoded(decoded_strings) stack_strings = stackstrings.extract_stackstrings( vw, selected_functions, self.MIN_STRINGLEN ) stack_strings = list(stack_strings) decoded_strings = [x for x in decoded_strs if not x in static_strings] except Exception as e: raise CuckooProcessingError("Error extracting strings with floss: %s" % e) if len(decoded_strings) or len(stack_strings): # Create annotated scripts if self.options.get("idapro_str_sct"): idapro_sct_name = base_name + ".idb" strings["idapro_sct_name"] = idapro_sct_name main.create_ida_script( self.file_path, os.path.join(self.str_script_path, idapro_sct_name), decoded_strings, stack_strings ) if self.options.get("radare_str_sct"): radare_sct_name = base_name + ".r2" strings["radare_sct_name"] = radare_sct_name main.create_r2_script( self.file_path, os.path.join(self.str_script_path, radare_sct_name), decoded_strings, stack_strings ) if self.options.get("x64dbg_str_sct"): x64dbg_sct_name = base_name + ".json" strings["x64dbg_sct_name"] = x64dbg_sct_name imagebase = vw.filemeta.values()[0]['imagebase'] main.create_x64dbg_database( self.file_path, os.path.join(self.str_script_path, base_name + ".json"), imagebase, decoded_strings ) # convert Floss strings into regular, readable strings for idx, s in enumerate(decoded_strings): decoded_strings[idx] = main.sanitize_string_for_printing(s.s) for idx, s in enumerate(stack_strings): stack_strings[idx] = s.s results = [decoded_strings, stack_strings, static_strings] for idx, str_type in enumerate(STRING_TYPES): strings[str_type] = results[idx] else: strings["static"] = static_strings return strings