mirror of https://github.com/MISP/misp-modules
Submit malware samples
_submit now includes malware samples (zipped content from misp) _import checks when no vti_results are returned + bugfixpull/70/head
parent
5624104b77
commit
3253d92b42
|
@ -6,7 +6,6 @@ Submit sample to VMRay.
|
||||||
Submit a sample to VMRay
|
Submit a sample to VMRay
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
# Deal with malicious samples (ZIP file, 'infected')
|
|
||||||
# Deal with archive submissions
|
# Deal with archive submissions
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
@ -15,12 +14,13 @@ import json
|
||||||
import base64
|
import base64
|
||||||
|
|
||||||
import io
|
import io
|
||||||
|
import zipfile
|
||||||
|
|
||||||
from ._vmray.vmray_rest_api import VMRayRESTAPI
|
from ._vmray.vmray_rest_api import VMRayRESTAPI
|
||||||
|
|
||||||
misperrors = {'error': 'Error'}
|
misperrors = {'error': 'Error'}
|
||||||
mispattributes = {'input': ['attachment'], 'output': ['text', 'sha1', 'sha256', 'md5', 'link']}
|
mispattributes = {'input': ['attachment', 'malware-sample'], 'output': ['text', 'sha1', 'sha256', 'md5', 'link']}
|
||||||
moduleinfo = {'version': '0.1', 'author': 'Koen Van Impe',
|
moduleinfo = {'version': '0.2', 'author': 'Koen Van Impe',
|
||||||
'description': 'Submit a sample to VMRay',
|
'description': 'Submit a sample to VMRay',
|
||||||
'module-type': ['expansion']}
|
'module-type': ['expansion']}
|
||||||
moduleconfig = ['apikey', 'url', 'shareable', 'do_not_reanalyze', 'do_not_include_vmrayjobids']
|
moduleconfig = ['apikey', 'url', 'shareable', 'do_not_reanalyze', 'do_not_include_vmrayjobids']
|
||||||
|
@ -38,8 +38,23 @@ def handler(q=False):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = request.get("data")
|
data = request.get("data")
|
||||||
attachment = request.get("attachment")
|
if 'malware-sample' in request:
|
||||||
data = base64.b64decode(data)
|
# 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:
|
except:
|
||||||
misperrors['error'] = "Unable to process submited sample data"
|
misperrors['error'] = "Unable to process submited sample data"
|
||||||
return misperrors
|
return misperrors
|
||||||
|
@ -74,10 +89,10 @@ def handler(q=False):
|
||||||
do_not_include_vmrayjobids = False
|
do_not_include_vmrayjobids = False
|
||||||
include_vmrayjobids = not do_not_include_vmrayjobids
|
include_vmrayjobids = not do_not_include_vmrayjobids
|
||||||
|
|
||||||
if data and attachment:
|
if data and sample_filename:
|
||||||
args = {}
|
args = {}
|
||||||
args["shareable"] = shareable
|
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
|
args["reanalyze"] = reanalyze
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -84,6 +84,7 @@ def handler(q=False):
|
||||||
# Get all information on the sample, returns a set of finished analyze jobs
|
# Get all information on the sample, returns a set of finished analyze jobs
|
||||||
data = vmrayGetInfoAnalysis(api, sample_id)
|
data = vmrayGetInfoAnalysis(api, sample_id)
|
||||||
if data["data"]:
|
if data["data"]:
|
||||||
|
vti_patterns_found = False
|
||||||
for analysis in data["data"]:
|
for analysis in data["data"]:
|
||||||
analysis_id = analysis["analysis_id"]
|
analysis_id = analysis["analysis_id"]
|
||||||
|
|
||||||
|
@ -93,17 +94,23 @@ def handler(q=False):
|
||||||
|
|
||||||
if analysis_data:
|
if analysis_data:
|
||||||
p = vmrayVtiPatterns(analysis_data["vti_patterns"])
|
p = vmrayVtiPatterns(analysis_data["vti_patterns"])
|
||||||
if p:
|
if p and len(p["results"]) > 0:
|
||||||
if include_analysisid:
|
vti_patterns_found = True
|
||||||
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"})
|
|
||||||
vmray_results = {'results': vmray_results["results"] + p["results"]}
|
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)
|
# Clean up (remove doubles)
|
||||||
vmray_results = vmrayCleanup(vmray_results)
|
if vti_patterns_found:
|
||||||
return vmray_results
|
vmray_results = vmrayCleanup(vmray_results)
|
||||||
|
return vmray_results
|
||||||
|
else:
|
||||||
|
misperrors['error'] = "No vti_results returned or jobs not finished"
|
||||||
|
return misperrors
|
||||||
else:
|
else:
|
||||||
misperrors['error'] = "Unable to fetch sample id %u" % (sample_id)
|
misperrors['error'] = "Unable to fetch sample id %u" % (sample_id)
|
||||||
return misperrors
|
return misperrors
|
||||||
|
@ -172,6 +179,8 @@ def vmrayVtiPatterns(vti_patterns):
|
||||||
content = vmrayGeneric(pattern)
|
content = vmrayGeneric(pattern)
|
||||||
elif only_network_info is False and pattern["category"] == "_process" and pattern["operation"] == "_install_ipc_endpoint":
|
elif only_network_info is False and pattern["category"] == "_process" and pattern["operation"] == "_install_ipc_endpoint":
|
||||||
content = vmrayGeneric(pattern, "mutex", 1)
|
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":
|
elif only_network_info is False and pattern["category"] == "_anti_analysis" and pattern["operation"] == "_delay_execution":
|
||||||
content = vmrayGeneric(pattern)
|
content = vmrayGeneric(pattern)
|
||||||
|
@ -240,9 +249,11 @@ def vmrayGeneric(el, attr="", attrpos=1):
|
||||||
if content:
|
if content:
|
||||||
if attr:
|
if attr:
|
||||||
content_split = content.split("\"")
|
content_split = content.split("\"")
|
||||||
content_split[attrpos] = vmraySanitizeInput(content_split[attrpos])
|
# Attributes are between open " and close "; so use >
|
||||||
r["values"].append(content_split[attrpos])
|
if len(content_split) > attrpos:
|
||||||
r["types"] = [attr]
|
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,
|
# Adding the value also as text to get the extra description,
|
||||||
# but this is pretty useless for "url"
|
# but this is pretty useless for "url"
|
||||||
|
|
Loading…
Reference in New Issue