def run(self): """Run analysis. @return: structured results. """ self.key = "procmemory" results = [] do_strings = self.options.get("strings", False) nulltermonly = self.options.get("nullterminated_only", True) minchars = str(self.options.get("minchars", 5)).encode("utf-8") if os.path.exists(self.pmemory_path): for dmp in os.listdir(self.pmemory_path): # if we're re-processing this task, this means if zips are enabled, we won't do any reprocessing on the # process dumps (only matters for now for Yara) if not dmp.endswith(".dmp"): continue dmp_path = os.path.join(self.pmemory_path, dmp) if os.path.getsize(dmp_path) == 0: continue dmp_file = File(dmp_path) process_name = "" process_path = "" process_id = int( os.path.splitext(os.path.basename(dmp_path))[0]) for process in self.results.get("behavior", {}).get( "processes", []) or []: if process_id == process["process_id"]: process_name = process["process_name"] process_path = process["module_path"] procdump = ProcDump(dmp_path, pretty=True) proc = dict( file=dmp_path, pid=process_id, name=process_name, path=process_path, yara=dmp_file.get_yara(category="memory"), cape_yara=dmp_file.get_yara(category="CAPE"), address_space=procdump.pretty_print(), ) for hit in proc["cape_yara"]: hit["memblocks"] = dict() for item in hit["addresses"]: memblock = self.get_yara_memblock( proc["address_space"], hit["addresses"][item]) if memblock: hit["memblocks"][item] = memblock # if self.options.get("extract_pe", False) extracted_pes = self.get_procmemory_pe(proc) endlimit = b"" if not HAVE_RE2: endlimit = b"8192" if do_strings: if nulltermonly: apat = b"([\x20-\x7e]{" + minchars + b"," + endlimit + b"})\x00" upat = b"((?:[\x20-\x7e][\x00]){" + minchars + b"," + endlimit + b"})\x00\x00" else: apat = b"[\x20-\x7e]{" + minchars + b"," + endlimit + b"}" upat = b"(?:[\x20-\x7e][\x00]){" + minchars + b"," + endlimit + b"}" matchdict = procdump.search(apat, all=True) strings = matchdict["matches"] matchdict = procdump.search(upat, all=True) ustrings = matchdict["matches"] for ws in ustrings: strings.append(ws.decode("utf-16le").encode("utf-8")) proc["strings_path"] = dmp_path + ".strings" proc["extracted_pe"] = extracted_pes f = open(proc["strings_path"], "wb") f.write(b"\n".join(strings)) f.close() procdump.close() results.append(proc) cape_name = cape_name_from_yara(proc, process_id, self.results) if cape_name and "detections" not in self.results: self.results["detections"] = cape_name return results
def run(self): """Run analysis. @return: list of process dumps with related information. """ self.key = "procdump" procdump_files = [] buf = self.options.get("buffer", 8192) if not os.path.exists(self.procdump_path): return None meta = {} if os.path.exists(self.files_metadata): for line in open(self.files_metadata, "rb"): entry = json.loads(line) filepath = os.path.join(self.analysis_path, entry["path"]) meta[filepath] = { "pids": entry["pids"], "filepath": entry["filepath"], "metadata": entry["metadata"], } file_names = os.listdir(self.procdump_path) for file_name in file_names: file_path = os.path.join(self.procdump_path, file_name) if not meta.get(file_path): continue file_info, pefile_object = File( file_path=file_path, guest_paths=meta[file_path]["metadata"], file_name=file_name).get_all() if pefile_object: self.results.setdefault("pefiles", {}) self.results["pefiles"].setdefault(file_info["sha256"], pefile_object) metastrings = meta[file_path].get("metadata", "").split(";?") if len(metastrings) < 3: continue file_info["process_path"] = metastrings[1] file_info["module_path"] = metastrings[2] file_info["process_name"] = file_info["process_path"].rsplit( "\\", 1)[-1] file_info["pid"] = meta[file_path]["pids"][0] type_strings = file_info["type"].split() if len(type_strings) < 3: continue if type_strings[0] == "MS-DOS": file_info["cape_type"] = "DOS MZ image: executable" else: file_info["cape_type"] = "PE image" if type_strings[0] == ("PE32+"): file_info["cape_type"] += ": 64-bit " elif type_strings[0] == ("PE32"): file_info["cape_type"] += ": 32-bit " file_info["cape_type"] += "DLL" if type_strings[2] == ( "(DLL)") else "executable" texttypes = [ "ASCII", "Windows Registry text", "XML document text", "Unicode text", ] if any(texttype in file_info["type"] for texttype in texttypes): with open(file_info["path"], "r") as drop_open: filedata = drop_open.read(buf + 1) file_info["data"] = convert_to_printable_and_truncate( filedata, buf) if file_info["pid"]: _ = cape_name_from_yara(file_info, file_info["pid"], self.results) if HAVE_FLARE_CAPA: pretime = timeit.default_timer() capa_details = flare_capa_details(file_path, "procdump") if capa_details: file_info["flare_capa"] = capa_details self.add_statistic_tmp("flare_capa", "time", pretime) # should we use dropped path here? static_file_info( file_info, file_path, str(self.task["id"]), self.task.get("package", ""), self.task.get("options", ""), self.self_extracted, self.results, ) procdump_files.append(file_info) return procdump_files