def _store_preloaded_file(self, filepath=None, fd=None): if not filepath and not fd: raise ValueError( "Please provide either the path to the file or a file-like " "object containing the data.") if filepath and fd: self.log( "debug", "Please provide either the path to the file or a " "file-like object containing the data, not both." "Choosing the filepath for now.") if fame_config.remote: if filepath: response = send_file_to_remote(filepath, '/files/') else: response = send_file_to_remote(fd, '/files/') return File(response.json()['file']) else: if filepath: with open(filepath, 'rb') as f: return File(filename=os.path.basename(filepath), stream=f) else: return File(filename=self._file['names'][0], stream=fd)
def add_extracted_file(self, filepath, automatic_analysis=True): self.log('debug', u"Adding extracted file '{}'".format(filepath)) fd = open(filepath, 'rb') filename = os.path.basename(filepath) f = File(filename=filename, stream=fd, create=False) if not f.existing: if fame_config.remote: response = send_file_to_remote(filepath, '/files/') f = File(response.json()['file']) else: f = File(filename=os.path.basename(filepath), stream=fd) # Automatically analyze extracted file if magic is enabled and module did not disable it if self.magic_enabled() and automatic_analysis: modules = None config = Config.get(name="extracted").get_values() if config is not None and "modules" in config: modules = config["modules"].split() f.analyze(self['groups'], self['analyst'], modules, self['options']) fd.close() self.append_to('extracted_files', f['_id']) f.add_parent_analysis(self)
def __init__(self, values): self['status'] = self.STATUS_PENDING self['executed_modules'] = [] self['pending_modules'] = [] self['waiting_modules'] = [] self['canceled_modules'] = [] self['tags'] = [] self['iocs'] = [] self['results'] = {} self['generated_files'] = {} self['extracted_files'] = [] self['support_files'] = {} self['logs'] = [] self['extractions'] = [] self['probable_names'] = [] self['options'] = {} self['date'] = datetime.datetime.now() self['end_date'] = None self['groups'] = [] self['analyst'] = [] MongoDict.__init__(self, values) self._file = File(store.files.find_one({'_id': self['file']})) if '_id' not in self: self._init_threat_intelligence() self.save() if self['modules']: self.queue_modules(self['modules']) else: self._automatic()
def add_group(self, id): f = File(get_or_404(current_user.files, _id=id)) group = request.form.get('group') f.add_groups([group]) return redirect(request.referrer)
def change_type(self, id): f = File(get_or_404(current_user.files, _id=id)) new_type = request.form.get('type') f.update_value("type", new_type) return redirect(request.referrer)
def add_comment(self, id): if comments_enabled(): f = File(get_or_404(current_user.files, _id=id)) if current_user.has_permission('add_probable_name'): probable_name = request.form.get('probable_name') else: probable_name = None comment = request.form.get('comment') analysis_id = request.form.get('analysis') notify = request.form.get('notify') if comment: # If there is an analysis ID, make sure it is accessible if analysis_id: get_or_404(current_user.analyses, _id=analysis_id) f.add_comment(current_user['_id'], comment, analysis_id, probable_name) if notify: self.notify_new_comment(f, analysis_id, current_user['_id'], comment) else: flash('Comment should not be empty', 'danger') return redirect(request.referrer)
def download(self, id): """Download the file with `id`. .. :quickref: File; Download a file :param id: id of the file to download. """ f = File(get_or_404(current_user.files, _id=id)) return file_download(f['filepath'])
def _get_object_to_analyze(self): file = request.files.get('file') or None url = request.form.get('url') or None hash = request.form.get('hash') or None f = None if file: f = File(filename=file.filename, stream=file.stream) elif url: stream = StringIO(url) f = File(filename='url', stream=stream) if not f.existing: f.update_value('type', 'url') f.update_value('names', [url]) elif hash: f = File(hash=hash) else: flash('You have to submit a file, a URL or a hash', 'danger') return f
def add_extracted_file(self, filepath): self.log('debug', "Adding extracted file '{}'".format(filepath)) fd = open(filepath, 'rb') filename = os.path.basename(filepath) f = File(filename=filename, stream=fd, create=False) if not f.existing: if fame_config.remote: response = send_file_to_remote(filepath, '/files/') f = File(response.json()['file']) else: f = File(filename=os.path.basename(filepath), stream=fd) f.analyze(self['groups'], self['analyst'], None, self['options']) fd.close() self.append_to('extracted_files', f['_id']) f.add_parent_analysis(self)
def remove_group(self, id): f = File(get_or_404(current_user.files, _id=id)) group = request.form.get('group') if group in f['owners']: flash('This group submitted this file themselves. You cannot neuralize them.', 'danger') else: f.remove_group(group) return redirect(request.referrer)
def _get_object_to_analyze(self): file = request.files.get('file') or None url = request.form.get('url') or None hash = request.form.get('hash') or None f = None if file: f = File(filename=file.filename, stream=file.stream) elif url: stream = StringIO(url) f = File(filename='url', stream=stream) if not f.existing: f.update_value('type', 'url') f.update_value('names', [url]) elif hash: config = Config.get(name="virustotal") if config: try: config = config.get_values() params = {'apikey': config.api_key, 'hash': hash} response = requests.get( 'https://www.virustotal.com/vtapi/v2/file/download', params=params) if response.status_code == 403: flash('This requires a valid API key.', 'danger') elif response.status_code == 404: flash('No file found with this hash.', 'danger') elif response.status_code == 200: f = File(filename='{}.bin'.format(hash), stream=StringIO(response.content)) except MissingConfiguration: flash("VirusTotal is not properly configured.", 'danger') else: flash( "There seems to be a problem with your installation (no 'virustotal' configuration)", 'danger') else: flash('You have to submit a file, a URL or a hash', 'danger') return f
def __init__(self, values): self['status'] = self.STATUS_PENDING self['executed_modules'] = [] self['pending_modules'] = [] self['waiting_modules'] = [] self['canceled_modules'] = [] self['preloading_modules'] = [] self['tags'] = [] self['iocs'] = [] self['results'] = {} self['generated_files'] = {} self['extracted_files'] = [] self['support_files'] = {} self['logs'] = [] self['extractions'] = [] self['probable_names'] = [] self['options'] = {} self['date'] = datetime.datetime.now() self['end_date'] = None self['groups'] = [] self['analyst'] = [] MongoDict.__init__(self, values) self._file = File(store.files.find_one({'_id': self['file']})) if '_id' not in self: self._init_threat_intelligence() # Sort preloading and processing modules if self['modules']: processing = [] for module_name in self['modules']: module = dispatcher.get_module(module_name) if module is not None: if module.info['type'] == "Preloading": self['preloading_modules'].append(module_name) else: processing.append(module_name) self['modules'] = processing self.save() if self['modules']: self.queue_modules(self['modules']) self._automatic() self.resume()
def _store_preloaded_file(self, filepath=None, fd=None): if not filepath and not fd: raise ValueError( "Please provide either the path to the file or a file-like " "object containing the data.") if filepath and fd: self.log( "debug", "Please provide either the path to the file or a " "file-like object containing the data, not both. " "Chosing the file-like object for now.") response = send_file_to_remote(fd, '/files/') else: response = send_file_to_remote(filepath, '/files/') return File(json_util.loads(response.text)['file'])
def submit_to_av(self, id, module): """Submit a file to an Antivirus module. .. :quickref: File; Submit file to an antivirus module If succesful, the response will be ``"ok"``. Otherwise, it will be an error message. :param id: id of the file to submit. :param module: name of the module to submit the file to. """ f = File(get_or_404(current_user.files, _id=id)) for av_module in dispatcher.get_antivirus_modules(): if av_module.name == module: av_module.submit(f['filepath']) f.update_value(['antivirus', module], True) break else: return make_response("antivirus module '{}' not present / enabled.".format(module)) return make_response("ok")
def each_with_type(self, target, file_type): self.joe = JoeSandbox(apikey=self.apikey, accept_tac=True) self.analysis_url = "https://jbxcloud.joesecurity.org/analysis/{}/0/html" self.results = dict() analysis = "" try: if file_type == 'url': analysis = self.joe.analysis_search(target) else: sha256 = "" basename = os.path.basename(target) with open(target, 'r+b') as f: filef = File(filename=basename, stream=f) sha256 = filef['sha256'] analysis = self.joe.analysis_search(sha256) if not self.force_submit and len(analysis): self.webid = analysis[0]['webid'] analysis_info = self.joe.analysis_info(self.webid) self.analysisid = analysis_info["analysisid"] else: data = self.submit_file(target, file_type) self.submission_id = data["submission_id"] # Wait for analysis to be over self.wait_for_analysis() # Add report URL to results self.results['URL'] = self.analysis_url.format(self.analysisid) # Get report, and extract IOCs self.process_report() # Get unpacked executables self.get_unpacked_executables() except (JoeException, Exception) as error: self.log("debug", "{}".format(error)) return True
def add_comment(self, id): if comments_enabled(): f = File(get_or_404(current_user.files, _id=id)) if current_user.has_permission("add_probable_name"): probable_name = request.form.get("probable_name") else: probable_name = None comment = request.form.get("comment") analysis_id = request.form.get("analysis") notify = request.form.get("notify") if comment: # If there is an analysis ID, make sure it is accessible if analysis_id: get_or_404(current_user.analyses, _id=analysis_id) f.add_comment(current_user["_id"], comment, analysis_id, probable_name, notify) else: flash("Comment should not be empty", "danger") return redirect(request.referrer)
def _get_file_from_filepath(self, filepath, fd): return File(filename=os.path.basename(filepath), stream=fd)
def post(self): """Create a new analysis. .. :quickref: Analysis; Create an analysis Launch a new analysis. You have to specify on which object this analysis will be made, by specifying one of: * ``file_id`` for an existing object * ``file`` for file uploads * ``url`` * ``hash`` if VirusTotal sample retrieval is enabled. You should also supply all enabled analysis options with the name ``options[OPTION_NAME]``. For boolean options, any value different than ``0`` or ``False`` means the option is enabled. If the submitted object already exists (and ``file_id`` was not specified), the response will be a file object. When a new analysis was successfuly created, the analysis object will be returned, in the ``analysis`` field. If there was error in your submission, they will be returned in the ``errors`` field. **Example request**:: headers = { 'Accept': "application/json", 'X-API-KEY': FAME_API_KEY } with open(filepath, 'rb') as f: params = { 'options[allow_internet_access]': "on", 'options[analysis_time]': "300", 'groups': "cert" } files = { 'file': f } r = requests.post(ENDPOINT, data=params, files=files, headers=headers) :form string file_id: (optional) the id of the object on which this analysis should run. :form file file: (optional) file to analyze. :form string url: (optional) url to analyze. :form string hash: (optional) hash to analyze. :form string module: (optional) the name of the target module. :form string groups: a comma-separated list of groups that will have access to this analysis. :form string comment: comment to add to this object. :form string option[*]: value of each enabled option. """ file_id = request.form.get('file_id') modules = filter(None, request.form.get('modules', '').split(',')) groups = request.form.get('groups', '').split(',') comment = request.form.get('comment', '') options = get_options() if options is None: return validation_error() valid_submission = self._validate_form(groups, modules, options) if not valid_submission: return validation_error() if file_id is not None: f = File(get_or_404(current_user.files, _id=file_id)) analysis = { 'analysis': f.analyze(groups, current_user['_id'], modules, options) } return redirect( analysis, url_for('AnalysesView:get', id=analysis['analysis']['_id'])) else: # When this is a new submission, validate the comment if not self._validate_comment(comment): return validation_error() f = self._get_object_to_analyze() if f is not None: f.add_owners(set(current_user['groups']) & set(groups)) if comment: f.add_comment(current_user['_id'], comment) if f.existing: f.add_groups(groups) flash( "File already exists, so the analysis was not launched." ) return redirect(clean_files(f), url_for('FilesView:get', id=f['_id'])) else: analysis = { 'analysis': clean_analyses( f.analyze(groups, current_user['_id'], modules, options)) } analysis['analysis']['file'] = clean_files(f) return redirect( analysis, url_for('AnalysesView:get', id=analysis['analysis']['_id'])) else: return render_template('analyses/new.html', options=dispatcher.options)
def _get_file_from_filepath(self, filepath, fd=None): response = send_file_to_remote(filepath, '/files/') return File(json_util.loads(response.text)['file'])
def post(self): file = request.files['file'] f = File(filename=secure_filename(file.filename), stream=file.stream) return render_json({'file': f})