def _search_local_hashes(self, event, open_session=True): local = [] samples_count = 0 if isinstance(event, MISPEvent): misp_event = event elif event.get('Event') is None: self.log('error', event) return else: misp_event = MISPEvent() misp_event.load(event) if not hasattr(misp_event, 'id'): # The event doesn't exists upstream, breaking. return for a in misp_event.attributes + [ attribute for obj in misp_event.objects for attribute in obj.attributes ]: row = None if a.type == 'malware-sample': samples_count += 1 if a.type in ('md5', 'sha1', 'sha256'): row = Database().find(key=a.type, value=a.value) elif a.type in ('filename|md5', 'filename|sha1', 'filename|sha256'): row = Database().find(key=a.type.split('|')[1], value=a.value.split('|')[1]) elif a.type == 'malware-sample': row = Database().find(key='md5', value=a.value.split('|')[1]) if row: local.append(row[0]) self.log( 'info', 'Event {} contains {} samples.'.format(misp_event.id, samples_count)) if not open_session: return shas = set([l.sha256 for l in local]) if len(shas) == 1: __sessions__.new(get_sample_path(shas.pop()), MispEvent(misp_event, self.offline_mode)) elif len(shas) > 1: self.log('success', 'The following samples are in this viper instance:') __sessions__.new( misp_event=MispEvent(misp_event, self.offline_mode)) for s in shas: self.log('item', s) else: __sessions__.new( misp_event=MispEvent(misp_event, self.offline_mode)) self.log('info', 'No known (in Viper) samples in that event.')
def test_mispevent(self, capsys, filename): mispevent = MispEvent(os.path.join(FIXTURE_DIR, filename)) mispevent.online() mispevent.offline() ips = mispevent.get_all_ips() domains = mispevent.get_all_domains() urls = mispevent.get_all_urls() hashes = mispevent.get_all_hashes() assert '191.101.230.149' in ips assert not domains assert not urls assert '722050c1b3f110c0ac9f80bc80723407' in hashes[0] assert not hashes[1]
def misp(self, option, verbose=False, submit=False): if option == 'download_all': for event in self._get_local_events( os.path.join(self.cur_path, 'misp_events')): self._download_hashes(MispEvent(event), False) return if not __sessions__.is_attached_misp(): return if option == 'hashes': ehashes, shashes = __sessions__.current.misp_event.get_all_hashes() to_scan = sorted(ehashes + shashes, key=len) while to_scan: h = to_scan.pop() response = self.scan(h, verbose) if response and not isinstance(response, bool): to_scan = [eh for eh in to_scan if eh not in response] elif option == 'download': self._download_hashes(__sessions__.current.misp_event, verbose) elif option == "ips": ips = __sessions__.current.misp_event.get_all_ips() for ip in ips: self.pdns_ip(ip, verbose) elif option == "domains": domains = __sessions__.current.misp_event.get_all_domains() for d in domains: self.pdns_domain(d, verbose) elif option == "urls": urls = __sessions__.current.misp_event.get_all_urls() for u in urls: self.url(u, verbose, submit)
def publish(self): current_event = copy.deepcopy(__sessions__.current.misp_event.event) event = self.misp.publish(current_event) if not self._has_error_message(event): self.log('success', 'Event {} published.'.format(event['Event']['id'])) __sessions__.new(misp_event=MispEvent(event))
def open_samples(self): if self.args.list: self._display_tmp_files() elif self.args.delete: if self.args.delete != 'all': try: int(self.args.delete) except Exception: self.log( 'error', 'You can only delete all the samples of the samples of a specific event ID.' ) return if self._clean_tmp_samples(self.args.delete): self.log('success', 'Successfully removed.') else: self.log('error', 'Nothing to remove.') else: tmp_samples = self._load_tmp_samples() try: eid, path, name = tmp_samples[int(self.args.sid)] except IndexError: self.log('error', 'Invalid sid, please use misp open -l.') return event = self.misp.get(eid) if not self._has_error_message(event): return __sessions__.new(path, MispEvent(event, self.offline_mode))
def download(self): ok = False data = None if self.args.hash: ok, data = self.misp.download_samples(sample_hash=self.args.hash) else: event_id = self._get_eventid() if event_id is None: return ok, data = self.misp.download_samples(event_id=event_id) if not ok: self.log('error', data) return to_print = [] for d in data: eid, filename, payload = d path = os.path.join(tempfile.gettempdir(), filename) with open(path, 'w') as f: f.write(payload.getvalue()) to_print.append((eid, path)) if len(to_print) == 1: self.log( 'success', 'The sample has been downloaded from Event {}'.format( to_print[0][0])) event = self.misp.get(to_print[0][0]) if not self._has_error_message(event): return __sessions__.new(to_print[0][1], MispEvent(event)) else: self.log('success', 'The following files have been downloaded:') for p in to_print: self.log('success', '\tEventID: {} - {}'.format(*p))
def upload(self): if self.offline_mode: self.log('error', 'Offline mode, unable to upload a sample') return categ = self.categories.get(self.args.categ) if self.args.info is not None: info = ' '.join(self.args.info) else: info = None if self.args.comment is not None: comment = ' '.join(self.args.comment) else: comment = None # No need to check the output: is the event_id is none, we create a new one. event_id = self._get_eventid(True) try: result = self.misp.upload_sample(__sessions__.current.file.name, __sessions__.current.file.path, event_id, self.args.distrib, self.args.ids, categ, info, comment, self.args.analysis, self.args.threat) except Exception as e: self.log('error', e) return if not self._has_error_message(result): self.log('success', "File uploaded successfully") if event_id is None: event_id = result['id'] full_event = self.misp.get(event_id) if not self._has_error_message(full_event): return __sessions__.new(misp_event=MispEvent(full_event, self.offline_mode))
def create_event(self): if self.args.threat is not None: # Dirty trick to keep consistency in the module: the threat level in the upload # API can go from 0 import to 3 but it is 1 to 4 in the event mgmt API. # It will be fixed in a near future, in the meantime, we do that: self.args.threat += 1 if not self.args.info: self.log('error', 'Info field is required for a new event') info = ' '.join(self.args.info) # Check if the following arguments have been set (and correctly set). If not, take the config values self.args.distrib = self.distribution if self.args.distrib is None else self.args.distrib self.args.sharing = self.sharinggroup if self.args.sharing is None else self.args.sharing if self.args.sharing and self.args.distrib != 4: self.args.sharing = None self.log('info', "Sharing group can only be set if distribution is 4. Clearing set value") misp_event = MISPEvent() misp_event.from_dict(info=info, distribution=self.args.distrib, sharing_group_id=self.args.sharing, threat_level_id=self.args.threat, analysis=self.args.analysis, date=self.args.date) self._search_local_hashes(misp_event) if self.offline_mode: # New event created locally, no ID __sessions__.current.misp_event.current_dump_file = self._dump() __sessions__.current.misp_event.offline() else: misp_event = self.misp.add_event(misp_event) if self._has_error_message(misp_event): return __sessions__.new(misp_event=MispEvent(misp_event, self.offline_mode)) self._dump()
def store(self): try: event_path = os.path.join(self.cur_path, 'misp_events') if not os.path.exists(event_path): os.mkdir(event_path) if self.args.list: header = ['Event ID', 'Title'] rows = [] for eid, path, title in self._get_local_events(event_path): rows.append((eid, title)) self.log('table', dict(header=header, rows=sorted(rows, key=lambda i: (int(i[0]))))) elif self.args.update: for eid, path, title in self._get_local_events(event_path): event = self.misp.get(eid) with open(path, 'w') as f: f.write(json.dumps(event)) self.log('success', '{} updated successfully.'.format(eid)) elif self.args.delete: path = os.path.join(event_path, '{}.json'.format(self.args.delete)) if os.path.exists(path): os.remove(path) self.log('success', '{} removed successfully.'.format(self.args.delete)) else: self.log('error', '{} does not exists.'.format(self.args.delete)) elif self.args.open: path = os.path.join(event_path, '{}.json'.format(self.args.open)) if os.path.exists(path): e_json = json.loads(open(path, 'r').read()) __sessions__.new(misp_event=MispEvent(e_json)) else: self.log('error', '{} does not exists.'.format(self.args.open)) elif __sessions__.is_attached_misp(): self._dump(__sessions__.current.misp_event.event) except IOError as e: self.log('error', e.strerror)
def download(self): ok = False data = None if self.args.hash: ok, data = self.misp.download_samples(sample_hash=self.args.hash) elif self.args.list is not None: list_events = [] if len(self.args.list) == 0: event_path = os.path.join(self.cur_path, 'misp_events') for eid, path, title in self._get_local_events(event_path): list_events.append(eid) else: list_events = self.args.list all_data = [] for eid in list_events: event = self.misp.get(eid) ok, data = self.misp.download_samples( event_id=event['Event']['id']) if not ok: self.log('error', data) continue if data: all_data += data data = all_data else: event_id = self._get_eventid() if event_id is None: return ok, data = self.misp.download_samples(event_id=event_id) if not ok: self.log('error', data) return to_print = [] samples_path = os.path.join(self.cur_path, 'misp_samples') for d in data: eid, filename, payload = d path = os.path.join(samples_path, eid, filename) if not os.path.exists(os.path.dirname(path)): os.makedirs(os.path.dirname(path)) with open(path, 'w') as f: f.write(payload.getvalue()) to_print.append((eid, path)) if len(to_print) == 1: self.log( 'success', 'The sample has been downloaded from Event {}'.format( to_print[0][0])) event = self.misp.get(to_print[0][0]) if not self._has_error_message(event): return __sessions__.new(to_print[0][1], MispEvent(event)) elif len(to_print) > 1: self.log('success', 'The following files have been downloaded:') self._display_tmp_files() else: self.log('warning', 'No samples available.')
def _search_local_hashes(self, event, open_session=True): local = [] samples_count = 0 if event.get('Event') is None: self.log('error', event) return for a in event['Event']['Attribute']: row = None if a['type'] == 'malware-sample': samples_count += 1 if a['type'] in ('malware-sample', 'filename|md5', 'md5'): h = a['value'] if '|' in a['type']: h = a['value'].split('|')[1] row = Database().find(key='md5', value=h) elif a['type'] in ('sha1', 'filename|sha1'): h = a['value'] if '|' in a['type']: h = a['value'].split('|')[1] row = Database().find(key='sha1', value=h) elif a['type'] in ('sha256', 'filename|sha256'): h = a['value'] if '|' in a['type']: h = a['value'].split('|')[1] row = Database().find(key='sha256', value=h) if row: local.append(row[0]) self.log( 'info', 'Event {} contains {} samples.'.format(event['Event']['id'], samples_count)) if not open_session: return shas = set([l.sha256 for l in local]) if len(shas) == 1: __sessions__.new(get_sample_path(shas.pop()), MispEvent(event)) elif len(shas) > 1: self.log('success', 'The following samples are in this viper instance:') __sessions__.new(misp_event=MispEvent(event)) for s in shas: self.log('item', s) else: __sessions__.new(misp_event=MispEvent(event)) self.log('info', 'No known (in Viper) samples in that event.')
def _populate(self, event, original_attributes): if len(event.attributes) == original_attributes: self.log('info', "No new attributes to add.") return event.timestamp = int(time.time()) result = self.misp.update(event._json()) if not self._has_error_message(result): self.log('success', "All attributes updated successfully") __sessions__.new(misp_event=MispEvent(result, self.offline_mode))
def publish(self): __sessions__.current.misp_event.event.publish() if self.offline_mode: self._dump() else: event = self.misp.update(__sessions__.current.misp_event.event) if not self._has_error_message(event): self.log('success', 'Event {} published.'.format(event['Event']['id'])) __sessions__.new(misp_event=MispEvent(event, self.offline_mode))
def _populate(self, event): result = self.misp.update(event) if not self._has_error_message(result): self.log('success', "All attributes updated successfully") event_id = self._get_eventid() if event_id is None: return event = self.misp.get(event_id) if self._has_error_message(event): return __sessions__.new(misp_event=MispEvent(event, self.offline_mode))
def _populate(self, event, attributes): if len(attributes) == 0: self.log('info', "No new attributes to add.") return to_send = {'Event': {'id': int(event['id']), 'uuid': event['uuid'], 'date': event['date'], 'distribution': event['distribution'], 'threat_level_id': event['threat_level_id'], 'analysis': event['analysis'], 'Attribute': attributes, 'timestamp': int(time.time())}} result = self.misp.update(to_send) if not self._has_error_message(result): self.log('success', "All attributes updated sucessfully") __sessions__.new(misp_event=MispEvent(result))
def _check_add(self, new_event): if not new_event.get('Event'): self.log('error', new_event) return old_related = self._find_related_id(__sessions__.current.misp_event.event.get('Event')) new_related = self._find_related_id(new_event.get('Event')) old_related_ids = [i[0] for i in old_related] for related, title in new_related: if related not in old_related_ids: self.log('success', u'New related event: {}/events/view/{} - {}'.format(self.url.rstrip('/'), related, title)) else: self.log('info', 'Related event: {}/events/view/{} - {}'.format(self.url.rstrip('/'), related, title)) __sessions__.new(misp_event=MispEvent(new_event))
def _check_add(self, new_event): old_related = self._find_related_id(__sessions__.current.misp_event.event) new_related = self._find_related_id(new_event) old_related_ids = [i[0] for i in old_related] for related, title in new_related: if related not in old_related_ids: self.log( 'success', 'New related event: {}/events/view/{} - {}'.format( self.url.rstrip('/'), related, title)) else: self.log( 'info', 'Related event: {}/events/view/{} - {}'.format( self.url.rstrip('/'), related, title)) __sessions__.new(misp_event=MispEvent(new_event, self.offline_mode))
def test_opened_session(self, capsys, filename, command, expected): if filename == "chromeinstall-8u31.exe": __sessions__.new(path=os.path.join(FIXTURE_DIR, filename)) elif filename == '58e902cd-dae8-49b9-882b-186c02de0b81.json': me = MispEvent(os.path.join(FIXTURE_DIR, filename), True) __sessions__.new(misp_event=me) instance = console.Console() if sys.version_info <= (3, 0): in_fct = 'viper.core.ui.console.input' else: in_fct = 'builtins.input' with mock.patch(in_fct, return_value='{};exit'.format(command)): instance.start() out, err = capsys.readouterr() assert re.search(r".*{}.*".format(expected), out)
def store(self): try: event_path = os.path.join(self.cur_path, 'misp_events') if not os.path.exists(event_path): os.mkdir(event_path) if self.args.list: header = ['Event ID', 'Title'] rows = [] for eid, path, title in self._get_local_events(event_path): rows.append((eid, title)) self.log( 'table', dict(header=header, rows=sorted(rows, key=lambda i: (int(i[0].split('_')[-1]))))) elif self.args.update: if self.offline_mode: self.log('error', 'Offline mode, cannot update locally stored events.') return for eid, path, title in self._get_local_events(event_path): event = self.misp.get(eid) with open(path, 'w') as f: f.write(json.dumps(event)) self.log('success', '{} updated successfully.'.format(eid)) elif self.args.sync: if self.offline_mode: self.log( 'error', 'Offline mode, cannot synchronize locally stored events.') return for eid, path, title in self._get_local_events(event_path): __sessions__.close() event = MISPEvent() event.load(path) if 'new_event_' in path: event = self.misp.add_event(event.to_json()) try: self._dump(event) os.remove(path) except Exception as e: self.log('error', 'Unable to create new event: {}.'.format(e)) else: eid = event.id try: event = self.misp.update(event._json()) except Exception as e: self.log( 'error', 'Unable to update event {}: {}.'.format(eid, e)) if self._has_error_message(event): return elif self.args.delete: path = os.path.join(event_path, '{}.json'.format(self.args.delete)) if os.path.exists(path): os.remove(path) self.log('success', '{} removed successfully.'.format(self.args.delete)) else: self.log('error', '{} does not exists.'.format(self.args.delete)) elif self.args.open: filename = '{}.json'.format(self.args.open) path = os.path.join(event_path, filename) if os.path.exists(path): try: with open(path, 'r') as f: e_json = json.load(f) __sessions__.new( misp_event=MispEvent(e_json, self.offline_mode)) __sessions__.current.misp_event.current_dump_file = filename except Exception as e: self.log('error', 'Unable to open {}: {}'.format(path, e)) else: self.log('error', '{} does not exists.'.format(self.args.open)) elif __sessions__.is_attached_misp(): self._dump() except IOError as e: self.log('error', e.strerror)