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/69/head
parent
adda9562c0
commit
7c05a8acef
|
@ -14,17 +14,20 @@ TODO:
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
import base64
|
import base64
|
||||||
|
import io
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
import zipfile
|
||||||
|
|
||||||
|
|
||||||
base_dir = os.path.dirname(__file__) or '.'
|
base_dir = os.path.dirname(__file__) or '.'
|
||||||
sys.path.append(base_dir)
|
sys.path.append(base_dir)
|
||||||
from vmray_rest_api import VMRayRESTAPI, VMRayRESTAPIError
|
from vmray_rest_api import VMRayRESTAPI, VMRayRESTAPIError
|
||||||
import io
|
|
||||||
|
|
||||||
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']
|
||||||
|
@ -39,11 +42,25 @@ def handler(q=False):
|
||||||
if q is False:
|
if q is False:
|
||||||
return False
|
return False
|
||||||
request = json.loads(q)
|
request = json.loads(q)
|
||||||
|
|
||||||
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
|
||||||
|
@ -78,10 +95,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:
|
||||||
|
|
|
@ -90,6 +90,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"]
|
||||||
|
|
||||||
|
@ -99,17 +100,25 @@ 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
|
||||||
|
@ -179,6 +188,8 @@ def vmrayVtiPatterns(vti_patterns):
|
||||||
content = vmrayGeneric(pattern)
|
content = vmrayGeneric(pattern)
|
||||||
elif only_network_info == False and pattern["category"] == "_process" and pattern["operation"] == "_install_ipc_endpoint":
|
elif only_network_info == 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 == False and pattern["category"] == "_process" and pattern["operation"] == "_crashed_process":
|
||||||
|
content = vmrayGeneric(pattern)
|
||||||
|
|
||||||
elif only_network_info == False and pattern["category"] == "_anti_analysis" and pattern["operation"] == "_delay_execution":
|
elif only_network_info == False and pattern["category"] == "_anti_analysis" and pattern["operation"] == "_delay_execution":
|
||||||
content = vmrayGeneric(pattern)
|
content = vmrayGeneric(pattern)
|
||||||
|
@ -247,9 +258,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