def __init__(self): Analyzer.__init__(self) self.url = self.getParam('config.url', None, 'No VMRay url given.').rstrip('/ ') disable_reanalyze = self.getParam('config.disablereanalyze', False) if disable_reanalyze == 'true' or disable_reanalyze: reanalyze = False else: reanalyze = True self.vmrc = VMRayClient(url=self.url, key=self.getParam('config.key', None, 'No VMRay API key given.'), cert=self.getParam('config.certpath', True), reanalyze=reanalyze)
def __init__(self): Analyzer.__init__(self) self.url = self.get_param('config.url', None, 'No VMRay url given.').rstrip('/ ') self.disable_reanalyze = self.get_param('config.disablereanalyze', False) # Check for string and boolean True if self.disable_reanalyze == 'true' or self.disable_reanalyze: reanalyze = False else: reanalyze = True verify = self.get_param('config.certverify', None, 'Certificate verification parameter is missing.') certpath = self.get_param('config.certpath', None) if verify and certpath: verify = certpath self.vmrc = VMRayClient(url=self.url, key=self.get_param('config.key', None, 'No VMRay API key given.'), cert=verify, reanalyze=reanalyze)
def __init__(self): Analyzer.__init__(self) self.reanalyze = self.get_param("config.reanalyze", True) self.verdict_only = self.get_param("config.verdict_only", False) self.shareable = self.get_param("config.shareable", False) self.tags = self.get_param("config.tags", ["TheHive"]) self.user_config = { "timeout": self.get_param("config.timeout", None), "net_scheme_name": self.get_param("config.net_scheme_name", None), } self.query_retry_wait = self.get_param("config.query_retry_wait", 10) self.recursive_sample_limit = self.get_param( "config.recursive_sample_limit", 10) verify = self.get_param("config.certverify", True) certpath = self.get_param("config.certpath", None) if verify and certpath: verify = certpath archive_compound_sample = self.get_param( "config.archive_compound_sample", False) if archive_compound_sample: archive_action = "compound_sample" else: archive_action = "separate_samples" self.vmrc = VMRayClient( url=self.get_param("config.url", None, "No VMRay URL given.").rstrip("/ "), key=self.get_param("config.key", None, "No VMRay API key given."), reanalyze=self.reanalyze, verify=verify, archive_password=self.get_param("config.archive_password", "malware"), archive_action=archive_action, max_jobs=self.get_param("config.max_jobs", None), enable_reputation=self.get_param("config.enable_reputation", None), enable_whois=self.get_param("config.enable_whois", None), analyzer_mode=self.get_param("config.analyzer_mode", None), known_malicious=self.get_param("config.known_malicious", None), known_benign=self.get_param("config.known_benign", None), )
class VMRayAnalyzer(Analyzer): """ VMRay analyzer that uses VMRayClient to connect to an VMRay instance. Allows uploading a sample and getting information via hash. More info regarding configuration in the complete documentation. """ def __init__(self): Analyzer.__init__(self) self.url = self.getParam('config.url', None, 'No VMRay url given.').rstrip('/ ') disable_reanalyze = self.getParam('config.disablereanalyze', False) if disable_reanalyze == 'true' or disable_reanalyze: reanalyze = False else: reanalyze = True self.vmrc = VMRayClient(url=self.url, key=self.getParam('config.key', None, 'No VMRay API key given.'), cert=self.getParam('config.certpath', True), reanalyze=reanalyze) def run(self): if self.data_type == 'hash': self.report({'scanreport': self.vmrc.get_sample(self.getData())}) elif self.data_type == 'file': filepath = self.getParam('file') filename = self.getParam('filename') submit_report = self.vmrc.submit_sample(filepath=filepath, filename=filename) # Check for completion while not self.vmrc.query_job_status( submissionid=submit_report['data']['submissions'][0] ['submission_id']): sleep(10) # Return the results self.report({ 'scanreport': self.vmrc.get_sample( samplehash=submit_report['data']['submissions'][0] ['submission_sample_sha256']) }) else: self.error('Data type currently not supported') def summary(self, raw): taxonomies = [] level = "info" namespace = "VMRay" predicate = "Scan" value = "\"0\"" r = {'reports': []} if raw.get('scanreport', None) and len(raw.get('scanreport').get('data')) > 0: for scan in raw.get('scanreport').get('data'): r['reports'].append({ 'score': scan.get('sample_score'), 'sample_severity': scan.get('sample_severity'), 'sample_last_reputation_severity': scan.get('sample_last_reputation_severity'), 'url': scan.get('sample_webif_url') }) if len(r["reports"]) == 0: value = "\"No Scan\"" level = "info" taxonomies.append( self.build_taxonomy(level, namespace, predicate, value)) else: for s in r["reports"]: i = 1 if s["sample_severity"] == "not_suspicious": level = "safe" elif s["sample_severity"] == "malicious": level = "malicious" else: level = "info" if r["reports"] > 1: value = "\"{}( from scan {})\"".format(s["score"], i) else: value = "{}".format(s["score"]) taxonomies.append( self.build_taxonomy(level, namespace, predicate, value)) i += 1 return {"taxonomies": taxonomies}
class VMRayAnalyzer(Analyzer): """ VMRay analyzer that uses VMRayClient to connect to an VMRay instance. Allows uploading a sample and getting information via hash. More info regarding configuration in the complete documentation. """ def __init__(self): Analyzer.__init__(self) self.url = self.get_param('config.url', None, 'No VMRay url given.').rstrip('/ ') self.disable_reanalyze = self.get_param('config.disablereanalyze', False) # Check for string and boolean True if self.disable_reanalyze == 'true' or self.disable_reanalyze: reanalyze = False else: reanalyze = True verify = self.get_param('config.certverify', None, 'Certificate verification parameter is missing.') certpath = self.get_param('config.certpath', None) if verify and certpath: verify = certpath self.vmrc = VMRayClient(url=self.url, key=self.get_param('config.key', None, 'No VMRay API key given.'), cert=verify, reanalyze=reanalyze) def run(self): if self.data_type == 'hash': self.report({'scanreport': self.vmrc.get_sample(self.get_data())}) elif self.data_type == 'file': filepath = self.get_param('file') filename = self.get_param('filename') submit_report = self.vmrc.submit_sample(filepath=filepath, filename=filename) # Ref: #332: check if job was submitted if self.disable_reanalyze: if len(submit_report['data']['errors']) > 0: if submit_report['result'] == 'ok': # Sample is already there, get the report self.report({'scanreport': self.vmrc.get_sample(samplehash=submit_report['data']['samples'][0]['sample_sha256hash'])}) else: self.error('Error while submitting sample to VMRay: {}.' .format([error_msg for error_msg in submit_report['data']['errors']])) # Check for completion while not self.vmrc.query_job_status(submissionid=submit_report['data']['submissions'][0]['submission_id']): sleep(10) # Return the results self.report({'scanreport': self.vmrc.get_sample( samplehash=submit_report['data']['submissions'][0]['submission_sample_sha256']) }) else: self.error('Data type currently not supported') def summary(self, raw): taxonomies = [] namespace = "VMRay" predicate = "Scan" r = { 'reports': [] } if raw.get('scanreport', None) and len(raw.get('scanreport').get('data')) > 0: for scan in raw.get('scanreport').get('data'): r['reports'].append({ 'score': scan.get('sample_score'), 'sample_severity': scan.get('sample_severity'), 'sample_last_reputation_severity': scan.get('sample_last_reputation_severity'), 'url': scan.get('sample_webif_url') }) if len(r["reports"]) == 0: value = "No Scan" level = "info" taxonomies.append(self.build_taxonomy(level, namespace, predicate, value)) else: for s in r["reports"]: i = 1 if s["sample_severity"] == "not_suspicious": level = "safe" elif s["sample_severity"] == "malicious": level = "malicious" else: level = "info" if r["reports"] > 1: value = "{}( from scan {})".format(s["score"], i) else: value = "{}".format(s["score"]) taxonomies.append(self.build_taxonomy(level, namespace, predicate, value)) i += 1 return {"taxonomies": taxonomies}
class VMRayAnalyzer(Analyzer): """ VMRay analyzer that uses VMRayClient to connect to an VMRay instance. Allows uploading a sample and getting information bac via submission data. More info regarding configuration in the complete documentation. """ _namespace = "VMRay" _severity_mapping = { "clean": "safe", "whitelisted": "safe", "suspicious": "suspicious", "malicious": "malicious", "blacklisted": "malicious", } _ioc_mapping = { "domains": ("domain", "domain"), "email_addresses": ("email", "mail"), "emails": ("sender", "mail"), "files": ("filename", "filename"), "ips": ("ip_address", "ip"), "mutexes": ("mutex_name", "other"), "registry": ("reg_key_name", "registry"), "urls": ("url", "url"), } def __init__(self): Analyzer.__init__(self) self.reanalyze = self.get_param("config.reanalyze", True) self.verdict_only = self.get_param("config.verdict_only", False) self.shareable = self.get_param("config.shareable", False) self.tags = self.get_param("config.tags", ["TheHive"]) self.user_config = { "timeout": self.get_param("config.timeout", None), "net_scheme_name": self.get_param("config.net_scheme_name", None), } self.query_retry_wait = self.get_param("config.query_retry_wait", 10) self.recursive_sample_limit = self.get_param( "config.recursive_sample_limit", 10) verify = self.get_param("config.certverify", True) certpath = self.get_param("config.certpath", None) if verify and certpath: verify = certpath archive_compound_sample = self.get_param( "config.archive_compound_sample", False) if archive_compound_sample: archive_action = "compound_sample" else: archive_action = "separate_samples" self.vmrc = VMRayClient( url=self.get_param("config.url", None, "No VMRay URL given.").rstrip("/ "), key=self.get_param("config.key", None, "No VMRay API key given."), reanalyze=self.reanalyze, verify=verify, archive_password=self.get_param("config.archive_password", "malware"), archive_action=archive_action, max_jobs=self.get_param("config.max_jobs", None), enable_reputation=self.get_param("config.enable_reputation", None), enable_whois=self.get_param("config.enable_whois", None), analyzer_mode=self.get_param("config.analyzer_mode", None), known_malicious=self.get_param("config.known_malicious", None), known_benign=self.get_param("config.known_benign", None), ) def _build_sample_node(self, sample, current_recursion_level): sample_id = sample["sample_id"] sample["sample_analyses"] = self.vmrc.get_sample_analyses(sample_id) sample[ "sample_threat_indicators"] = self.vmrc.get_sample_threat_indicators( sample_id) sample["sample_mitre_attack"] = self.vmrc.get_sample_mitre_attack( sample_id) sample["sample_iocs"] = self.vmrc.get_sample_iocs(sample_id) if self.recursive_sample_limit > current_recursion_level: sample["sample_child_samples"] = [ self.vmrc.get_sample(child_sample_id) for child_sample_id in sample["sample_child_sample_ids"] ] for child_sample in sample["sample_child_samples"]: self._build_sample_node(child_sample, current_recursion_level + 1) def _build_report(self, submissions=None, samples=None): if not submissions and not samples: self.error( "Either submissions or samples must be provided in order to build a report" ) return sample_ids = ([sample["sample_id"] for sample in samples] if samples else [ submission["submission_sample_id"] for submission in submissions ]) # note: the dictionary fetched in case the reanalysis is disabled is incomplete. we need to query the samples again in all cases samples = [self.vmrc.get_sample(sample_id) for sample_id in sample_ids] for sample in samples: self._build_sample_node(sample, 0) return {"samples": samples} def _wait_for_results(self, submission_result): # Ref: #332: check if job was submitted if not self.reanalyze: if len(submission_result["errors"]) > 0: # Sample has alredy been analyzed and reanalysis is turned off, get the reports self.report( self._build_report(samples=submission_result["samples"])) return # stop waiting for report, because we already have it running_submissions = submission_result["submissions"] finished_submissions = [] while len(running_submissions) != len(finished_submissions): finished_submissions.extend([ updated_submission for updated_submission in ( self.vmrc.update_submission( current_submission["submission_id"]) for current_submission in running_submissions) if "submission_finished" in updated_submission and updated_submission["submission_finished"] ]) sleep(self.query_retry_wait) # Return the results self.report(self._build_report(submissions=finished_submissions)) def run(self): if self.data_type == "hash": # don't run anything, try to build a report using existing results instead samples = self.vmrc.get_samples_by_hash(self.get_data()) if samples: self.report(self._build_report(samples=samples)) else: self.report({"samples": samples}) elif self.data_type == "file": shareable = self.shareable and self.get_param("tlp") in (0, 1) self._wait_for_results( self.vmrc.submit_file_sample( file_path=self.get_param("file"), file_name=self.get_param("filename"), tags=self.tags, shareable=shareable, user_config=self.user_config, )) elif self.data_type == "url": shareable = self.shareable and self.get_param("tlp") in (0, 1) self._wait_for_results( self.vmrc.submit_url_sample( url_sample=self.get_data(), tags=self.tags, shareable=shareable, user_config=self.user_config, )) else: self.error("Data type currently not supported") def _taxonomies_for_samples(self, samples): taxonomies = [] for sample in samples: has_verdict = "sample_verdict" in sample level = (self._severity_mapping.get(sample["sample_verdict"], "info") if has_verdict else self._severity_mapping.get( sample["sample_severity"], "info")) value = "{}".format(sample["sample_verdict"] if has_verdict else sample["sample_score"]) if len(samples) > 1: value += " (from sample {})".format(sample["sample_id"]) taxonomies.append( self.build_taxonomy(level, self._namespace, "Verdict", value ) if has_verdict else self. build_taxonomy(level, self._namespace, "Score", value)) if not self.verdict_only: for threat_indicator in sample.get("sample_threat_indicators", {}).get( "threat_indicators", []): predicate = threat_indicator.get("category", None) value = threat_indicator.get("operation", "") if predicate: taxonomies.append( self.build_taxonomy(level, self._namespace, predicate, value)) for mitre_technique in sample.get( "sample_mitre_attack", {}).get("mitre_attack_techniques", []): predicate = mitre_technique.get("technique_id", None) value = mitre_technique.get("technique", "Unknown MITRE technique") if "tactics" in mitre_technique: value += " using tactics: {}".format(", ".join( mitre_technique["tactics"])) if predicate: taxonomies.append( self.build_taxonomy(level, self._namespace, predicate, value)) # add child sample taxonomies if they have been added taxonomies.extend( self._taxonomies_for_samples( sample.get("sample_child_samples", []))) return taxonomies def _sandbox_reports_for_samples(self, samples): sandbox = "vmray" sandbox_type = "on-premise" sandbox_reports = [] for sample in samples: permalink = sample.get("sample_webif_url", None) score = sample.get("sample_vti_score", 0) sandbox_report = { "permalink": permalink, "score": score, "sandbox-type": sandbox_type, "{}-sandbox".format(sandbox_type): sandbox, } sandbox_reports.append(sandbox_report) # add child sample taxonomies if they have been added sandbox_reports.extend( self._sandbox_reports_for_samples( sample.get("sample_child_samples", []))) return sandbox_reports def summary(self, raw): taxonomies = [] sandbox_reports = [] samples = raw.get("samples", []) if len(samples) == 0: taxonomies.append( self.build_taxonomy("info", self._namespace, "None", "No Scan")) else: taxonomies.extend(self._taxonomies_for_samples(samples)) sandbox_reports.extend(self._sandbox_reports_for_samples(samples)) return {"taxonomies": taxonomies, "sandbox-reports": sandbox_reports} def _artifacts_for_samples(self, samples): artifacts = [] for sample in samples: link = sample.get("sample_webif_url", None) iocs = sample.get("sample_iocs", {}).get("iocs", {}) for ( ioc_type, (ioc_payload_name, ioc_data_type), ) in self._ioc_mapping.items(): if ioc_type in iocs: for ioc_node in iocs[ioc_type]: severity = ioc_node.get("severity", "unknown") level = self._severity_mapping.get(severity, "info") tags = list(set((severity, level, ioc_node["type"]))) payload = ioc_node[ioc_payload_name] context_tags = [] if "hashes" in ioc_node: for hash_node in ioc_node["hashes"]: if "sha256_hash" in hash_node: hash_value = hash_node["sha256_hash"] context_tags.append( "sha256:{}".format(hash_value)) artifacts.append( self.build_artifact("hash", hash_value, message=link, tags=tags)) elif "operations" in ioc_node: for operation in ioc_node["operations"]: context_tags.append( "operation:{}".format(operation)) tags.extend(set(context_tags)) artifacts.append( self.build_artifact(ioc_data_type, payload, message=link, tags=tags)) # add child samples if they have been added artifacts.extend( self._artifacts_for_samples( sample.get("sample_child_samples", []))) return artifacts def artifacts(self, raw): return self._artifacts_for_samples(raw.get("samples", []))