mirror of https://github.com/MISP/PyMISP
chg: Update upload malware/attachment example script
Fix #447 Make data at attibute level more generic with getter/setter methodspull/452/head
parent
73c8d8b87d
commit
9df636cd37
|
@ -1,43 +1,60 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
from pymisp import PyMISP
|
from pymisp import ExpandedPyMISP, MISPEvent, MISPAttribute
|
||||||
from keys import misp_url, misp_key, misp_verifycert
|
from keys import misp_url, misp_key, misp_verifycert
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
from pathlib import Path
|
||||||
import glob
|
|
||||||
|
|
||||||
|
|
||||||
def init(url, key):
|
|
||||||
return PyMISP(url, key, misp_verifycert, 'json')
|
|
||||||
|
|
||||||
|
|
||||||
def upload_files(m, eid, paths, distrib, ids, categ, comment, info, analysis, threat):
|
|
||||||
out = m.upload_samplelist(paths, eid, distrib, ids, categ, comment, info, analysis, threat)
|
|
||||||
print(out)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser(description='Send malware sample to MISP.')
|
parser = argparse.ArgumentParser(description='Send malware sample to MISP.')
|
||||||
parser.add_argument("-u", "--upload", type=str, required=True, help="File or directory of files to upload.")
|
parser.add_argument("-u", "--upload", type=str, required=True, help="File or directory of files to upload.")
|
||||||
parser.add_argument("-e", "--event", type=int, help="Not supplying an event ID will cause MISP to create a single new event for all of the POSTed malware samples.")
|
|
||||||
parser.add_argument("-d", "--distrib", type=int, help="The distribution setting used for the attributes and for the newly created event, if relevant. [0-3].")
|
parser.add_argument("-d", "--distrib", type=int, help="The distribution setting used for the attributes and for the newly created event, if relevant. [0-3].")
|
||||||
parser.add_argument("-ids", action='store_true', help="You can flag all attributes created during the transaction to be marked as \"to_ids\" or not.")
|
parser.add_argument("-c", "--comment", type=str, help="Comment for the uploaded file(s).")
|
||||||
parser.add_argument("-c", "--categ", help="The category that will be assigned to the uploaded samples. Valid options are: Payload delivery, Artifacts dropped, Payload Installation, External Analysis.")
|
parser.add_argument('-m', '--is-malware', action='store_true', help='The file(s) to upload are malwares')
|
||||||
|
parser.add_argument('--expand', action='store_true', help='(Only if the file is a malware) Run lief expansion (creates objects)')
|
||||||
|
parser.add_argument("-e", "--event", type=int, default=None, help="Not supplying an event ID will cause MISP to create a single new event for all of the POSTed malware samples.")
|
||||||
parser.add_argument("-i", "--info", help="Used to populate the event info field if no event ID supplied.")
|
parser.add_argument("-i", "--info", help="Used to populate the event info field if no event ID supplied.")
|
||||||
parser.add_argument("-a", "--analysis", type=int, help="The analysis level of the newly created event, if applicatble. [0-2]")
|
|
||||||
parser.add_argument("-t", "--threat", type=int, help="The threat level ID of the newly created event, if applicatble. [1-4]")
|
|
||||||
parser.add_argument("-co", "--comment", type=str, help="Comment for the uploaded file(s).")
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
misp = init(misp_url, misp_key)
|
misp = ExpandedPyMISP(misp_url, misp_key, misp_verifycert)
|
||||||
|
|
||||||
files = []
|
files = []
|
||||||
if os.path.isfile(args.upload):
|
p = Path(args.upload)
|
||||||
files = [args.upload]
|
if p.is_file():
|
||||||
elif os.path.isdir(args.upload):
|
files = [p]
|
||||||
files = [f for f in glob.iglob(os.path.join(args.upload + '*'))]
|
elif p.is_dir():
|
||||||
|
files = [f for f in p.glob('**/*') if f.is_file()]
|
||||||
else:
|
else:
|
||||||
print('invalid file')
|
print('invalid upload path (must be file or dir)')
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
upload_files(misp, args.event, files, args.distrib, args.ids, args.categ, args.comment, args.info, args.analysis, args.threat)
|
if args.is_malware:
|
||||||
|
arg_type = 'malware-sample'
|
||||||
|
else:
|
||||||
|
arg_type = 'attachment'
|
||||||
|
|
||||||
|
# Create attributes
|
||||||
|
attributes = []
|
||||||
|
for f in files:
|
||||||
|
a = MISPAttribute()
|
||||||
|
a.type = arg_type
|
||||||
|
a.value = f.name
|
||||||
|
a.data = f
|
||||||
|
a.comment = args.comment
|
||||||
|
a.distribution = args.distrib
|
||||||
|
if args.expand and arg_type == 'malware-sample':
|
||||||
|
a.expand = 'binary'
|
||||||
|
attributes.append(a)
|
||||||
|
|
||||||
|
if args.event:
|
||||||
|
for a in attributes:
|
||||||
|
misp.add_attribute(args.event, a)
|
||||||
|
else:
|
||||||
|
m = MISPEvent()
|
||||||
|
m.info = args.info
|
||||||
|
m.distribution = args.distrib
|
||||||
|
m.attributes = attributes
|
||||||
|
if args.expand and arg_type == 'malware-sample':
|
||||||
|
m.run_expansions()
|
||||||
|
misp.add_event(m)
|
||||||
|
|
|
@ -41,6 +41,8 @@ if (3, 0) <= sys.version_info < (3, 6):
|
||||||
else:
|
else:
|
||||||
OLD_PY3 = False
|
OLD_PY3 = False
|
||||||
|
|
||||||
|
if sys.version_info >= (3, 6):
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from dateutil.parser import parse
|
from dateutil.parser import parse
|
||||||
|
@ -120,6 +122,7 @@ class MISPAttribute(AbstractMISP):
|
||||||
self.__category_type_mapping = describe_types['category_type_mappings']
|
self.__category_type_mapping = describe_types['category_type_mappings']
|
||||||
self.__sane_default = describe_types['sane_defaults']
|
self.__sane_default = describe_types['sane_defaults']
|
||||||
self.__strict = strict
|
self.__strict = strict
|
||||||
|
self._data = None
|
||||||
self.uuid = str(uuid.uuid4())
|
self.uuid = str(uuid.uuid4())
|
||||||
self.ShadowAttribute = []
|
self.ShadowAttribute = []
|
||||||
self.Sighting = []
|
self.Sighting = []
|
||||||
|
@ -251,7 +254,6 @@ class MISPAttribute(AbstractMISP):
|
||||||
# other possible values
|
# other possible values
|
||||||
if kwargs.get('data'):
|
if kwargs.get('data'):
|
||||||
self.data = kwargs.pop('data')
|
self.data = kwargs.pop('data')
|
||||||
self._load_data()
|
|
||||||
if kwargs.get('id'):
|
if kwargs.get('id'):
|
||||||
self.id = int(kwargs.pop('id'))
|
self.id = int(kwargs.pop('id'))
|
||||||
if kwargs.get('event_id'):
|
if kwargs.get('event_id'):
|
||||||
|
@ -294,7 +296,7 @@ class MISPAttribute(AbstractMISP):
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
to_return = super(MISPAttribute, self).to_dict()
|
to_return = super(MISPAttribute, self).to_dict()
|
||||||
if to_return.get('data'):
|
if self.data:
|
||||||
to_return['data'] = base64.b64encode(self.data.getvalue()).decode()
|
to_return['data'] = base64.b64encode(self.data.getvalue()).decode()
|
||||||
return to_return
|
return to_return
|
||||||
|
|
||||||
|
@ -328,9 +330,20 @@ class MISPAttribute(AbstractMISP):
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _load_data(self):
|
@property
|
||||||
if not isinstance(self.data, BytesIO):
|
def data(self):
|
||||||
self.data = BytesIO(base64.b64decode(self.data))
|
return self._data if self._data else None
|
||||||
|
|
||||||
|
@data.setter
|
||||||
|
def data(self, data):
|
||||||
|
if sys.version_info >= (3, 6):
|
||||||
|
if isinstance(data, Path):
|
||||||
|
with data.open('rb') as f:
|
||||||
|
self._data = BytesIO(f.read())
|
||||||
|
if isinstance(data, (str, bytes)):
|
||||||
|
self._data = BytesIO(base64.b64decode(data))
|
||||||
|
elif isinstance(data, BytesIO):
|
||||||
|
self._data = data
|
||||||
if self.type == 'malware-sample':
|
if self.type == 'malware-sample':
|
||||||
try:
|
try:
|
||||||
with ZipFile(self.data) as f:
|
with ZipFile(self.data) as f:
|
||||||
|
|
Loading…
Reference in New Issue