def _QueryHash(self, digest): """Queries the Viper Server for a specfic hash. Args: digest (str): hash to look up. Returns: dict[str, object]: JSON response or None on error. """ if not self._url: self._url = '{0:s}://{1:s}:{2:d}/file/find'.format( self._protocol, self._host, self._port) request_data = {self.lookup_hash: digest} try: json_response = self.MakeRequestAndDecodeJSON(self._url, 'POST', data=request_data) except errors.ConnectionError as exception: json_response = None logger.error( 'Unable to query Viper with error: {0!s}.'.format(exception)) return json_response
def _QueryHash(self, nsrl_socket, digest): """Queries nsrlsvr for a specific hash. Args: nsrl_socket (socket._socketobject): socket of connection to nsrlsvr. digest (str): hash to look up. Returns: bool: True if the hash was found, False if not or None on error. """ try: query = 'QUERY {0:s}\n'.format(digest).encode('ascii') except UnicodeDecodeError: logger.error( 'Unable to encode digest: {0!s} to ASCII.'.format(digest)) return False response = None try: nsrl_socket.sendall(query) response = nsrl_socket.recv(self._RECEIVE_BUFFER_SIZE) except socket.error as exception: logger.error( 'Unable to query nsrlsvr with error: {0!s}.'.format(exception)) if not response: return False # Strip end-of-line characters since they can differ per platform on which # nsrlsvr is running. response = response.strip() # nsrlsvr returns "OK 1" if the has was found or "OK 0" if not. return response == b'OK 1'
def _QueryHash(self, nsrl_socket, digest): """Queries nsrlsvr for a specific hash. Args: nsrl_socket (socket._socketobject): socket of connection to nsrlsvr. digest (str): hash to look up. Returns: bool: True if the hash was found, False if not or None on error. """ try: query = 'QUERY {0:s}\n'.format(digest).encode('ascii') except UnicodeDecodeError: logger.error('Unable to encode digest: {0!s} to ASCII.'.format(digest)) return False response = None try: nsrl_socket.sendall(query) response = nsrl_socket.recv(self._RECEIVE_BUFFER_SIZE) except socket.error as exception: logger.error('Unable to query nsrlsvr with error: {0!s}.'.format( exception)) if not response: return False # Strip end-of-line characters since they can differ per platform on which # nsrlsvr is running. response = response.strip() # nsrlsvr returns "OK 1" if the has was found or "OK 0" if not. return response == b'OK 1'
def _GenerateLabels(self, hash_information): """Generates a list of strings that will be used in the event tag. Args: hash_information (dict[str, object]): the JSON decoded contents of the result of a VirusTotal lookup, as produced by the VirusTotalAnalyzer. Returns: list[str]: strings describing the results from VirusTotal. """ response_code = hash_information['response_code'] if response_code == self._VIRUSTOTAL_NOT_PRESENT_RESPONSE_CODE: return ['virustotal_not_present'] if response_code == self._VIRUSTOTAL_PRESENT_RESPONSE_CODE: positives = hash_information['positives'] if positives > 0: return ['virustotal_detections_{0:d}'.format(positives)] return ['virsutotal_no_detections'] if response_code == self._VIRUSTOTAL_ANALYSIS_PENDING_RESPONSE_CODE: return ['virustotal_analysis_pending'] logger.error('VirusTotal returned unknown response code {0!s}'.format( response_code)) return ['virustotal_unknown_response_code_{0:d}'.format(response_code)]
def GenerateLabels(self, hash_information): """Generates a list of strings that will be used in the event tag. Args: hash_information (dict[str, object]): the JSON decoded contents of the result of a VirusTotal lookup, as produced by the VirusTotalAnalyzer. Returns: list[str]: strings describing the results from VirusTotal. """ response_code = hash_information['response_code'] if response_code == self._VIRUSTOTAL_NOT_PRESENT_RESPONSE_CODE: return ['virustotal_not_present'] if response_code == self._VIRUSTOTAL_PRESENT_RESPONSE_CODE: positives = hash_information['positives'] if positives > 0: return ['virustotal_detections_{0:d}'.format(positives)] return ['virsutotal_no_detections'] if response_code == self._VIRUSTOTAL_ANALYSIS_PENDING_RESPONSE_CODE: return ['virustotal_analysis_pending'] logger.error( 'VirusTotal returned unknown response code {0!s}'.format( response_code)) return ['virustotal_unknown_response_code_{0:d}'.format(response_code)]
def _QueryHash(self, digest): """Queries the Viper Server for a specfic hash. Args: digest (str): hash to look up. Returns: dict[str, object]: JSON response or None on error. """ if not self._url: self._url = '{0:s}://{1:s}:{2:d}/file/find'.format( self._protocol, self._host, self._port) request_data = {self.lookup_hash: digest} try: json_response = self.MakeRequestAndDecodeJSON( self._url, 'POST', data=request_data) except errors.ConnectionError as exception: json_response = None logger.error('Unable to query Viper with error: {0!s}.'.format( exception)) return json_response
def _HandleHashAnalysis(self, mediator, hash_analysis): """Deals with the results of the analysis of a hash. This method ensures that labels are generated for the hash, then tags all events derived from files with that hash. Args: mediator (AnalysisMediator): mediates interactions between analysis plugins and other components, such as storage and dfVFS. hash_analysis (HashAnalysis): hash analysis plugin's results for a given hash. Returns: collections.Counter: number of events per label. """ events_per_labels_counter = collections.Counter() labels = self.GenerateLabels(hash_analysis.hash_information) try: data_stream_identifiers = self._data_streams_by_hash.pop( hash_analysis.subject_hash) except KeyError: data_stream_identifiers = [] logger.error( ('unable to retrieve data streams for digest hash: {0:s}' ).format(hash_analysis.subject_hash)) for data_stream_identifier in data_stream_identifiers: event_identifiers = self._event_identifiers_by_data_stream.pop( data_stream_identifier) # Do no bail out earlier to maintain the state of # self._data_streams_by_hash and self._event_identifiers_by_data_stream. if not labels: continue for event_identifier in event_identifiers: event_tag = events.EventTag() event_tag.SetEventIdentifier(event_identifier) try: event_tag.AddLabels(labels) except (TypeError, ValueError): error_label = 'error_{0:s}'.format(self.NAME) logger.error(( 'unable to add labels: {0!s} for digest hash: {1:s} defaulting ' 'to: {2:s}').format(labels, hash_analysis.subject_hash, error_label)) labels = [error_label] event_tag.AddLabels(labels) mediator.ProduceEventTag(event_tag) for label in labels: events_per_labels_counter[label] += 1 return events_per_labels_counter
def _GetSocket(self): """Establishes a connection to an nsrlsvr instance. Returns: socket._socketobject: socket connected to an nsrlsvr instance or None if a connection cannot be established. """ try: return socket.create_connection( (self._host, self._port), self._SOCKET_TIMEOUT) except socket.error as exception: logger.error( 'Unable to connect to nsrlsvr with error: {0!s}.'.format(exception))
def _GetSocket(self): """Establishes a connection to an nsrlsvr instance. Returns: socket._socketobject: socket connected to an nsrlsvr instance or None if a connection cannot be established. """ try: return socket.create_connection((self._host, self._port), self._SOCKET_TIMEOUT) except socket.error as exception: logger.error( 'Unable to connect to nsrlsvr with error: {0!s}.'.format( exception))
def _HandleHashAnalysis(self, hash_analysis): """Deals with the results of the analysis of a hash. This method ensures that labels are generated for the hash, then tags all events derived from files with that hash. Args: hash_analysis (HashAnalysis): hash analysis plugin's results for a given hash. Returns: tuple: containing: list[dfvfs.PathSpec]: path specifications that had the hash value looked up. list[str]: labels that corresponds to the hash value that was looked up. list[EventTag]: event tags for all events that were extracted from the path specifications. """ tags = [] labels = self.GenerateLabels(hash_analysis.hash_information) path_specifications = self._hash_path_specs.pop( hash_analysis.subject_hash) for path_specification in path_specifications: event_identifiers = self._event_identifiers_by_path_spec.pop( path_specification, []) if not labels: continue for event_identifier in event_identifiers: try: event_tag = events.EventTag() event_tag.SetEventIdentifier(event_identifier) event_tag.AddLabels(labels) tags.append(event_tag) except (TypeError, ValueError) as exception: logger.error( 'unable to add labels to event with error: {0!s}'. format(exception)) return path_specifications, labels, tags
def _QueryHashes(self, digests): """Queries VirusTotal for a specfic hashes. Args: digests (list[str]): hashes to look up. Returns: dict[str, object]: JSON response or None on error. """ url_parameters = {'apikey': self._api_key, 'resource': ', '.join(digests)} try: json_response = self.MakeRequestAndDecodeJSON( self._VIRUSTOTAL_API_REPORT_URL, 'GET', params=url_parameters) except errors.ConnectionError as exception: json_response = None logger.error('Unable to query VirusTotal with error: {0!s}.'.format( exception)) return json_response
def _QueryHashes(self, digests): """Queries VirusTotal for a specific hashes. Args: digests (list[str]): hashes to look up. Returns: dict[str, object]: JSON response or None on error. """ url_parameters = { 'apikey': self._api_key, 'resource': ', '.join(digests) } try: json_response = self.MakeRequestAndDecodeJSON( self._VIRUSTOTAL_API_REPORT_URL, 'GET', params=url_parameters) except errors.ConnectionError as exception: json_response = None logger.error( 'Unable to query VirusTotal with error: {0!s}.'.format( exception)) return json_response