def analyze(self, dataSource, fileManager, context): transferDbs = AppSQLiteDB.findAppDatabases(dataSource, "transfer20.db", True, self._PACKAGE_NAME) for transferDb in transferDbs: try: current_case = Case.getCurrentCaseThrows() # transferDbHelper = CommunicationArtifactsHelper(current_case.getSleuthkitCase(), self._MODULE_NAME, transferDb.getDBFile(), Account.Type.ZAPYA) queryString = "SELECT device, name, direction, createtime, path, title FROM transfer" transfersResultSet = transferDb.runQuery(queryString) if transfersResultSet is not None: while transfersResultSet.next(): direction = CommunicationDirection.UNKNOWN fromId = None toId = None fileAttachments = ArrayList() if (transfersResultSet.getInt("direction") == 1): direction = CommunicationDirection.OUTGOING toId = transfersResultSet.getString("device") else: direction = CommunicationDirection.INCOMING fromId = transfersResultSet.getString("device") timeStamp = transfersResultSet.getLong("createtime") / 1000 messageArtifact = transferDbHelper.addMessage( self._MESSAGE_TYPE, direction, fromId, toId, timeStamp, MessageReadStatus.UNKNOWN, None, # subject None, # message Text None ) # thread id # add the file as attachment fileAttachments.add(FileAttachment(current_case.getSleuthkitCase(), transferDb.getDBFile().getDataSource(), transfersResultSet.getString("path"))) messageAttachments = MessageAttachments(fileAttachments, []) transferDbHelper.addAttachments(messageArtifact, messageAttachments) except SQLException as ex: self._logger.log(Level.WARNING, "Error processing query result for transfer.", ex) self._logger.log(Level.WARNING, traceback.format_exc()) except TskCoreException as ex: self._logger.log(Level.SEVERE, "Failed to create Zapya message artifacts.", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) except BlackboardException as ex: self._logger.log(Level.WARNING, "Failed to post artifacts.", ex) self._logger.log(Level.WARNING, traceback.format_exc()) except NoCurrentCaseException as ex: self._logger.log(Level.WARNING, "No case currently open.", ex) self._logger.log(Level.WARNING, traceback.format_exc()) finally: transferDb.close()
def parse_messages(self, skype_db, helper, current_case): #Query for messages and iterate row by row adding #each message artifact try: messages_parser = SkypeMessagesParser(skype_db) while messages_parser.next(): message_artifact = helper.addMessage( messages_parser.get_message_type(), messages_parser.get_message_direction(), messages_parser.get_phone_number_from(), messages_parser.get_phone_number_to(), messages_parser.get_message_date_time(), messages_parser.get_message_read_status(), messages_parser.get_message_subject(), messages_parser.get_message_text(), messages_parser.get_thread_id()) if (messages_parser.get_file_attachment() is not None): file_attachments = ArrayList() file_attachments.add( FileAttachment(current_case.getSleuthkitCase(), skype_db.getDBFile().getDataSource(), messages_parser.get_file_attachment())) message_attachments = MessageAttachments( file_attachments, []) helper.addAttachments(message_artifact, message_attachments) messages_parser.close() except SQLException as ex: #Error parsing Skype db self._logger.log( Level.WARNING, "Error parsing Skype database for message artifacts.", ex) self._logger.log(Level.WARNING, traceback.format_exc()) except TskCoreException as ex: #Severe error trying to add to case database.. case is not complete. #These exceptions are thrown by the CommunicationArtifactsHelper. self._logger.log( Level.SEVERE, "Failed to add message artifacts to the case database.", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) except BlackboardException as ex: #Failed to post notification to blackboard self._logger.log( Level.WARNING, "Failed to post message artifact to the blackboard", ex) self._logger.log(Level.WARNING, traceback.format_exc())
def parse_messages(self, dataSource, messages_db, helper, current_case): try: messages_db.attachDatabase(dataSource, "wa.db", messages_db.getDBFile().getParentPath(), "wadb") messages_parser = WhatsAppMessagesParser(messages_db) while messages_parser.next(): message_artifact = helper.addMessage( messages_parser.get_message_type(), messages_parser.get_message_direction(), messages_parser.get_phone_number_from(), messages_parser.get_phone_number_to(), messages_parser.get_message_date_time(), messages_parser.get_message_read_status(), messages_parser.get_message_subject(), messages_parser.get_message_text(), messages_parser.get_thread_id()) # add attachments, if any if (messages_parser.get_url_attachment() is not None): url_attachments = ArrayList() url_attachments.add( URLAttachment(messages_parser.get_url_attachment())) message_attachments = MessageAttachments([], url_attachments) helper.addAttachments(message_artifact, message_attachments) messages_parser.close() except SQLException as ex: self._logger.log( Level.WARNING, "Error querying the whatsapp database for contacts.", ex) self._logger.log(Level.WARNING, traceback.format_exc()) except TskCoreException as ex: self._logger.log( Level.SEVERE, "Error adding whatsapp contact artifacts to the case database.", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) except BlackboardException as ex: self._logger.log( Level.WARNING, "Error posting contact artifact to the blackboard.", ex) self._logger.log(Level.WARNING, traceback.format_exc())
def parse_messages(self, messages_db, helper, current_case): try: messages_parser = LineMessagesParser(messages_db) while messages_parser.next(): message_artifact = helper.addMessage( messages_parser.get_message_type(), messages_parser.get_message_direction(), messages_parser.get_phone_number_from(), messages_parser.get_phone_number_to(), messages_parser.get_message_date_time(), messages_parser.get_message_read_status(), messages_parser.get_message_subject(), messages_parser.get_message_text(), messages_parser.get_thread_id()) if (messages_parser.get_file_attachment() is not None): file_attachments = ArrayList() file_attachments.add( FileAttachment(current_case.getSleuthkitCase(), messages_db.getDBFile().getDataSource(), messages_parser.get_file_attachment())) message_attachments = MessageAttachments( file_attachments, []) helper.addAttachments(message_artifact, message_attachments) messages_parser.close() except SQLException as ex: self._logger.log( Level.WARNING, "Error parsing the Line App Database for messages.", ex) self._logger.log(Level.WARNING, traceback.format_exc()) except TskCoreException as ex: #Error adding artifact to case database... case is not complete. self._logger.log( Level.SEVERE, "Error adding Line message artifacts to the case database.", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) except BlackboardException as ex: #Error posting notification to blackboard self._logger.log( Level.WARNING, "Error posting Line message artifacts to blackboard.", ex) self._logger.log(Level.WARNING, traceback.format_exc())
def _newArtifactTSKMessage(self, appDbHelper, message, participants, selfAccountId): threadId = message[0] dateString = message[1] senderId = message[2] messageText = message[4] previewURL = message[5] playableURL = message[6] formatString = "%Y-%m-%d %H:%M:%S" # We assume 'dateString' is in UTC/GMT dateTime = datetime.datetime.strptime(dateString, formatString) timeStruct = dateTime.timetuple() timestamp = int(calendar.timegm(timeStruct)) subject = "" messageType = "Messenger (Beta)" direction = self._deduceCommunicationDirection(senderId, selfAccountId) recipientIdsList = [ participantId for participantId in participants if participantId != senderId ] readStatus = MessageReadStatus.UNKNOWN artifact = appDbHelper.addMessage(messageType, direction, senderId, recipientIdsList, timestamp, readStatus, subject, messageText, threadId) fileAttachments = ArrayList() urlAttachments = ArrayList() if previewURL: urlAttachments.add(URLAttachment(previewURL)) if playableURL: urlAttachments.add(URLAttachment(playableURL)) messageAttachments = MessageAttachments(fileAttachments, urlAttachments) appDbHelper.addAttachments(artifact, messageAttachments) return artifact
def parse_messages(self, textnow_db, helper, current_case): #Query for messages and iterate row by row adding #each message artifact try: messages_parser = TextNowMessagesParser(textnow_db) while messages_parser.next(): message_artifact = helper.addMessage( messages_parser.get_message_type(), messages_parser.get_message_direction(), messages_parser.get_phone_number_from(), messages_parser.get_phone_number_to(), messages_parser.get_message_date_time(), messages_parser.get_message_read_status(), messages_parser.get_message_subject(), messages_parser.get_message_text(), messages_parser.get_thread_id() ) if (len(messages_parser.get_file_attachment()) > 0): file_attachments = ArrayList() self._logger.log(Level.INFO, "SHow Attachment ==> " + str(len(messages_parser.get_file_attachment())) + " <> " + str(messages_parser.get_file_attachment())) file_attachments.add(FileAttachment(current_case.getSleuthkitCase(), textnow_db.getDBFile().getDataSource(), messages_parser.get_file_attachment())) message_attachments = MessageAttachments(file_attachments, []) helper.addAttachments(message_artifact, message_attachments) messages_parser.close() except SQLException as ex: #Error parsing TextNow db self._logger.log(Level.WARNING, "Error parsing TextNow databases for messages.", ex) self._logger.log(Level.WARNING, traceback.format_exc()) except TskCoreException as ex: #Error adding artifacts to the case database.. case database is not complete. self._logger.log(Level.SEVERE, "Error adding TextNow messages artifacts to the case database", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) except BlackboardException as ex: #Error posting notification to blackboard... self._logger.log(Level.WARNING, "Error posting TextNow messages artifact to the blackboard", ex) self._logger.log(Level.WARNING, traceback.format_exc())
def analyze(self, dataSource, fileManager, context): historyDbs = AppSQLiteDB.findAppDatabases(dataSource, "history.db", True, self._PACKAGE_NAME) for historyDb in historyDbs: try: current_case = Case.getCurrentCaseThrows() historyDbHelper = CommunicationArtifactsHelper( current_case.getSleuthkitCase(), self._MODULE_NAME, historyDb.getDBFile(), Account.Type.SHAREIT) queryString = """ SELECT history_type, device_id, device_name, description, timestamp, file_path FROM history JOIN item where history.content_id = item.item_id """ historyResultSet = historyDb.runQuery(queryString) if historyResultSet is not None: while historyResultSet.next(): direction = "" fromId = None toId = None fileAttachments = ArrayList() if (historyResultSet.getInt("history_type") == 1): direction = CommunicationDirection.INCOMING fromId = historyResultSet.getString("device_id") else: direction = CommunicationDirection.OUTGOING toId = historyResultSet.getString("device_id") timeStamp = historyResultSet.getLong( "timestamp") / 1000 messageArtifact = historyDbHelper.addMessage( self._MESSAGE_TYPE, direction, fromId, toId, timeStamp, MessageReadStatus.UNKNOWN, None, # subject None, # message text None) # thread id # add the file as attachment fileAttachments.add( FileAttachment( current_case.getSleuthkitCase(), historyDb.getDBFile().getDataSource(), historyResultSet.getString("file_path"))) messageAttachments = MessageAttachments( fileAttachments, []) historyDbHelper.addAttachments(messageArtifact, messageAttachments) except SQLException as ex: self._logger.log( Level.WARNING, "Error processing query result for ShareIt history.", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) except TskCoreException as ex: self._logger.log( Level.SEVERE, "Failed to create ShareIt message artifacts.", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) except BlackboardException as ex: self._logger.log(Level.WARNING, "Failed to post artifacts.", ex) self._logger.log(Level.WARNING, traceback.format_exc()) except NoCurrentCaseException as ex: self._logger.log(Level.WARNING, "No case currently open.", ex) self._logger.log(Level.WARNING, traceback.format_exc()) finally: historyDb.close()
def analyzeMessages(self, threadsDb, threadsDBHelper): try: ## Messages are found in the messages table. ## This query filters messages by msg_type to only get actual user created conversation messages (msg_type 0). ## The participant ids can be found in the thread_participants table. ## Participant names are found in thread_users table. ## Joining these tables produces multiple rows per message, one row for each recipient. ## The result set is processed to collect the multiple recipients for a given message. sqlString = """ SELECT msg_id, text, sender, timestamp_ms, msg_type, messages.thread_key as thread_key, snippet, thread_participants.user_key as user_key, thread_users.name as name, attachments, pending_send_media_attachment FROM messages JOIN thread_participants ON messages.thread_key = thread_participants.thread_key JOIN thread_users ON thread_participants.user_key = thread_users.user_key WHERE msg_type = 0 ORDER BY msg_id """ messagesResultSet = threadsDb.runQuery(sqlString) if messagesResultSet is not None: oldMsgId = None direction = CommunicationDirection.UNKNOWN fromId = None recipientIdsList = None timeStamp = -1 msgText = "" threadId = "" messageAttachments = None currentCase = Case.getCurrentCaseThrows() while messagesResultSet.next(): msgId = messagesResultSet.getString("msg_id") # new msg begins when msgId changes if msgId != oldMsgId: # Create message artifact with collected attributes if oldMsgId is not None: messageArtifact = threadsDBHelper.addMessage( self._MESSAGE_TYPE, direction, fromId, recipientIdsList, timeStamp, MessageReadStatus.UNKNOWN, "", # subject msgText, threadId) if (messageAttachments is not None): threadsDBHelper.addAttachments( messageArtifact, messageAttachments) messageAttachments = None oldMsgId = msgId # New message - collect all attributes recipientIdsList = [] ## get sender id by parsing JSON in sender column fromId = self.getSenderIdFromJson( messagesResultSet.getString("sender")) direction = self.deduceDirectionFromSenderId(fromId) # Get recipient and add to list self.addRecipientToList( messagesResultSet.getString("user_key"), fromId, recipientIdsList) timeStamp = messagesResultSet.getLong( "timestamp_ms") / 1000 # Get msg text # Sometimes there may not be an explict msg text, # but an app generated snippet instead msgText = messagesResultSet.getString("text") if not msgText: msgText = messagesResultSet.getString("snippet") # Get attachments and pending attachments if they exist attachment = messagesResultSet.getString("attachments") pendingAttachment = messagesResultSet.getString( "pending_send_media_attachment") urlAttachments = ArrayList() fileAttachments = ArrayList() if ((attachment is not None) or (pendingAttachment is not None)): if (attachment is not None): attachmentDict = json.loads(attachment)[0] if (attachmentDict["mime_type"] == "image/jpeg" ): urls = attachmentDict.get("urls", None) if (urls is not None): urlAttachments = self.getJPGListFromJson( urls) elif (attachmentDict["mime_type"] == "video/mp4"): # filename does not have an associated path with it so it will be ignored urls = attachmentDict.get("urls", None) if (urls is not None): urlAttachments = self.getJPGListFromJson( urls) video_data_url = attachmentDict.get( "video_data_url", None) if (video_data_url is not None): urlAttachments.add( URLAttachment(video_data_url)) video_data_thumbnail_url = attachmentDict.get( "video_data_thumbnail_url", None) if (video_data_thumbnail_url is not None): urlAttachments.add( URLAttachment( video_data_thumbnail_url)) elif (attachmentDict["mime_type"] == "audio/mpeg"): audioUri = attachmentDict.get( "audio_uri", None) if (audioUri is None or audioUri == ""): continue else: fileAttachments.add( FileAttachment( currentCase.getSleuthkitCase(), threadsDb.getDBFile(). getDataSource(), audioUri.replace( "file://", ""))) else: self._logger.log( Level.INFO, "Attachment type not handled: " + attachmentDict["mime_type"]) if (pendingAttachment is not None): pendingAttachmentDict = json.loads( pendingAttachment)[0] pendingAttachmentUri = pendingAttachmentDict.get( "uri", None) if (pendingAttachmentUri is not None): fileAttachments.add( FileAttachment( currentCase.getSleuthkitCase(), threadsDb.getDBFile(). getDataSource(), pendingAttachmentUri.replace( "file://", ""))) messageAttachments = MessageAttachments( fileAttachments, urlAttachments) threadId = messagesResultSet.getString("thread_key") else: # same msgId as last, just collect recipient from current row self.addRecipientToList( messagesResultSet.getString("user_key"), fromId, recipientIdsList) # at the end of the loop, add last message messageArtifact = threadsDBHelper.addMessage( self._MESSAGE_TYPE, direction, fromId, recipientIdsList, timeStamp, MessageReadStatus.UNKNOWN, "", # subject msgText, threadId) except SQLException as ex: self._logger.log( Level.WARNING, "Error processing query result for FB Messenger messages.", ex) self._logger.log(Level.WARNING, traceback.format_exc()) except TskCoreException as ex: self._logger.log(Level.SEVERE, "Failed to add FB Messenger message artifacts.", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) except BlackboardException as ex: self._logger.log(Level.WARNING, "Failed to post artifacts.", ex) self._logger.log(Level.WARNING, traceback.format_exc())
def analyze(self, dataSource, fileManager, context): selfAccountId = None transactionDbs = AppSQLiteDB.findAppDatabases(dataSource, "trans-history-db", True, self._PACKAGE_NAME) for transactionDb in transactionDbs: try: current_case = Case.getCurrentCaseThrows() # get the profile with connection_times 0, that's the self account. profilesResultSet = transactionDb.runQuery( "SELECT device_id, nick_name FROM profile WHERE connect_times = 0" ) if profilesResultSet: while profilesResultSet.next(): if not selfAccountId: selfAccountId = profilesResultSet.getString( "device_id") # create artifacts helper if selfAccountId is not None: transactionDbHelper = CommunicationArtifactsHelper( current_case.getSleuthkitCase(), self._MODULE_NAME, transactionDb.getDBFile(), Account.Type.XENDER, Account.Type.XENDER, selfAccountId) else: transactionDbHelper = CommunicationArtifactsHelper( current_case.getSleuthkitCase(), self._MODULE_NAME, transactionDb.getDBFile(), Account.Type.XENDER) queryString = """ SELECT f_path, f_display_name, f_size_str, c_start_time, c_direction, c_session_id, s_name, s_device_id, r_name, r_device_id FROM new_history """ messagesResultSet = transactionDb.runQuery(queryString) if messagesResultSet is not None: while messagesResultSet.next(): direction = CommunicationDirection.UNKNOWN fromId = None toId = None fileAttachments = ArrayList() if (messagesResultSet.getInt("c_direction") == 1): direction = CommunicationDirection.OUTGOING toId = messagesResultSet.getString("r_device_id") else: direction = CommunicationDirection.INCOMING fromId = messagesResultSet.getString("s_device_id") timeStamp = messagesResultSet.getLong( "c_start_time") / 1000 messageArtifact = transactionDbHelper.addMessage( self._MESSAGE_TYPE, direction, fromId, toId, timeStamp, MessageReadStatus.UNKNOWN, None, # subject None, # message text messagesResultSet.getString("c_session_id")) # add the file as attachment fileAttachments.add( FileAttachment( current_case.getSleuthkitCase(), transactionDb.getDBFile().getDataSource(), messagesResultSet.getString("f_path"))) messageAttachments = MessageAttachments( fileAttachments, []) transactionDbHelper.addAttachments( messageArtifact, messageAttachments) except SQLException as ex: self._logger.log( Level.WARNING, "Error processing query result for profiles.", ex) self._logger.log(Level.WARNING, traceback.format_exc()) except TskCoreException as ex: self._logger.log(Level.SEVERE, "Failed to create Xender message artifacts.", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) except BlackboardException as ex: self._logger.log(Level.WARNING, "Failed to post artifacts.", ex) self._logger.log(Level.WARNING, traceback.format_exc()) except NoCurrentCaseException as ex: self._logger.log(Level.WARNING, "No case currently open.", ex) self._logger.log(Level.WARNING, traceback.format_exc()) finally: transactionDb.close()
def analyze(self, dataSource, fileManager, context): selfAccountId = None accountDbs = AppSQLiteDB.findAppDatabases(dataSource, "accountdb.db", True, self._PACKAGE_NAME) for accountDb in accountDbs: try: accountResultSet = accountDb.runQuery( "SELECT uid, name FROM account") if accountResultSet: # We can determine the IMO user ID of the device owner. # Therefore we can create and use a app account and use that # as a 'self' account instead of a Device account if not selfAccountId: selfAccountId = accountResultSet.getString("uid") except SQLException as ex: self._logger.log(Level.WARNING, "Error processing query result for account", ex) self._logger.log(Level.WARNING, traceback.format_exc()) finally: accountDb.close() friendsDbs = AppSQLiteDB.findAppDatabases(dataSource, "imofriends.db", True, self._PACKAGE_NAME) for friendsDb in friendsDbs: try: current_case = Case.getCurrentCaseThrows() if selfAccountId is not None: friendsDBHelper = CommunicationArtifactsHelper( current_case.getSleuthkitCase(), self._PARSER_NAME, friendsDb.getDBFile(), Account.Type.IMO, Account.Type.IMO, selfAccountId) else: friendsDBHelper = CommunicationArtifactsHelper( current_case.getSleuthkitCase(), self._PARSER_NAME, friendsDb.getDBFile(), Account.Type.IMO) contactsResultSet = friendsDb.runQuery( "SELECT buid, name FROM friends") if contactsResultSet is not None: while contactsResultSet.next(): contactId = contactsResultSet.getString("buid") ## add a TSK_ID attribute with contact's IMO Id additionalAttributes = ArrayList() additionalAttributes.add( BlackboardAttribute( BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ID, self._PARSER_NAME, contactId)) friendsDBHelper.addContact( contactsResultSet.getString( "name"), ## contact name "", ## phone "", ## home phone "", ## mobile "", ## email additionalAttributes) queryString = """ SELECT messages.buid AS buid, imdata, last_message, timestamp, message_type, message_read, name FROM messages INNER JOIN friends ON friends.buid = messages.buid """ messagesResultSet = friendsDb.runQuery(queryString) if messagesResultSet is not None: while messagesResultSet.next(): direction = "" fromId = None toId = None name = messagesResultSet.getString("name") uniqueId = messagesResultSet.getString("buid") if (messagesResultSet.getInt("message_type") == 1): direction = CommunicationDirection.INCOMING fromId = uniqueId else: direction = CommunicationDirection.OUTGOING toId = uniqueId message_read = messagesResultSet.getInt("message_read") if (message_read == 1): msgReadStatus = MessageReadStatus.READ elif (message_read == 0): msgReadStatus = MessageReadStatus.UNREAD else: msgReadStatus = MessageReadStatus.UNKNOWN timeStamp = messagesResultSet.getLong( "timestamp") / 1000000000 msgBody = messagesResultSet.getString("last_message") messageArtifact = friendsDBHelper.addMessage( self._MESSAGE_TYPE, direction, fromId, toId, timeStamp, msgReadStatus, "", # subject msgBody, "") # thread id # Parse the imdata JSON structure to check if there is an attachment. # If one exists, create an attachment and add to the message. fileAttachments = ArrayList() urlAttachments = ArrayList() imdataJsonStr = messagesResultSet.getString("imdata") if imdataJsonStr is not None: imdata_dict = json.loads(imdataJsonStr) # set to none if the key doesn't exist in the dict attachmentOriginalPath = imdata_dict.get( 'original_path', None) attachmentLocalPath = imdata_dict.get( 'local_path', None) if attachmentOriginalPath: attachmentPath = attachmentOriginalPath else: attachmentPath = attachmentLocalPath if attachmentPath: # Create a file attachment with given path fileAttachment = FileAttachment( current_case.getSleuthkitCase(), friendsDb.getDBFile().getDataSource(), attachmentPath) fileAttachments.add(fileAttachment) msgAttachments = MessageAttachments( fileAttachments, []) attachmentArtifact = friendsDBHelper.addAttachments( messageArtifact, msgAttachments) except SQLException as ex: self._logger.log( Level.WARNING, "Error processing query result for IMO friends", ex) self._logger.log(Level.WARNING, traceback.format_exc()) except TskCoreException as ex: self._logger.log(Level.SEVERE, "Failed to add IMO message artifacts.", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) except BlackboardException as ex: self._logger.log(Level.WARNING, "Failed to post artifacts.", ex) self._logger.log(Level.WARNING, traceback.format_exc()) except NoCurrentCaseException as ex: self._logger.log(Level.WARNING, "No case currently open.", ex) self._logger.log(Level.WARNING, traceback.format_exc()) finally: friendsDb.close()