def make_objects(self, path=None, pseudofile=None, filename=None): to_return = {'objects': [], 'references': []} if path: fo, peo, seos = make_binary_objects(path) else: fo, peo, seos = make_binary_objects(pseudofile=pseudofile, filename=filename) if seos: for s in seos: to_return['objects'].append(s) if s.ObjectReference: to_return['references'] += s.ObjectReference if peo: to_return['objects'].append(peo) if peo.ObjectReference: to_return['references'] += peo.ObjectReference if fo: to_return['objects'].append(fo) if fo.ObjectReference: to_return['references'] += fo.ObjectReference # Remove UUIDs for comparing the objects. for o in to_return['objects']: o.pop('uuid') for o in to_return['references']: o.pop('referenced_uuid') o.pop('object_uuid') return json.dumps(to_return, cls=MISPEncode)
def add_sample(self): """Add the sample/target of the analysis""" target = self.report.get("target", {}) category = target.get("category", "") if not category: log.warning("Could not find info about the sample " "in the report, skipping") return False if category == "file": log.debug("Sample is a file, uploading it") self.read_malware() file_o, bin_type_o, bin_section_li = make_binary_objects( pseudofile=io.BytesIO(self.malware_binary), filename=target["file"]["name"], ) file_o.comment = "Submitted sample" # fix categories for obj in filter(None, ( file_o, bin_type_o, *bin_section_li, )): for attr in obj.attributes: if attr.type in PAYLOAD_DELIVERY: attr.category = "Payload delivery" self.event.add_object(obj) elif category == "url": log.debug("Sample is a URL") o = MISPObject(name='url') o.add_attribute('url', target['url']) o.add_attribute('text', "Submitted URL") self.event.add_object(o)
def add_hashes(self): if self.args.filename is None and self.args.md5 is None and self.args.sha1 is None and self.args.sha256 is None: if not __sessions__.is_attached_file(True): self.log('error', "Not attached to a file, please set the hashes manually.") return False file_obj, bin_obj, sections = make_binary_objects(filepath=__sessions__.current.file.path, standalone=False) __sessions__.current.misp_event.event.add_object(file_obj) if bin_obj: __sessions__.current.misp_event.event.add_object(bin_obj) for s in sections: __sessions__.current.misp_event.event.add_object(s) else: if self.args.filename: if self.args.md5: __sessions__.current.misp_event.event.add_attribute('filename|md5', '{}|{}'.format( self.args.filename, self.args.md5)) if self.args.sha1: __sessions__.current.misp_event.event.add_attribute('filename|sha1', '{}|{}'.format( self.args.filename, self.args.sha1)) if self.args.sha256: __sessions__.current.misp_event.event.add_attribute('filename|sha256', '{}|{}'.format( self.args.filename, self.args.sha256)) else: if self.args.md5: __sessions__.current.misp_event.event.add_attribute('md5', self.args.md5) if self.args.sha1: __sessions__.current.misp_event.event.add_attribute('sha1', self.args.sha1) if self.args.sha256: __sessions__.current.misp_event.event.add_attribute('sha256', self.args.sha256) self._change_event()
def unzip_attachement(filename, data, email_object, file_objects, password=None): """Extract the contents of a zipfile. Args: filename (str): A string containing the name of the zip file. data (decoded attachment data): Data object decoded from an e-mail part. Returns: Returns an array containing a dict for each file Example Dict {"values":"name_of_file.txt", "data":<Base64 Encoded BytesIO>, "comment":"string here"} """ with zipfile.ZipFile(data, "r") as zf: if password is not None: comment = f'Extracted from {filename} with password "{password}"' password = str.encode(password) # Byte encoded password required else: comment = f'Extracted from {filename}' for zip_file_name in zf.namelist(): # Get all files in the zip file with zf.open(zip_file_name, mode='r', pwd=password) as fp: file_data = BytesIO(fp.read()) f_object, main_object, sections = make_binary_objects( pseudofile=file_data, filename=zip_file_name, standalone=False) f_object.comment = comment file_objects.append(f_object) file_objects.append(main_object) file_objects += sections email_object.add_reference(f_object.uuid, 'includes', 'Email attachment')
def make_objects(path): to_return = {'objects': [], 'references': []} fo, peo, seos = make_binary_objects(path) if seos: for s in seos: to_return['objects'].append(s) if s.ObjectReference: to_return['references'] += s.ObjectReference if peo: if hasattr(peo, 'certificates') and hasattr(peo, 'signers'): # special authenticode case for PE objects for c in peo.certificates: to_return['objects'].append(c) for s in peo.signers: to_return['objects'].append(s) del peo.certificates del peo.signers del peo.sections to_return['objects'].append(peo) if peo.ObjectReference: to_return['references'] += peo.ObjectReference if fo: to_return['objects'].append(fo) if fo.ObjectReference: to_return['references'] += fo.ObjectReference return json.dumps(to_return, default=pymisp_json_default)
def _find_attached_forward(self): forwarded_emails = [] for attachment in self.original_mail.iter_attachments(): try: attachment_content = attachment.get_content() except KeyError: # Attachment type has no handler continue # Search for email forwarded as attachment # I could have more than one, attaching everything. if isinstance(attachment_content, message.EmailMessage): forwarded_emails.append(self.forwarded_email(pseudofile=BytesIO(attachment_content.as_bytes()))) else: if isinstance(attachment_content, str): attachment_content = attachment_content.encode() filename = attachment.get_filename() if not filename: filename = 'missing_filename' if self.config_from_email_body.get('attachment') == self.config.m2m_benign_attachment_keyword: # Attach sane file self.misp_event.add_attribute('attachment', value=filename, data=BytesIO(attachment_content)) else: f_object, main_object, sections = make_binary_objects(pseudofile=BytesIO(attachment_content), filename=filename, standalone=False) self.misp_event.add_object(f_object) if main_object: self.misp_event.add_object(main_object) [self.misp_event.add_object(section) for section in sections] return forwarded_emails
def _get_dropped_objs(self, path, filename=None, comment=None): """ Internal wrapper to get dropped files/buffers as file objects @ params - path: relative to the cuckoo analysis directory - filename: if not specified, deduced from the path """ if not filename: filename = posixpath.basename(path) dropped_file = self.get_file(path) dropped_binary = io.BytesIO(dropped_file.read()) # create ad hoc objects file_o, bin_type_o, bin_section_li = make_binary_objects( pseudofile=dropped_binary, filename=filename, ) if comment: file_o.comment = comment # fix categories for obj in filter(None, ( file_o, bin_type_o, *bin_section_li, )): for attr in obj.attributes: if attr.type in ARTIFACTS_DROPPED: attr.category = "Artifacts dropped" return file_o, bin_type_o, bin_section_li
def forwarded_email(self, pseudofile: BytesIO): '''Extracts all possible indicators out of an email and create a MISP event out of it. * Gets all relevant Headers * Attach the body * Create MISP file objects (uses lief if possible) * Set all references ''' email_object = EMailObject(pseudofile=pseudofile, attach_original_mail=True, standalone=False) if email_object.attachments: # Create file objects for the attachments for attachment_name, attachment in email_object.attachments: if not (self.ignore_nullsize_attachments and attachment.getbuffer().nbytes == 0): if not attachment_name: attachment_name = 'NameMissing.txt' if self.config_from_email_body.get( 'attachment' ) == self.config.m2m_benign_attachment_keyword: a = self.misp_event.add_attribute( 'attachment', value=attachment_name, data=attachment) email_object.add_reference(a.uuid, 'related-to', 'Email attachment') else: f_object, main_object, sections = make_binary_objects( pseudofile=attachment, filename=attachment_name, standalone=False) if self.config.vt_key: try: vt_object = VTReportObject( self.config.vt_key, f_object.get_attributes_by_relation( 'sha256')[0].value, standalone=False) self.misp_event.add_object(vt_object) f_object.add_reference(vt_object.uuid, 'analysed-with') except InvalidMISPObject as e: print(e) pass self.misp_event.add_object(f_object) if main_object: self.misp_event.add_object(main_object) for section in sections: self.misp_event.add_object(section) email_object.add_reference(f_object.uuid, 'related-to', 'Email attachment') self.process_body_iocs(email_object) if self.config.spamtrap or self.config.attach_original_mail or self.config_from_email_body.get( 'attach_original_mail'): self.misp_event.add_object(email_object) return email_object
def add_file(self, event_id, path, filename, object_type): fo = None peo = None seos = None # try: if not object_type == "master": dap = { "category": "Artifacts dropped" } #, "self.sharing_group_id": None, "distribution": 5} fo, peo, seos = make_binary_objects( path, filename=filename, default_attributes_parameters=dap) else: fo, peo, seos = make_binary_objects(path, filename=filename) # except Exception as e: # traceback.print_exc() if seos and self.options.get("seo", False): for s in seos: template_id = self.misp.get_object_template_id(s.template_uuid) r = self.misp.add_object(event_id, template_id, s) if peo and self.options.get("peo", False): template_id = self.misp.get_object_template_id(peo.template_uuid) r = self.misp.add_object(event_id, template_id, peo) for ref in peo.ObjectReference: r = self.misp.add_object_reference(ref) if fo: template_id = self.misp.get_object_template_id(fo.template_uuid) response = self.misp.add_object(event_id, template_id, fo) if self.options.get("seo", False) or self.options.get( "peo", False): for ref in fo.ObjectReference: r = self.misp.add_object_reference(ref) if fo and object_type == 'master': self.master_obj = fo else: self.slaves_id.append(fo.uuid)
def add_file(self, event_id, path, filename, object_type): fo = None peo = None seos = None # try: if not object_type == "master": dap = {"category": "Artifacts dropped"}#, "self.sharing_group_id": None, "distribution": 5} fo, peo, seos = make_binary_objects(path, filename=filename, default_attributes_parameters=dap) else: fo, peo, seos = make_binary_objects(path, filename=filename) # except Exception as e: # traceback.print_exc() if seos and self.options.get("seo", False): for s in seos: template_id = self.misp.get_object_template_id(s.template_uuid) r = self.misp.add_object(event_id, template_id, s) if peo and self.options.get("peo", False): template_id = self.misp.get_object_template_id(peo.template_uuid) r = self.misp.add_object(event_id, template_id, peo) for ref in peo.ObjectReference: r = self.misp.add_object_reference(ref) if fo: template_id = self.misp.get_object_template_id(fo.template_uuid) response = self.misp.add_object(event_id, template_id, fo) if self.options.get("seo", False) or self.options.get("peo", False): for ref in fo.ObjectReference: r = self.misp.add_object_reference(ref) if fo and object_type == 'master': self.master_obj = fo else: self.slaves_id.append(fo.uuid)
def _expand_local_sample(self, pseudofile, filename, refobj=None, default_attributes_paramaters={}): objs = [] hashes = [] # Just expand the event with every possible objects fo, peo, seos = make_binary_objects(pseudofile=pseudofile, filename=filename, standalone=False, default_attributes_paramaters=default_attributes_paramaters) fo.add_reference(refobj, 'derived-from') hashes += [h.value for h in fo.get_attributes_by_relation('sha256')] hashes += [h.value for h in fo.get_attributes_by_relation('sha1')] hashes += [h.value for h in fo.get_attributes_by_relation('md5')] if self.args.populate: objs.append(fo) if peo: objs.append(peo) if seos: objs += seos return objs, hashes
def make_objects(self, path): to_return = {'objects': [], 'references': []} fo, peo, seos = make_binary_objects(path) if seos: for s in seos: to_return['objects'].append(s) if s.ObjectReference: to_return['references'] += s.ObjectReference if peo: to_return['objects'].append(peo) if peo.ObjectReference: to_return['references'] += peo.ObjectReference if fo: to_return['objects'].append(fo) if fo.ObjectReference: to_return['references'] += fo.ObjectReference return json.dumps(to_return, cls=MISPEncode)
def make_objects(path): to_return = {'objects': [], 'references': []} fo, peo, seos = make_binary_objects(path) if seos: for s in seos: to_return['objects'].append(s) if s.ObjectReference: to_return['references'] += s.ObjectReference if peo: to_return['objects'].append(peo) if peo.ObjectReference: to_return['references'] += peo.ObjectReference if fo: to_return['objects'].append(fo) if fo.ObjectReference: to_return['references'] += fo.ObjectReference return json.dumps(to_return, cls=MISPEncode)
def make_objects(path): to_return = {'objects': [], 'references': []} fo, peo, seos = make_binary_objects(path) if seos: for s in seos: to_return['objects'].append(s) if s.ObjectReference: to_return['references'] += s.ObjectReference if peo: to_return['objects'].append(peo) if peo.ObjectReference: to_return['references'] += peo.ObjectReference if fo: to_return['objects'].append(fo) if fo.ObjectReference: to_return['references'] += fo.ObjectReference return json.dumps(to_return, default=pymisp_json_default)
def add_hashes(self): if self.args.filename is None and self.args.md5 is None and self.args.sha1 is None and self.args.sha256 is None: if not __sessions__.is_attached_file(True): self.log( 'error', "Not attached to a file, please set the hashes manually.") return False file_obj, bin_obj, sections = make_binary_objects( filepath=__sessions__.current.file.path, standalone=False) __sessions__.current.misp_event.event.add_object(file_obj) if bin_obj: __sessions__.current.misp_event.event.add_object(bin_obj) for s in sections: __sessions__.current.misp_event.event.add_object(s) else: if self.args.filename: if self.args.md5: __sessions__.current.misp_event.event.add_attribute( 'filename|md5', '{}|{}'.format(self.args.filename, self.args.md5)) if self.args.sha1: __sessions__.current.misp_event.event.add_attribute( 'filename|sha1', '{}|{}'.format(self.args.filename, self.args.sha1)) if self.args.sha256: __sessions__.current.misp_event.event.add_attribute( 'filename|sha256', '{}|{}'.format(self.args.filename, self.args.sha256)) else: if self.args.md5: __sessions__.current.misp_event.event.add_attribute( 'md5', self.args.md5) if self.args.sha1: __sessions__.current.misp_event.event.add_attribute( 'sha1', self.args.sha1) if self.args.sha256: __sessions__.current.misp_event.event.add_attribute( 'sha256', self.args.sha256) self._change_event()
def _expand_local_sample(self, pseudofile, filename, refobj=None, default_attributes_parameters={}): objs = [] hashes = [] # Just expand the event with every possible objects fo, peo, seos = make_binary_objects( pseudofile=pseudofile, filename=filename, standalone=False, default_attributes_parameters=default_attributes_parameters) fo.add_reference(refobj, 'derived-from') hashes += [h.value for h in fo.get_attributes_by_relation('sha256')] hashes += [h.value for h in fo.get_attributes_by_relation('sha1')] hashes += [h.value for h in fo.get_attributes_by_relation('md5')] if self.args.populate: objs.append(fo) if peo: objs.append(peo) if seos: objs += seos return objs, hashes
import traceback from keys import misp_url, misp_key, misp_verifycert import glob import argparse if __name__ == '__main__': parser = argparse.ArgumentParser(description='Extract indicators out of binaries and add MISP objects to a MISP instance.') parser.add_argument("-e", "--event", required=True, help="Event ID to update.") parser.add_argument("-p", "--path", required=True, help="Path to process (expanded using glob).") args = parser.parse_args() pymisp = PyMISP(misp_url, misp_key, misp_verifycert) for f in glob.glob(args.path): try: fo, peo, seos = make_binary_objects(f) except Exception as e: traceback.print_exc() continue if seos: for s in seos: template_id = pymisp.get_object_template_id(s.template_uuid) r = pymisp.add_object(args.event, template_id, s) if peo: template_id = pymisp.get_object_template_id(peo.template_uuid) r = pymisp.add_object(args.event, template_id, peo) for ref in peo.ObjectReference: r = pymisp.add_object_reference(ref)
) parser.add_argument("-e", "--event", required=True, help="Event ID to update.") parser.add_argument("-p", "--path", required=True, help="Path to process (expanded using glob).") args = parser.parse_args() pymisp = ExpandedPyMISP(misp_url, misp_key, misp_verifycert) for f in glob.glob(args.path): try: fo, peo, seos = make_binary_objects(f) except Exception: traceback.print_exc() continue if seos: for s in seos: r = pymisp.add_object(args.event, s) if peo: r = pymisp.add_object(args.event, peo) for ref in peo.ObjectReference: r = pymisp.add_object_reference(ref) if fo: response = pymisp.add_object(args.event, fo)
def createMalware(iUUID, iUpdate=False): try: # fUNCTION SETUP # ----------------------------------------------- myUUID = iUUID myTags = [] # ATTRIBUTES COMMON FIELDS # ----------------------------------------------- attributeToIDS = 0 # 0 false : 1 true attributeComment = "" attribDisableCorrelation = 1 # 0 false : 1 true # MISP SETUP # ----------------------------------------------- event = pm.MISPEvent() event.uuid = myUUID # GET UUID METADATA FROM PARENT CHILD TABLE # ----------------------------------------------- iPC_META = db.get_parent_child_data(iUUID=myUUID) parentuuid = iPC_META["parentuuid"] event.extends_uuid = parentuuid name = iPC_META["name"] if name in gv._BLACKLISTED_FILES: return True event.info = name print("f(x) createMalware: MALWARE SAMPLE NAME: {}".format(name)) # SET VERSION myVersion = iPC_META["version"] if myVersion != "": attributeType = "text" attributeCategory = "Internal reference" if gv._DEBUG: print( "f(x) createMalware: CREATING FAMILY COMMENT: \nCATEGORY: {} \nTYPE: {} \nVALUE: {} \nCOMMENT: {} \nDISABLE CORRELATION: {} \ ".format(attributeCategory, attributeType, myVersion, attributeToIDS, attributeComment, attribDisableCorrelation)) event.add_attribute(attributeType, myVersion, comment=attributeComment, category=attributeCategory, to_ids=attributeToIDS, disable_correlation=attribDisableCorrelation) # SET DATE ADDED date_added = iPC_META["date_added"] if valid_date(date_added): event.date = date_added else: event.date = datetime.date.today() # GET TAGS myTags = db.get_set_all_tags(myUUID) event.tags = myTags if gv._DEBUG: print("f(x) createMalware: TAGS") print(*myTags, sep="\n") # MARK SOURCE OF INFORMATION attributeType = "link" attributeCategory = "Internal reference" attributeComment = "DATA FROM MALPEDIA." if gv._DEBUG: print( "f(x) createMalware: ATTRIBUTION LINK: \nCATEGORY: {} \nTYPE: {} \nVALUE: {} \nTO_IDS: {} \nCOMMENT: {} \nDISABLE CORRELATION: {} \ ".format(attributeCategory, attributeType, gv._MALPEDIA_URL, attributeToIDS, attributeComment, attribDisableCorrelation)) event.add_attribute(attributeType, gv._MALPEDIA_URL, comment=attributeComment, category=attributeCategory, to_ids=attributeToIDS, disable_correlation=attribDisableCorrelation) # ADD ATTACHMENT myPath = iPC_META["path"] fo = None peo = None seos = None # CREATE ATTACHMENT BUT DON'T UPLOAD IT AGAIN IF THIS IS JUST AN UPDATE if iUpdate == False: for f in glob.glob(iPC_META["path"]): try: fo, peo, seos = make_binary_objects(f) except Exception as e: continue gv._THREAD_LIST.append( uexecutor.submit(pushToMISPWithAttachment, event, myPath, iUpdate, gv._MISP_URL, gv._MISP_KEY, gv._MISP_VERIFYCERT, gv._DEBUG, fo, peo, seos)) # pushToMISPWithAttachment(event, myPath, iUpdate, gv._MISP_URL, gv._MISP_KEY, gv._MISP_VERIFYCERT, gv._DEBUG, fo , peo, seos) except Exception as e: exc_type, _, exc_tb = sys.exc_info() fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] print("f(x) createMalware: {}: {}: {}".format(exc_type, fname, exc_tb.tb_lineno)) sys.exit(e)
def handler(q=False): if q is False: return False # Decode and parse email request = json.loads(q) # request data is always base 64 byte encoded data = base64.b64decode(request["data"]) email_object = EMailObject(pseudofile=BytesIO(data), attach_original_mail=True, standalone=False) # Check if we were given a configuration config = request.get("config", {}) # Don't be picky about how the user chooses to say yes to these acceptable_config_yes = ['y', 'yes', 'true', 't'] # Do we unzip attachments we find? unzip = config.get("unzip_attachments", None) if (unzip is not None and unzip.lower() in acceptable_config_yes): unzip = True # Do we try to find passwords for protected zip files? zip_pass_crack = config.get("guess_zip_attachment_passwords", None) if (zip_pass_crack is not None and zip_pass_crack.lower() in acceptable_config_yes): zip_pass_crack = True password_list = get_zip_passwords(email_object.email) # Do we extract URL's from the email. extract_urls = config.get("extract_urls", None) if (extract_urls is not None and extract_urls.lower() in acceptable_config_yes): extract_urls = True file_objects = [] # All possible file objects # Get Attachments # Get file names of attachments for attachment_name, attachment in email_object.attachments: # Create file objects for the attachments if not attachment_name: attachment_name = 'NameMissing.txt' temp_filename = Path(attachment_name) zipped_files = [ "doc", "docx", "dot", "dotx", "xls", "xlsx", "xlm", "xla", "xlc", "xlt", "xltx", "xlw", "ppt", "pptx", "pps", "ppsx", "pot", "potx", "potx", "sldx", "odt", "ods", "odp", "odg", "odf", "fodt", "fods", "fodp", "fodg", "ott", "uot" ] # Attempt to unzip the attachment and return its files if unzip and temp_filename.suffix[1:] not in zipped_files: try: unzip_attachement(attachment_name, attachment, email_object, file_objects) except RuntimeError: # File is encrypted with a password if zip_pass_crack is True: password = test_zip_passwords(attachment, password_list) if password: unzip_attachement(attachment_name, attachment, email_object, file_objects, password) else: # Inform the analyst that we could not crack password f_object, main_object, sections = make_binary_objects( pseudofile=attachment, filename=attachment_name, standalone=False) f_object.comment = "Encrypted Zip: Password could not be cracked from message" file_objects.append(f_object) file_objects.append(main_object) file_objects += sections email_object.add_reference(f_object.uuid, 'includes', 'Email attachment') except zipfile.BadZipFile: # Attachment is not a zipfile # Just straight add the file f_object, main_object, sections = make_binary_objects( pseudofile=attachment, filename=attachment_name, standalone=False) file_objects.append(f_object) file_objects.append(main_object) file_objects += sections email_object.add_reference(f_object.uuid, 'includes', 'Email attachment') else: # Just straight add the file f_object, main_object, sections = make_binary_objects( pseudofile=attachment, filename=attachment_name, standalone=False) file_objects.append(f_object) file_objects.append(main_object) file_objects += sections email_object.add_reference(f_object.uuid, 'includes', 'Email attachment') mail_body = email_object.email.get_body(preferencelist=('html', 'plain')) if extract_urls: if mail_body: charset = mail_body.get_content_charset() if mail_body.get_content_type() == 'text/html': url_parser = HTMLURLParser() url_parser.feed( mail_body.get_payload(decode=True).decode(charset, errors='ignore')) urls = url_parser.urls else: urls = re.findall( r'https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+', mail_body.get_payload(decode=True).decode(charset, errors='ignore')) for url in urls: if not url: continue url_object = URLObject(url, standalone=False) file_objects.append(url_object) email_object.add_reference(url_object.uuid, 'includes', 'URL in email body') objects = [email_object.to_json()] if file_objects: objects += [o.to_json() for o in file_objects if o] r = {'results': {'Object': [json.loads(o) for o in objects]}} return r
def add_object(self, event, data, filename): obj = make_binary_objects(pseudofile=BytesIO(data), filename=filename) if obj[1]: self.api.add_object(event['Event']['id'], 28, obj[1])