def test_search_all(self, proc_dump): data = ProcDump(dump_file=proc_dump[1]).search(regex=br"program", all=True) test_str = b"\xcd!This program cannot be run in DOS mode.\r\r\n$\x00\x00\x00\x00\x00\x00\x00d\x94$S \xf5J\x00 \xf5J\x00 \xf5J\x00)\x8d\xdf\x00!\xf5J\x00)\x8d\xd9\x00-\xf5J\x00 \xf5K\x00F\xf5J\x00)\x8d\xce\x00#\xf5J\x00)\x8d\xc9\x005\xf5J\x00)\x8d\xde\x00!\xf5J\x00)\x8d\xdb\x00!\xf5J\x00Rich \xf5J\x00\x00\x00\x00\x00\x00\x00\x00\x00PE\x00\x00L\x01\x04\x00\t\x1d\xddX\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x02\x01\x0b\x01\t\x00\x00<\x00\x00\x00p\x00\x00\x00\x00\x00\x00\x98\x17\x00\x00\x00\x10\x00\x00\x00P\x00\x00\x00\x00I\x00\x00\x10\x00\x00\x00\x02\x00\x00\x06\x00\x01\x00\x06\x00\x01\x00\x06\x00\x01\x00" assert data["detail"][-1]["match"][0].string == test_str
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) if "cape_yara" in proc: cape_name = "" for hit in proc["cape_yara"]: if "name" in hit: if not cape_name: cape_name = hit["name"] if cape_name: if "detections" not in self.results: self.results["detections"] = cape_name return results
def test_parse_dump(self, proc_dump): test_dict = [ { "end": 12894362193, "prot": 0, "start": 12894362189, "PE": False, "chunks": [{ "end": 12894362193, "prot": 0, "start": 12894362189, "state": 65535, "offset": 24, "type": 184, "PE": False, "size": 4, }], "size": 4, }, { "end": 216, "prot": None, "start": 0, "PE": False, "chunks": [ { "end": 0, "prot": 0, "start": 0, "state": 0, "offset": 52, "type": 0, "PE": False, "size": 0 }, { "end": 216, "prot": 1275181089, "start": 0, "state": 247078670, "offset": 76, "type": 3439965184, "PE": False, "size": 216, }, ], "size": 216, }, { "end": 231309758694400, "prot": 262144, "start": 231309758693376, "PE": False, "chunks": [{ "end": 231309758694400, "prot": 262144, "start": 231309758693376, "state": 0, "offset": 316, "type": 2151677954, "PE": False, "size": 1024, }], "size": 1024, }, ] assert ProcDump(dump_file=proc_dump[1]).parse_dump() == test_dict
def test_search(self, proc_dump): data = ProcDump(dump_file=proc_dump[1]).search(regex=br".*") test_str = b"@\x00\x00\x00" assert data["match"].string == test_str
def test_get_data(self, proc_dump): data = ProcDump(dump_file=proc_dump[1]).get_data(addr=0, size=26) assert data == b"\xcd!This program cannot be r"
def test_init(self, proc_dump): assert ProcDump(dump_file=proc_dump[1])
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 = self.options.get("minchars", 5) 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) dmp_file = File(dmp_path) process_name = "" process_path = "" process_id = int(os.path.splitext(os.path.basename(dmp_path))[0]) if "behavior" in self.results and "processes" in self.results["behavior"]: for process in self.results["behavior"]["processes"]: 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(os.path.join(CUCKOO_ROOT, "data", "yara", "index_memory.yar")), address_space=procdump.pretty_print(), ) endlimit = "" if not HAVE_RE2: endlimit = "8192" if do_strings: if nulltermonly: apat = "([\x20-\x7e]{" + str(minchars) + "," + endlimit + "})\x00" upat = "((?:[\x20-\x7e][\x00]){" + str(minchars) + "," + endlimit + "})\x00\x00" else: apat = "[\x20-\x7e]{" + str(minchars) + "," + endlimit + "}" upat = "(?:[\x20-\x7e][\x00]){" + str(minchars) + "," + endlimit + "}" matchdict = procdump.search(apat, all=True) strings = matchdict["matches"] matchdict = procdump.search(upat, all=True) ustrings = matchdict["matches"] for ws in ustrings: strings.append(str(ws.decode("utf-16le"))) proc["strings_path"] = dmp_path + ".strings" f=open(proc["strings_path"], "w") f.write("\n".join(strings)) f.close() procdump.close() results.append(proc) return results
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 = self.options.get("minchars", 5) 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) dmp_file = File(dmp_path) process_name = "" process_path = "" process_id = int( os.path.splitext(os.path.basename(dmp_path))[0]) if "behavior" in self.results and "processes" in self.results[ "behavior"]: for process in self.results["behavior"]["processes"]: 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( os.path.join(CUCKOO_ROOT, "data", "yara", "index_memory.yar")), address_space=procdump.pretty_print(), ) endlimit = "" if not HAVE_RE2: endlimit = "8192" if do_strings: if nulltermonly: apat = "([\x20-\x7e]{" + str( minchars) + "," + endlimit + "})\x00" upat = "((?:[\x20-\x7e][\x00]){" + str( minchars) + "," + endlimit + "})\x00\x00" else: apat = "[\x20-\x7e]{" + str( minchars) + "," + endlimit + "}" upat = "(?:[\x20-\x7e][\x00]){" + str( minchars) + "," + endlimit + "}" matchdict = procdump.search(apat, all=True) strings = matchdict["matches"] matchdict = procdump.search(upat, all=True) ustrings = matchdict["matches"] for ws in ustrings: strings.append(str(ws.decode("utf-16le"))) proc["strings_path"] = dmp_path + ".strings" f = open(proc["strings_path"], "w") f.write("\n".join(strings)) f.close() procdump.close() # Deduplicate configs if proc["yara"]: for match in proc["yara"]: # Dyre if match["name"] == "DyreCfgInjectsList": output = list() buf = "" recline = False for ystring in match["strings"]: for line in ystring.splitlines(): if line.startswith("<litem>"): buf = "" recline = True if recline: buf += line.strip() + "\n" if line.startswith("</litem>"): recline = False if buf not in output: output.append(buf) match["strings"] = ["".join(output)] match["meta"][ "description"] += " (Observed %d unique inject elements)" % len( output) elif match["name"] == "DyreCfgRedirectList": output = list() buf = "" recline = False for ystring in match["strings"]: for line in ystring.splitlines(): if line.startswith("<rpcgroup>"): buf = "" recline = True if recline: buf += line.strip() + "\n" if line.startswith("</rpcgroup>"): recline = False if buf not in output: output.append(buf) match["strings"] = ["".join(output)] match["meta"][ "description"] += " (Observed %d unique redirect elements)" % len( output) # DarkComet elif match["name"] == "DarkCometConfig": output = list() recline = False for ystring in match["strings"]: for line in ystring.splitlines(): if line.startswith("#BEGIN DARKCOMET"): buf = "" recline = True if recline: buf += line.strip() + "\n" if line.startswith("#EOF DARKCOMET"): recline = False if buf not in output: output.append(buf) match["strings"] = ["".join(output)] results.append(proc) return results
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 = self.options.get("minchars", 5) 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) dmp_file = File(dmp_path) process_name = "" process_path = "" process_id = int(os.path.splitext(os.path.basename(dmp_path))[0]) if "behavior" in self.results and "processes" in self.results["behavior"]: for process in self.results["behavior"]["processes"]: 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(os.path.join(CUCKOO_ROOT, "data", "yara", "index_memory.yar")), address_space=procdump.pretty_print(), ) endlimit = "" if not HAVE_RE2: endlimit = "8192" if do_strings: if nulltermonly: apat = "([\x20-\x7e]{" + str(minchars) + "," + endlimit + "})\x00" upat = "((?:[\x20-\x7e][\x00]){" + str(minchars) + "," + endlimit + "})\x00\x00" else: apat = "[\x20-\x7e]{" + str(minchars) + "," + endlimit + "}" upat = "(?:[\x20-\x7e][\x00]){" + str(minchars) + "," + endlimit + "}" matchdict = procdump.search(apat, all=True) strings = matchdict["matches"] matchdict = procdump.search(upat, all=True) ustrings = matchdict["matches"] for ws in ustrings: strings.append(str(ws.decode("utf-16le"))) proc["strings_path"] = dmp_path + ".strings" f=open(proc["strings_path"], "w") f.write("\n".join(strings)) f.close() procdump.close() # Deduplicate configs if proc["yara"]: for match in proc["yara"]: # Dyre if match["name"] == "DyreCfgInjectsList": output = list() buf = "" recline = False for ystring in match["strings"]: for line in ystring.splitlines(): if line.startswith("<litem>"): buf = "" recline = True if recline: buf += line.strip() + "\n" if line.startswith("</litem>"): recline = False if buf not in output: output.append(buf) match["strings"] = ["".join(output)] match["meta"]["description"] += " (Observed %d unique inject elements)" % len(output) elif match["name"] == "DyreCfgRedirectList": output = list() buf = "" recline = False for ystring in match["strings"]: for line in ystring.splitlines(): if line.startswith("<rpcgroup>"): buf = "" recline = True if recline: buf += line.strip() + "\n" if line.startswith("</rpcgroup>"): recline = False if buf not in output: output.append(buf) match["strings"] = ["".join(output)] match["meta"]["description"] += " (Observed %d unique redirect elements)" % len(output) # DarkComet elif match["name"] == "DarkCometConfig": output = list() recline = False for ystring in match["strings"]: for line in ystring.splitlines(): if line.startswith("#BEGIN DARKCOMET"): buf = "" recline = True if recline: buf += line.strip() + "\n" if line.startswith("#EOF DARKCOMET"): recline = False if buf not in output: output.append(buf) match["strings"] = ["".join(output)] results.append(proc) return results