def build_options(self): """Generate analysis options. @return: options dict. """ options = {} if self.task.category == "file": options["file_name"] = File(self.task.target).get_name() options["file_type"] = File(self.task.target).get_type() options["pe_exports"] = \ ",".join(File(self.task.target).get_exported_functions()) package, activity = File(self.task.target).get_apk_entry() self.task.options["apk_entry"] = "%s:%s" % (package, activity) options["id"] = self.task.id options["ip"] = self.machine.resultserver_ip options["port"] = self.machine.resultserver_port options["category"] = self.task.category options["target"] = self.task.target options["package"] = self.task.package options["options"] = emit_options(self.task.options) options["enforce_timeout"] = self.task.enforce_timeout options["clock"] = self.task.clock options["terminate_processes"] = self.cfg.cuckoo.terminate_processes if not self.task.timeout: options["timeout"] = self.cfg.timeouts.default else: options["timeout"] = self.task.timeout # copy in other analyzer specific options, TEMPORARY (most likely) vm_options = getattr(machinery.options, self.machine.name) for k in vm_options: if k.startswith("analyzer_"): options[k] = vm_options[k] return options
def run(self): self.key = "network" self.ja3_file = self.options.get( "ja3_file", os.path.join(CUCKOO_ROOT, "data", "ja3", "ja3fingerprint.json")) if not IS_DPKT: log.error("Python DPKT is not installed, aborting PCAP analysis.") return {} if not os.path.exists(self.pcap_path): log.warning("The PCAP file does not exist at path \"%s\".", self.pcap_path) return {} if os.path.getsize(self.pcap_path) == 0: log.error("The PCAP file at path \"%s\" is empty." % self.pcap_path) return {} ja3_fprints = self._import_ja3_fprints() sorted_path = self.pcap_path.replace("dump.", "dump_sorted.") if cfg.processing.sort_pcap: sort_pcap(self.pcap_path, sorted_path) buf = Pcap(self.pcap_path, ja3_fprints).run() results = Pcap(sorted_path, ja3_fprints).run() results["http"] = buf["http"] results["dns"] = buf["dns"] else: results = Pcap(self.pcap_path, ja3_fprints).run() # Save PCAP file hash. if os.path.exists(self.pcap_path): results["pcap_sha256"] = File(self.pcap_path).get_sha256() if os.path.exists(sorted_path): results["sorted_pcap_sha256"] = File(sorted_path).get_sha256() return results
def run(self): self.key = "network" self.ja3_file = self.options.get("ja3_file", os.path.join(CUCKOO_ROOT, "data", "ja3", "ja3fingerprint.json")) if not IS_DPKT: log.error("Python DPKT is not installed, aborting PCAP analysis") return {} if not os.path.exists(self.pcap_path): log.warning('The PCAP file does not exist at path "%s"', self.pcap_path) return {} if os.path.getsize(self.pcap_path) == 0: log.error('The PCAP file at path "%s" is empty', self.pcap_path) return {} ja3_fprints = self._import_ja3_fprints() results = {"pcap_sha256": File(self.pcap_path).get_sha256()} self.options["sorted"] = False results.update(Pcap(self.pcap_path, ja3_fprints, self.options).run()) if proc_cfg.network.sort_pcap: sorted_path = self.pcap_path.replace("dump.", "dump_sorted.") sort_pcap(self.pcap_path, sorted_path) if os.path.exists(sorted_path): results["sorted_pcap_sha256"] = File(sorted_path).get_sha256() self.options["sorted"] = True results.update(Pcap(sorted_path, ja3_fprints, self.options).run()) if HAVE_HTTPREPLAY: try: p2 = Pcap2(self.pcap_path, self.get_tlsmaster(), self.network_path).run() if p2: results.update(p2) except Exception: log.exception("Error running httpreplay-based PCAP analysis") return results
def demux_sample(filename, package, options): """ If file is a ZIP, extract its included files and return their file paths If file is an email, extracts its attachments and return their file paths (later we'll also extract URLs) """ # if a package was specified, then don't do anything special if package: return [filename] # don't try to extract from office docs magic = File(filename).get_type() # if file is an Office doc and password is supplied, try to decrypt the doc if "Microsoft" in magic: ignore = ["Outlook", "Message", "Disk Image"] if any(x in magic for x in ignore): pass elif "Composite Document File" in magic or "CDFV2 Encrypted" in magic: password = False tmp_pass = options2passwd(options) if tmp_pass: password = tmp_pass if password: return demux_office(filename, password) else: return [filename] # don't try to extract from Java archives or executables if "Java Jar" in magic: return [filename] if "PE32" in magic or "MS-DOS executable" in magic: return [filename] if any(x in magic for x in VALID_LINUX_TYPES): return [filename] retlist = list() if HAS_SFLOCK: # all in one unarchiver retlist = demux_sflock(filename, options) # if it wasn't a ZIP or an email or we weren't able to obtain anything interesting from either, then just submit the # original file if not retlist: retlist.append(filename) else: if len(retlist) > 10: retlist = retlist[:10] return retlist
def run(self, results): """Writes report. @param results: Cuckoo results dict. @raise CuckooReportError: if fails to write report. """ if not HAVE_JINJA2: raise CuckooReportError("Failed to generate HTML report: Jinja2 Python library is not installed") shots_path = os.path.join(self.analysis_path, "shots") if os.path.exists(shots_path): shots = [] counter = 1 for shot_name in os.listdir(shots_path): if not shot_name.endswith(".jpg"): continue shot_path = os.path.join(shots_path, shot_name) if os.path.getsize(shot_path) == 0: continue shot = {} shot["id"] = os.path.splitext(File(shot_path).get_name())[0] shot["data"] = base64.b64encode(open(shot_path, "rb").read()) shots.append(shot) counter += 1 shots.sort(key=lambda shot: shot["id"]) results["screenshots"] = shots else: results["screenshots"] = [] env = Environment(autoescape=True) env.loader = FileSystemLoader(os.path.join(CUCKOO_ROOT, "data", "html")) try: tpl = env.get_template("report.html") html = tpl.render({"results" : results}) except Exception as e: raise CuckooReportError("Failed to generate HTML report: %s" % e) try: report = open(os.path.join(self.reports_path, "report.html"), "w") report.write(html) report.close() except (TypeError, IOError) as e: raise CuckooReportError("Failed to write HTML report: %s" % e) return True
def run(self): self.key = "network" self.ja3_file = self.options.get("ja3_file", os.path.join(CUCKOO_ROOT, "data", "ja3", "ja3fingerprint.json")) if not IS_DPKT: log.error("Python DPKT is not installed, aborting PCAP analysis.") return {} if not os.path.exists(self.pcap_path): log.warning('The PCAP file does not exist at path "%s".', self.pcap_path) return {} if os.path.getsize(self.pcap_path) == 0: log.error('The PCAP file at path "%s" is empty.' % self.pcap_path) return {} ja3_fprints = self._import_ja3_fprints() results = {} # Save PCAP file hash. if os.path.exists(self.pcap_path): results["pcap_sha256"] = File(self.pcap_path).get_sha256() """ if proc_cfg.network.sort_pcap: sorted_path = self.pcap_path.replace("dump.", "dump_sorted.") sort_pcap(self.pcap_path, sorted_path) # Sorted PCAP file hash. if os.path.exists(sorted_path): results["sorted_pcap_sha256"] = File(sorted_path).get_sha256() pcap_path = sorted_path else: pcap_path = self.pcap_path else: pcap_path = self.pcap_path """ pcap_path = self.pcap_path results.update(Pcap(pcap_path, ja3_fprints, self.options).run()) # buf = Pcap(self.pcap_path, ja3_fprints).run() # results = Pcap(sorted_path, ja3_fprints).run() # results["http"] = buf["http"] # results["dns"] = buf["dns"] if os.path.exists(pcap_path) and HAVE_HTTPREPLAY: try: p2 = Pcap2(pcap_path, self.get_tlsmaster(), self.network_path) results.update(p2.run()) except: log.exception("Error running httpreplay-based PCAP analysis") return results
def run(self): """Run analysis. @return: list of dropped files with related information. """ self.key = "dropped" dropped_files = [] for dir_name, dir_names, file_names in os.walk(self.dropped_path): for file_name in file_names: file_path = os.path.join(dir_name, file_name) file_info = File(file_path=file_path).get_all() dropped_files.append(file_info) return dropped_files
def run(self): """Runs VirusTotal processing @return: full VirusTotal report. """ self.key = "virustotal" virustotal = [] key = self.options.get("key", None) if not key: raise CuckooProcessingError( "VirusTotal API key not configured, skip") if self.task["category"] == "file": if not os.path.exists(self.file_path): raise CuckooProcessingError("File {0} not found, skip".format( self.file_path)) resource = File(self.file_path).get_md5() url = VIRUSTOTAL_FILE_URL elif self.task["category"] == "url": resource = self.task["target"] url = VIRUSTOTAL_URL_URL data = urllib.urlencode({"resource": resource, "apikey": key}) try: request = urllib2.Request(url, data) response = urllib2.urlopen(request) response_data = response.read() except urllib2.URLError as e: raise CuckooProcessingError( "Unable to establish connection to VirusTotal: {0}".format(e)) except urllib2.HTTPError as e: raise CuckooProcessingError( "Unable to perform HTTP request to VirusTotal (http code={0})". format(e.code)) try: virustotal = json.loads(response_data) except ValueError as e: raise CuckooProcessingError( "Unable to convert response to JSON: {0}".format(e)) if "scans" in virustotal: virustotal["scans"] = dict([ (engine.replace(".", "_"), signature) for engine, signature in virustotal["scans"].items() ]) return virustotal
def run(self): """Run analysis. @return: structured results. """ self.key = "procmemory" results = [] if self.options.get("extract_img") and not HAVE_PEFILE: log.warning( "In order to extract PE files from memory dumps it is " "required to have pefile installed (`pip install pefile`).") if os.path.exists(self.pmemory_path): for dmp in os.listdir(self.pmemory_path): if not dmp.endswith(".dmp"): continue dump_path = os.path.join(self.pmemory_path, dmp) dump_file = File(dump_path) pid, num = map(int, re.findall("(\\d+)", dmp)) proc = dict( file=dump_path, pid=pid, num=num, yara=dump_file.get_yara("memory"), urls=list(dump_file.get_urls()), regions=list(self.read_dump(dump_path)), ) if self.options.get("idapro"): self.create_idapy(proc) if self.options.get("extract_img") and HAVE_PEFILE: proc["extracted"] = list(self.dump_images(proc)) if self.options.get("dump_delete"): try: os.remove(dump_path) except OSError: log.error( "Unable to delete memory dump file at path \"%s\"", dump_path) results.append(proc) results.sort(key=lambda x: (x["pid"], x["num"])) return results
def run(self): """Run analysis. @return: results dict. """ self.key = "static" static = {} if self.task["category"] == "file" and os.path.exists(self.file_path): if HAVE_PEFILE: if "PE32" in File(self.file_path).get_type(): static.update(PortableExecutable(self.file_path).run()) static["keys"] = self._get_keys() return static
def run(self): """Run file information gathering. @return: information dict. """ self.key = "target" if not self.task: return {"category": "unknown", "file": {"name": "unknown"}} target_info = {"category": self.task["category"]} # We have to deal with file or URL targets. if self.task["category"] == "file": target_info["file"] = {} # et's try to get as much information as possible, i.e., the # filename if the file is not available anymore. if os.path.exists(self.file_path): target_info["file"] = File(self.file_path).get_all() target_info["file"]["name"] = File(self.task["target"]).get_name() elif self.task["category"] == "url": target_info["url"] = self.task["target"] return target_info
def demux_sample(filename, package, options): """ If file is a ZIP, extract its included files and return their file paths If file is an email, extracts its attachments and return their file paths (later we'll also extract URLs) """ # if a package was specified, then don't do anything special # this will allow for the ZIP package to be used to analyze binaries with included DLL dependencies # do the same if file= is specified in the options if package or "file=" in options: return [filename] # don't try to extract from office docs magic = File(filename).get_type() if "Microsoft" in magic or "Java Jar" in magic or "Composite Document File" in magic: return [filename] if "PE32" in magic or "MS-DOS executable" in magic: return [filename] retlist = demux_zip(filename, options) if not retlist: retlist = demux_rar(filename, options) if not retlist: retlist = demux_email(filename, options) if not retlist: retlist = demux_msg(filename, options) # handle ZIPs/RARs inside extracted files if retlist: newretlist = [] for item in retlist: zipext = demux_zip(item, options) if zipext: newretlist.extend(zipext) else: rarext = demux_rar(item, options) if rarext: newretlist.extend(rarext) else: newretlist.append(item) retlist = newretlist # if it wasn't a ZIP or an email or we weren't able to obtain anything interesting from either, then just submit the # original file if not retlist: retlist.append(filename) return retlist
def add_path(self, file_path, timeout=0, package="", options="", priority=1, custom="", machine="", platform="", tags=None, memory=False, enforce_timeout=False, clock=None): """Add a task to database from file path. @param file_path: sample path. @param timeout: selected timeout. @param options: analysis options. @param priority: analysis priority. @param custom: custom options. @param machine: selected machine. @param platform: platform. @param tags: Tags required in machine selection @param memory: toggle full memory dump. @param enforce_timeout: toggle full timeout execution. @param clock: virtual machine clock time @return: cursor or None. """ if not file_path or not os.path.exists(file_path): return None # Convert empty strings and None values to a valid int if not timeout: timeout = 0 if not priority: priority = 1 return self.add(File(file_path), timeout, package, options, priority, custom, machine, platform, tags, memory, enforce_timeout, clock)
def run(self): """Run analysis. @return: list of dropped files with related information. """ self.key = "dropped" dropped_files = [] buf = self.options.get("buffer", 8192) if self.task["category"] == "pcap": return dropped_files file_names = os.listdir(self.dropped_path) for file_name in file_names: file_path = os.path.join(self.dropped_path, file_name) if not os.path.isfile(file_path): continue if file_name.endswith("_info.txt"): continue guest_paths = [ line.strip() for line in open(file_path + "_info.txt") ] guest_name = guest_paths[0].split("\\")[-1] file_info = File(file_path=file_path, guest_paths=guest_paths, file_name=guest_name).get_all() texttypes = [ "ASCII", "Windows Registry text", "XML document text", "Unicode text", ] readit = False for texttype in texttypes: if texttype in file_info["type"]: readit = True break if readit: with open(file_info["path"], "r") as drop_open: filedata = drop_open.read(buf + 1) if len(filedata) > buf: file_info["data"] = convert_to_printable(filedata[:buf] + " <truncated>") else: file_info["data"] = convert_to_printable(filedata) dropped_files.append(file_info) return dropped_files
def get_json_document(results, analysis_path): # Create a copy of the dictionary. This is done in order to not modify # the original dictionary and possibly # compromise the following reporting modules. report = dict(results) if "network" not in report: report["network"] = {} # Add screenshot paths report["shots"] = [] shots_path = os.path.join(analysis_path, "shots") if os.path.exists(shots_path): shots = [ shot for shot in os.listdir(shots_path) if shot.endswith(".jpg") ] for shot_file in sorted(shots): shot_path = os.path.join(analysis_path, "shots", shot_file) screenshot = File(shot_path) if screenshot.valid(): # Strip the extension as it's added later # in the Django view report["shots"].append(shot_file.replace(".jpg", "")) # Calculate the mlist_cnt for display if present to reduce db load if "signatures" in results: for entry in results["signatures"]: if entry["name"] == "ie_martian_children": report["mlist_cnt"] = len(entry["data"]) if entry["name"] == "office_martian_children": report["f_mlist_cnt"] = len(entry["data"]) # Other info we want quick access to from the web UI if results.get("virustotal", {}).get("positive") and results.get( "virustotal", {}).get("total"): report["virustotal_summary"] = "%s/%s" % ( results["virustotal"]["positive"], results["virustotal"]["total"]) if results.get("suricata", False): keywords = ("tls", "alerts", "files", "http", "ssh", "dns") keywords_dict = ("suri_tls_cnt", "suri_alert_cnt", "suri_file_cnt", "suri_http_cnt", "suri_ssh_cnt", "suri_dns_cnt") for keyword, keyword_value in zip(keywords, keywords_dict): if results["suricata"].get(keyword, 0): report[keyword_value] = len(results["suricata"][keyword]) return report
def process_new_task_files(request, samples, details, opt_filename, unique): list_of_files = [] for sample in samples: # Error if there was only one submitted sample and it's empty. # But if there are multiple and one was empty, just ignore it. if not sample.size: details["errors"].append( {sample.name: "You uploaded an empty file."}) continue elif sample.size > web_cfg.general.max_sample_size: details["errors"].append({ sample.name: "You uploaded a file that exceeds the maximum allowed upload size specified in conf/web.conf." }) continue if opt_filename: filename = opt_filename else: filename = sanitize_filename(sample.name) # Moving sample from django temporary file to CAPE temporary storage to let it persist between reboot (if user like to configure it in that way). try: path = store_temp_file(sample.read(), filename) except OSError: details["errors"].append({ filename: "Your specified temp folder, disk is out of space. Clean some space before continue." }) continue sha256 = File(path).get_sha256() if (not request.user.is_staff and (web_cfg.uniq_submission.enabled or unique) and db.check_file_uniq(sha256, hours=web_cfg.uniq_submission.hours)): details["errors"].append({ filename: "Duplicated file, disable unique option on submit or in conf/web.conf to force submission" }) continue content = get_file_content(path) list_of_files.append((content, path, sha256)) return list_of_files, details
def demux_sample(filename: bytes, package: str, options: str, use_sflock: bool = True) -> List[bytes]: """ If file is a ZIP, extract its included files and return their file paths If file is an email, extracts its attachments and return their file paths (later we'll also extract URLs) """ # sflock requires filename to be bytes object for Py3 # TODO: Remove after checking all uses of demux_sample use bytes ~TheMythologist if isinstance(filename, str) and use_sflock: filename = filename.encode() # if a package was specified, then don't do anything special if package: return [filename] # don't try to extract from office docs magic = File(filename).get_type() # if file is an Office doc and password is supplied, try to decrypt the doc if "Microsoft" in magic: pass # ignore = {"Outlook", "Message", "Disk Image"} elif "Composite Document File" in magic or "CDFV2 Encrypted" in magic: password = options2passwd(options) or None if use_sflock: if HAS_SFLOCK: return demux_office(filename, password) else: log.error( "Detected password protected office file, but no sflock is installed: pip3 install -U sflock2" ) # don't try to extract from Java archives or executables if "Java Jar" in magic or "PE32" in magic or "MS-DOS executable" in magic or any( x in magic for x in VALID_LINUX_TYPES): return [filename] # all in one unarchiver retlist = demux_sflock(filename, options) if HAS_SFLOCK and use_sflock else [] # if it wasn't a ZIP or an email or we weren't able to obtain anything interesting from either, then just submit the # original file if not retlist: retlist.append(filename) return retlist[:10]
def run(self): """Run analysis. @return: list of dropped files with related information. """ self.key = "dropped" dropped_files = [] buf = self.options.get("buffer", 8192) for dir_name, dir_names, file_names in os.walk(self.dropped_path): for file_name in file_names: file_path = os.path.join(dir_name, file_name) if file_name.endswith("_info.txt") and not os.path.exists( file_path + "_info.txt"): continue guest_paths = [ line.strip() for line in open(file_path + "_info.txt") ] file_info = File(file_path=file_path, guest_paths=guest_paths).get_all() # Used by ElasticSearch to find the file on disk # since they are in random generated directories if Config("reporting").get("elasticsearchdb").get("enabled"): file_info["dropdir"] = file_path.split("/")[-2] texttypes = [ "ASCII", "Windows Registry text", "XML document text", "Unicode text", ] readit = False for texttype in texttypes: if texttype in file_info["type"]: readit = True break if readit: with open(file_info["path"], "r") as drop_open: filedata = drop_open.read(buf + 1) if len(filedata) > buf: file_info["data"] = convert_to_printable( filedata[:buf] + " <truncated>") else: file_info["data"] = convert_to_printable(filedata) dropped_files.append(file_info) return dropped_files
def run(self): """Run analysis. @return: list of dropped files with related information. """ self.key = "dropped" dropped_files = [] buf = self.options.get("buffer", 8192) if self.task["category"] == "pcap": return dropped_files if not os.path.exists(self.dropped_path): return dropped_files textchars = bytearray({7, 8, 9, 10, 12, 13, 27} | set(range(0x20, 0x100)) - {0x7f}) is_binary_file = lambda bytes: bool(bytes.translate(None, textchars)) file_names = os.listdir(self.dropped_path) for file_name in file_names: file_path = os.path.join(self.dropped_path, file_name) if not os.path.isfile(file_path): continue if file_name.endswith("_info.txt"): continue guest_paths = [ line.strip() for line in open(file_path + "_info.txt") ] guest_name = guest_paths[0].split("\\")[-1] file_info = File(file_path=file_path, guest_paths=guest_paths, file_name=guest_name).get_all() if is_binary_file(open(file_info["path"], 'rb').read(8192)): pass else: with open(file_info["path"], "r") as drop_open: filedata = drop_open.read(buf + 1) if len(filedata) > buf: file_info["data"] = convert_to_printable(filedata[:buf] + " <truncated>") else: file_info["data"] = convert_to_printable(filedata) dropped_files.append(file_info) return dropped_files
def static_extraction(path): try: hits = File(path).get_yara(category="CAPE") if not hits: return False # Get the file data with open(path, "rb") as file_open: file_data = file_open.read() for hit in hits: config = static_config_parsers(hit["name"], file_data) if config: return config return False except Exception as e: log.error(e) return False
def run(self): """Run analysis. @return: structured results. """ self.key = "procmemory" results = [] for dmp in os.listdir(self.pmemory_path): dmp_path = os.path.join(self.pmemory_path, dmp) dmp_file = File(dmp_path) proc = dict(yara=dmp_file.get_yara( os.path.join(CUCKOO_ROOT, "data", "yara", "index_memory.yar"))) results.append(proc) return results
def static_extraction(path): cape_config = dict() try: hits = File(path).get_yara(CAPE_YARA_RULEPATH) if not hits: return False # Get the file data with open(path, "r") as file_open: file_data = file_open.read() for hit in hits: config = static_config_parsers(hit["name"], file_data, cape_config) if config: return config return False except Exception as e: log.error(e) return False
def _extracted_files_metadata(folder: str, destination_folder: str, files: list = None) -> List[dict]: """ args: folder - where files extracted destination_folder - where to move extracted files files - file names """ metadata = [] filelog = os.path.join(os.path.dirname(destination_folder), "files.json") if not files: files = os.listdir(folder) with open(filelog, "a") as f: for file in files: full_path = os.path.join(folder, file) file_details, _pe = File(full_path).get_all() if processing_conf.trid.enabled: trid_info(full_path, file_details) if processing_conf.die.enabled: detect_it_easy_info(full_path, file_details) metadata.append(file_details) dest_path = os.path.join(destination_folder, file_details["sha256"]) file_details["path"] = dest_path file_details["name"] = os.path.basename(dest_path) if not os.path.exists(dest_path): shutil.move(full_path, dest_path) print( json.dumps( { "path": os.path.join("files", file_details["sha256"]), "filepath": file_details["name"], "pids": [], "ppids": [], "metadata": "", "category": "files", }, ensure_ascii=False, ), file=f, ) return metadata
def run(self): """Run analysis. @return: structured results. """ self.key = "procmemory" results = [] if os.path.exists(self.pmemory_path): for dmp in os.listdir(self.pmemory_path): if not dmp.endswith(".dmp"): continue dump_path = os.path.join(self.pmemory_path, dmp) dump_file = File(dump_path) if "-" in os.path.basename(dump_path): pid = int(os.path.basename(dump_path).split("-")[0]) else: pid = int(os.path.basename(dump_path).split(".")[0]) proc = dict( file=dump_path, pid=pid, yara=dump_file.get_yara("memory"), urls=list(dump_file.get_urls()), regions=list(self.read_dump(dump_path)), ) if self.options.get("idapro"): self.create_idapy(proc) if self.options.get("dump_delete"): try: os.remove(dump_path) except OSError: log.error( "Unable to delete memory dump file at path \"%s\" ", dump_path) results.append(proc) return results
def static_extraction(path): try: if not File.yara_initialized: init_yara() hits = File(path).get_yara(category="CAPE") if not hits: return False # Get the file data with open(path, "rb") as file_open: file_data = file_open.read() for hit in hits: cape_name = File.get_cape_name_from_yara_hit(hit) config = static_config_parsers(cape_name, path, file_data) if config: return config return False except Exception as e: log.error(e) return False
def get_procmemory_pe(self, mem_pe): res = list() file_item = open(mem_pe.get("file"), "rb") for memmap in mem_pe.get("address_space") or []: if not memmap.get("PE"): continue data = b"" for chunk in memmap["chunks"]: if int(chunk["start"], 16) >= int(memmap["start"], 16) and int(chunk["end"], 16) <= int(memmap["end"], 16): file_item.seek(chunk["offset"]) data += file_item.read(int(chunk["size"], 16)) # save pe to disk path = os.path.join(self.pmemory_path, "{}_{}".format(mem_pe["pid"], memmap["start"])) with open(path, "wb") as f: f.write(data) res.append(File(path).get_all()) return res
def store_file(self): """Store a copy of the file being analyzed.""" if not os.path.exists(self.task.target): log.error( "Task #{0}: The file to analyze does not exist at path '{1}', " "analysis aborted".format( self.task.id, convert_to_printable(self.task.target))) return False sha256 = File(self.task.target).get_sha256() self.binary = os.path.join(CUCKOO_ROOT, "storage", "binaries", sha256) if os.path.exists(self.binary): log.info("Task #{0}: File already exists at '{1}'".format( self.task.id, self.binary)) else: # TODO: do we really need to abort the analysis in case we are not # able to store a copy of the file? try: shutil.copy(self.task.target, self.binary) except (IOError, shutil.Error) as e: log.error( "Task #{0}: Unable to store file from '{1}' to '{2}', " "analysis aborted".format( self.task.id, convert_to_printable(self.task.target), self.binary)) return False try: new_binary_path = os.path.join(self.storage, "binary") if hasattr(os, "symlink"): os.symlink(self.binary, new_binary_path) else: shutil.copy(self.binary, new_binary_path) except (AttributeError, OSError) as e: log.error("Task #{0}: Unable to create symlink/copy from '{1}' to " "'{2}': {3}".format(self.task.id, self.binary, self.storage, e)) return True
def add_reboot(self, task_id, timeout=0, options="", priority=1, owner="", machine="", platform="", tags=None, memory=False, enforce_timeout=False, clock=None): """Add a reboot task to database from an existing analysis. @param task_id: task id of existing analysis. @param timeout: selected timeout. @param options: analysis options. @param priority: analysis priority. @param owner: task owner. @param machine: selected machine. @param platform: platform. @param tags: tags for machine selection @param memory: toggle full memory dump. @param enforce_timeout: toggle full timeout execution. @param clock: virtual machine clock time @return: cursor or None. """ # Convert empty strings and None values to a valid int if not timeout: timeout = 0 if not priority: priority = 1 task = self.view_task(task_id) if not task or not os.path.exists(task.target): log.error( "Unable to add reboot analysis as the original task or its " "sample has already been deleted." ) return # TODO Integrate the Reboot screen with the submission portal and # pass the parent task ID through as part of the "options". custom = "%s" % task_id return self.add(File(task.target), timeout, "reboot", options, priority, custom, owner, machine, platform, tags, memory, enforce_timeout, clock, "file")
def run(self): """Run analysis. @return: results dict. """ self.key = "static" static = {} # Does the target file still exist? if self.task["category"] != "file" or \ not os.path.exists(self.file_path): return package = self.task.get("package") if self.task["category"] == "file": ext = os.path.splitext(self.task["target"])[1].lstrip(".").lower() else: ext = None if ext == "exe" or "PE32" in File(self.file_path).get_type(): if HAVE_PEFILE: static.update(PortableExecutable(self.file_path).run()) static["keys"] = self._get_keys() if package == "wsf" or ext == "wsf": static["wsf"] = WindowsScriptFile(self.file_path).run() if package in ("doc", "ppt", "xls") or ext in self.office_ext: static["office"] = OfficeDocument(self.file_path).run() def pdf_worker(filepath): return PdfDocument(filepath).run() if package == "pdf" or ext == "pdf": timeout = int(self.options.get("pdf_timeout", 60)) static["pdf"] = dispatch(pdf_worker, (self.file_path, ), timeout=timeout) return static
def store_file(self): """Store a copy of the file being analyzed.""" if not os.path.exists(self.task.target): log.error( "The file to analyze does not exist at path \"%s\", " "analysis aborted", self.task.target) return False sha256 = File(self.task.target).get_sha256() self.binary = os.path.join(CUCKOO_ROOT, "storage", "binaries", sha256) if os.path.exists(self.binary): pass #log.info("File already exists at \"%s\"", self.binary) else: # TODO: do we really need to abort the analysis in case we are not # able to store a copy of the file? try: shutil.copy(self.task.target, self.binary) except (IOError, shutil.Error) as e: log.error( "Unable to store file from \"%s\" to \"%s\", " "analysis aborted", self.task.target, self.binary) return False try: self.storage_binary = os.path.join(self.storage, "binary") if hasattr(os, "symlink"): os.symlink(self.binary, self.storage_binary) else: shutil.copy(self.binary, self.storage_binary) except (AttributeError, OSError) as e: log.error( "Unable to create symlink/copy from \"%s\" to " "\"%s\": %s", self.binary, self.storage, e) return True