diff --git a/misp_modules/modules/expansion/vmray_submit.py b/misp_modules/modules/expansion/vmray_submit.py index 407853c..15b163b 100644 --- a/misp_modules/modules/expansion/vmray_submit.py +++ b/misp_modules/modules/expansion/vmray_submit.py @@ -6,7 +6,6 @@ Submit sample to VMRay. Submit a sample to VMRay TODO: - # Deal with malicious samples (ZIP file, 'infected') # Deal with archive submissions ''' @@ -15,12 +14,13 @@ import json import base64 import io +import zipfile from ._vmray.vmray_rest_api import VMRayRESTAPI misperrors = {'error': 'Error'} -mispattributes = {'input': ['attachment'], 'output': ['text', 'sha1', 'sha256', 'md5', 'link']} -moduleinfo = {'version': '0.1', 'author': 'Koen Van Impe', +mispattributes = {'input': ['attachment', 'malware-sample'], 'output': ['text', 'sha1', 'sha256', 'md5', 'link']} +moduleinfo = {'version': '0.2', 'author': 'Koen Van Impe', 'description': 'Submit a sample to VMRay', 'module-type': ['expansion']} moduleconfig = ['apikey', 'url', 'shareable', 'do_not_reanalyze', 'do_not_include_vmrayjobids'] @@ -38,8 +38,23 @@ def handler(q=False): try: data = request.get("data") - attachment = request.get("attachment") - data = base64.b64decode(data) + if 'malware-sample' in request: + # malicious samples are encrypted with zip (password infected) and then base64 encoded + sample_filename = request.get("malware-sample").split("|",1)[0] + data = base64.b64decode(data) + fl = io.BytesIO(data) + zf = zipfile.ZipFile(fl) + sample_hashname = zf.namelist()[0] + data = zf.read(sample_hashname,b"infected") + zf.close() + elif 'attachment' in request: + # All attachments get base64 encoded + sample_filename = request.get("attachment") + data = base64.b64decode(data) + + else: + misperrors['error'] = "No malware sample or attachment supplied" + return misperrors except: misperrors['error'] = "Unable to process submited sample data" return misperrors @@ -74,10 +89,10 @@ def handler(q=False): do_not_include_vmrayjobids = False include_vmrayjobids = not do_not_include_vmrayjobids - if data and attachment: + if data and sample_filename: args = {} args["shareable"] = shareable - args["sample_file"] = {'data': io.BytesIO(data), 'filename': attachment} + args["sample_file"] = {'data': io.BytesIO(data), 'filename': sample_filename} args["reanalyze"] = reanalyze try: diff --git a/misp_modules/modules/import_mod/vmray_import.py b/misp_modules/modules/import_mod/vmray_import.py index dceeb1f..a7b7110 100644 --- a/misp_modules/modules/import_mod/vmray_import.py +++ b/misp_modules/modules/import_mod/vmray_import.py @@ -84,6 +84,7 @@ def handler(q=False): # Get all information on the sample, returns a set of finished analyze jobs data = vmrayGetInfoAnalysis(api, sample_id) if data["data"]: + vti_patterns_found = False for analysis in data["data"]: analysis_id = analysis["analysis_id"] @@ -93,17 +94,23 @@ def handler(q=False): if analysis_data: p = vmrayVtiPatterns(analysis_data["vti_patterns"]) - if p: - if include_analysisid: - url1 = "https://cloud.vmray.com/user/analysis/view?from_sample_id=%u" % sample_id - url2 = "&id=%u" % analysis_id - url3 = "&sub=%2Freport%2Foverview.html" - p["results"].append({"values": url1 + url2 + url3, "types": "link"}) + if p and len(p["results"]) > 0: + vti_patterns_found = True vmray_results = {'results': vmray_results["results"] + p["results"]} - + if include_analysisid: + a_id = {'results': []} + url1 = "https://cloud.vmray.com/user/analysis/view?from_sample_id=%u" % sample_id + url2 = "&id=%u" % analysis_id + url3 = "&sub=%2Freport%2Foverview.html" + a_id["results"].append({ "values": url1 + url2 + url3, "types": "link" }) + vmray_results = {'results': vmray_results["results"] + a_id["results"] } # Clean up (remove doubles) - vmray_results = vmrayCleanup(vmray_results) - return vmray_results + if vti_patterns_found: + vmray_results = vmrayCleanup(vmray_results) + return vmray_results + else: + misperrors['error'] = "No vti_results returned or jobs not finished" + return misperrors else: misperrors['error'] = "Unable to fetch sample id %u" % (sample_id) return misperrors @@ -172,6 +179,8 @@ def vmrayVtiPatterns(vti_patterns): content = vmrayGeneric(pattern) elif only_network_info is False and pattern["category"] == "_process" and pattern["operation"] == "_install_ipc_endpoint": content = vmrayGeneric(pattern, "mutex", 1) + elif only_network_info is False and pattern["category"] == "_process" and pattern["operation"] == "_crashed_process": + content = vmrayGeneric(pattern) elif only_network_info is False and pattern["category"] == "_anti_analysis" and pattern["operation"] == "_delay_execution": content = vmrayGeneric(pattern) @@ -240,9 +249,11 @@ def vmrayGeneric(el, attr="", attrpos=1): if content: if attr: content_split = content.split("\"") - content_split[attrpos] = vmraySanitizeInput(content_split[attrpos]) - r["values"].append(content_split[attrpos]) - r["types"] = [attr] + # Attributes are between open " and close "; so use > + if len(content_split) > attrpos: + content_split[attrpos] = vmraySanitizeInput(content_split[attrpos]) + r["values"].append(content_split[attrpos]) + r["types"] = [attr] # Adding the value also as text to get the extra description, # but this is pretty useless for "url"