class VirusTotal(Processor): name = "virustotal" category = "sandbox" default_options = { "report_sleep": 60, "retry_count": 10, "send_files": True, "enabled": False, } required_options = ["api_key"] filetypes_exclude = FILETYPES_ARCHIVE + ["text/url"] def setup(self): self.vt_key = self.options.get("api_key") self.vt_type = self.options.get("key_type", "") if self.vt_type == "public": self.vt = PublicApi(key=self.vt_key) elif self.vt_type == "": self.vt = PublicApi(key=self.vt_key) elif self.vt_type == "private": self.vt = PrivateApi(key=self.vt_key) def get(self, file_hash): result = self.vt.get_file_report(file_hash) if result["response_code"] is not VT_RESPONSE_OK: return None report = result["results"] if report["response_code"] is not VT_SCAN_OK: return None return report def scan(self, sample_data): retry_count = 0 scan_request = self.vt.scan_file(sample_data, from_disk=False) file_hash = scan_request["results"]["sha256"] while retry_count <= self.options.get("retry_count"): sleep(self.options.get("report_sleep")) report = self.get(file_hash) if report: return report retry_count += 1 raise RuntimeError("Maximum retries waiting for scan result for %s" % file_hash) def process(self, sample): file_hash = hash_data(sample["data"]) report = self.get(file_hash) if not report: self.logger.info("Sample %s not found on VirusTotal" % file_hash) if not self.options.get("send_files"): return {"scan_id": "not found"} self.logger.info("Sending %s to VirusTotal" % file_hash) report = self.scan(sample["data"]) detections = [] for av, res in report["scans"].items(): if res["detected"]: self.parse_av_tags(res["result"]) detections.append({ "av": av, "version": res["version"], "result": res["result"] }) if report["positives"] > 0: self.add_tag("malware") if self.key_type == "private": if len(report["tags"]) > 1: self.parse_tags(report["tags"]) if len(report["ITW_urls"]): # add ITW urls as URL indicator for url in report["ITW_urls"]: self.add_ioc("urls", url) return { "scan_id": report["scan_id"], "positives": report["positives"], "scan_date": report["scan_date"], "detections": sorted(detections, key=itemgetter("av")), } def parse_av_tags(self, malware_name): if in_string(["banker", "banload"], malware_name): self.add_tag("malware-banker") if in_string(["trojan"], malware_name): self.add_tag("malware-trojan") if in_string(["bot"], malware_name): self.add_tag("malware-botnet") if in_string(["rat"], malware_name): self.add_tag("malware-rat") def parse_tags_malware(self, tag): if tag in ["upx", "asprox", "themida"]: self.add_tag("malware-packed") def parse_tags_documents(self, tag): if tag == "macros": self.add_tag("document-contains-macros") if tag.startswith("auto-"): self.add_tag("document-contains-{0}".format(tag)) if tag.endswith("-file"): self.add_tag("document-contains-{0}".format(tag)) if tag == "powershell": self.add_tag("document-contains-powershell") def parse_tags_pdf(self, tag): if tag == "js-embedded": self.add_tag("pdf-contains-javascript") if tag == "flash-embedded": self.add_tag("pdf-contains-flash") if tag == "autoaction": self.add_tag("pdf-contains-autoaction") if tag == "acroform": self.add_tag("pdf-contains-acroform") if tag == "launch-action": self.add_tag("pdf-contains-launchaction") if tag == "file-embedded": self.add_tag("pdf-contains-embeddedfiles") def parse_tags_flash(self, tag): if tag == "obfuscated": self.add_tag("flash-obfuscated") if tag == "javascript": self.add_tag("flash-contains-javascript") ignore_tags = ["flash-embedded", "js-embedded", "file-embedded"] if tag.endswith("-embedded") and tag not in ignore_tags: # swap $type-embedded. i.e., converts to 'flash-contains-embedded-exe', etc. tag = tag.split("-") self.add_tag("flash-contains-{0}-".format(tag[1], tag[0])) def parse_tags(self, sample_tags): for tag in sample_tags: # malware packer specific self.parse_tags_malware(tag) # osx specific if tag == "dropper": self.add_tag("malware-dropper") # Tags to be captured as-is as_is_tags = ["encrypted", "exploit"] if tag in as_is_tags: self.add_tag(tag) # cves if "cve" in tag: self.add_tag(tag.lower()) # document specific tags self.parse_tags_documents(tag) # pdf specific tags self.parse_tags_pdf(tag) # flash specific tags self.parse_tags_flash(tag)