Esempio n. 1
0
    def analyze(self, dataSource, fileManager, context):
        try:
            contact_and_message_dbs = AppSQLiteDB.findAppDatabases(
                dataSource, "naver_line", True, self._LINE_PACKAGE_NAME)
            calllog_dbs = AppSQLiteDB.findAppDatabases(dataSource,
                                                       "call_history", True,
                                                       self._LINE_PACKAGE_NAME)

            for contact_and_message_db in contact_and_message_dbs:
                current_case = Case.getCurrentCaseThrows()
                helper = CommunicationArtifactsHelper(
                    current_case.getSleuthkitCase(), self._PARSER_NAME,
                    contact_and_message_db.getDBFile(), Account.Type.LINE)
                self.parse_contacts(contact_and_message_db, helper)
                self.parse_messages(contact_and_message_db, helper)

            for calllog_db in calllog_dbs:
                current_case = Case.getCurrentCaseThrows()
                helper = CommunicationArtifactsHelper(
                    current_case.getSleuthkitCase(), self._PARSER_NAME,
                    calllog_db.getDBFile(), Account.Type.LINE)
                self.parse_calllogs(dataSource, calllog_db, helper)

        except NoCurrentCaseException as ex:
            # Error parsing Line databases.
            self._logger.log(Level.WARNING,
                             "Error parsing the Line App Databases", ex)
            self._logger.log(Level.WARNING, traceback.format_exc())

        for contact_and_message_db in contact_and_message_dbs:
            contact_and_message_db.close()

        for calllog_db in calllog_dbs:
            calllog_db.close()
Esempio n. 2
0
    def process(self, data_source, progress_bar):
        """Where the analysis is done

        Args:
            data_source (Content): autopsy case data source
            progressBar (DataSourceIngestModuleProgress): progress bar related to this analysis
        """

        progress_bar.switchToIndeterminate()
        self.log(Level.INFO, "GBoard Data Source Ingest Module is analysing...")

        try:
            current_case = Case.getCurrentCaseThrows()
            services = current_case.getServices()

            blackboard = services.getBlackboard()
            file_manager = services.getFileManager()

            input_dir = self.get_input_dir(data_source, file_manager)
            # Run GBoard analysis tool
            analysis_output = self.run_analyzer(input_dir)
            # Report analysis to Autopsy Blackboard
            self.report_analysis(input_dir, data_source, blackboard, file_manager, analysis_output)
            # Report clipboard analysis to Autopsy Blackboard
            # TODO: This should be inside the tool aswell
            self.analyze_clipboard(blackboard, data_source, file_manager)

            return IngestModule.ProcessResult.OK

        except NoCurrentCaseException as ex:
            self.log(Level.WARNING, "No case currently open. " + ex.toString())
Esempio n. 3
0
    def generateReport(self, baseReportDir, progressBar):

        module_path = os.path.dirname(os.path.abspath(__file__))
        exe_ext = '.exe' if os.name == 'nt' else ''
        self.path_to_exe = os.path.join(module_path, 'gboard-forensics' + exe_ext)

        self.log(Level.INFO, "Running reporter for " + baseReportDir.getReportDirectoryPath() + " folder")
        self.log(Level.INFO, "Relative file path: " + self.getRelativeFilePath())

        # Issue: https://sleuthkit.discourse.group/t/error-generting-reports-in-python/2297
        output_file = os.path.join(baseReportDir.getReportDirectoryPath(), self.getRelativeFilePath())
        progressBar.setIndeterminate(True)
        progressBar.start()

        try:
            current_case = Case.getCurrentCaseThrows()
            services = current_case.getServices()

            file_manager = services.getFileManager()

            input_dir = self.get_input_dir(file_manager)
            # Run GBoard analysis tool
            report_output = self.run_reporter(input_dir)

            report = open(output_file, 'w')
            report.write(report_output)
            report.close()

            current_case.addReport(output_file, self.moduleName, "HTML Report")
            progressBar.complete(ReportStatus.COMPLETE)

        except NoCurrentCaseException as ex:
            self.log(Level.WARNING, "No case currently open. " + ex.toString())
            progressBar.complete(ReportStatus.ERROR)
Esempio n. 4
0
    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
                        
                        if (historyResultSet.getInt("history_type") == 1):
                            direction = CommunicationDirection.INCOMING
                            fromId = historyResultSet.getString("device_id")
                        else:
                            direction = CommunicationDirection.OUTGOING
                            toId = historyResultSet.getString("device_id")
                            
                        msgBody = ""    # there is no body.
                        attachments = [historyResultSet.getString("file_path")]
                        msgBody = general.appendAttachmentList(msgBody, attachments)
                        
                        timeStamp = historyResultSet.getLong("timestamp") / 1000
                        messageArtifact = historyDbHelper.addMessage(
                                                            self._MESSAGE_TYPE,
                                                            direction,
                                                            fromId,
                                                            toId,
                                                            timeStamp,
                                                            MessageReadStatus.UNKNOWN,
                                                            None,   # subject
                                                            msgBody,
                                                            None )  # thread id
                                                                                                
                        # TBD: add the file as attachment ??

            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()
Esempio n. 5
0
    def analyze(self, dataSource, fileManager, context):
        """
            Extract, Transform and Load all messages, contacts and 
            calllogs from the TextNow databases.
        """

        textnow_dbs = AppSQLiteDB.findAppDatabases(dataSource, 
                    "textnow_data.db", True, self._TEXTNOW_PACKAGE_NAME)
        
        try:
            for textnow_db in textnow_dbs:
                current_case = Case.getCurrentCaseThrows()
                helper = CommunicationArtifactsHelper(
                            current_case.getSleuthkitCase(), self._PARSER_NAME, 
                            textnow_db.getDBFile(), Account.Type.TEXTNOW
                         ) 
                self.parse_contacts(textnow_db, helper) 
                self.parse_calllogs(textnow_db, helper)
                self.parse_messages(textnow_db, helper, current_case)
        except NoCurrentCaseException as ex:
            self._logger.log(Level.WARNING, "No case currently open.", ex)
            self._logger.log(Level.WARNING, traceback.format_exc())
        
        for textnow_db in textnow_dbs:
            textnow_db.close()
Esempio n. 6
0
    def analyze(self, dataSource, fileManager, context):
        try:
            self.current_case = Case.getCurrentCaseThrows()
        except NoCurrentCaseException as ex:
            self._logger.log(Level.WARNING, "No case currently open.", ex)
            self._logger.log(Level.WARNING, traceback.format_exc())
            return

        try:
            absFiles = fileManager.findFiles(dataSource,
                                             "da_destination_history")
            if absFiles.isEmpty():
                return
            for abstractFile in absFiles:
                try:
                    jFile = File(
                        self.current_case.getTempDirectory(),
                        str(abstractFile.getId()) + abstractFile.getName())
                    ContentUtils.writeToFile(
                        abstractFile, jFile,
                        context.dataSourceIngestIsCancelled)
                    self.__findGeoLocationsInDB(jFile.toString(), abstractFile)
                except Exception as ex:
                    self._logger.log(Level.SEVERE,
                                     "Error parsing Google map locations", ex)
                    self._logger.log(Level.SEVERE, traceback.format_exc())
        except TskCoreException as ex:
            # Error finding Google map locations.
            pass
Esempio n. 7
0
    def startUp(self, context):
        """Where module setup and configuration is done

        Args:
            context (IngestJobContext): Context of the ingest module
        """

        self.log(Level.INFO, "GBoard Data Source Ingest Module is starting up...")

        # setup the current context
        self.context = context

        # check if executable exists
        module_path = os.path.dirname(os.path.abspath(__file__))
        exe_ext = '.exe' if 'win' in System.getProperty("os.name").encode('ascii','ignore').lower() else ''
        self.path_to_exe = os.path.join(module_path, 'gboard-forensics' + exe_ext)

        if not os.path.exists(self.path_to_exe):
            raise IngestModuleException('Executable file not found!')

        try:
            current_case = Case.getCurrentCaseThrows()

            # create artifacts
            self.dictionary_art_type = self.createCustomArtifactType(current_case, self.GBOARD_DICTIONARY_ARTIFACT, 'Gboard Dictionary')
            self.tc_history_timeline_art_type = self.createCustomArtifactType(current_case, self.GBOARD_TC_HISTORY_TIMELINE_ARTIFACT, 'Gboard History Timeline')
            self.tc_raw_assembled_timeline_art_type = self.createCustomArtifactType(current_case, self.GBOARD_TC_RAW_ASSEMBLED_TIMELINE_ARTIFACT, 'Gboard Assembled Timeline')
            self.tc_processed_history_art_type = self.createCustomArtifactType(current_case, self.GBOARD_TC_PROCESSED_HISTORY_ARTIFACT, 'Gboard Processed History')
            self.emojis_art_type = self.createCustomArtifactType(current_case, self.GBOARD_EMOJIS_ARTIFACT, 'Gboard Expression History: Emojis')
            self.emoticons_art_type = self.createCustomArtifactType(current_case, self.GBOARD_EMOTICONS_ARTIFACT, 'Gboard Expression History: Emoticons')
            self.translate_art_type = self.createCustomArtifactType(current_case, self.GBOARD_TRANSLATE_ARTIFACT, 'Gboard Translate Cache')

            # emojis and emoticons attributes
            self.expression_shares_attr_type = self.createCustomAttributeType(current_case, self.GBOARD_EXPRESSION_SHARES_ATTRIBUTE, 'Shares')
            self.expression_emoji_attr_type = self.createCustomAttributeType(current_case, self.GBOARD_EXPRESSION_EMOJI_ATTRIBUTE, 'Emoji')
            self.expression_base_emoji_attr_type = self.createCustomAttributeType(current_case, self.GBOARD_EXPRESSION_BASE_EMOJI_ATTRIBUTE, 'Base Emoji')
            self.expression_emoticon_attr_type = self.createCustomAttributeType(current_case, self.GBOARD_EXPRESSION_EMOTICON_ATTRIBUTE, 'Emoticon')

            # training cache attributes
            self.tc_delete_flag_attr_type = self.createCustomAttributeType(current_case, self.GBOARD_TC_DELETE_FLAG_ATTRIBUTE, 'Deleted?')

            # clipboard attributes
            self.clipboard_attr_type = self.createCustomAttributeType(current_case, self.GBOARD_CLIPBOARD_ATTRIBUTE, 'Gboard Clipboard')
            self.clipboard_html_text_attr_type = self.createCustomAttributeType(current_case, self.GBOARD_CLIPBOARD_HTML_TEXT_ATTRIBUTE, 'HTML Text')

            # dictionary attributes
            self.dictionary_word_attr_type = self.createCustomAttributeType(current_case, self.GBOARD_DICTIONARY_WORD_ATTRIBUTE, 'Word')
            self.dictionary_shortcut_attr_type = self.createCustomAttributeType(current_case, self.GBOARD_DICTIONARY_SHORTCUT_ATTRIBUTE, 'Shortcut')
            self.dictionary_locale_attr_type = self.createCustomAttributeType(current_case, self.GBOARD_DICTIONARY_LOCALE_ATTRIBUTE, 'Locale')

            # translation cache attributes
            self.translate_original_attr_type = self.createCustomAttributeType(current_case, self.GBOARD_TRANSLATE_ORIGINAL_ATTRIBUTE, 'Original Text')
            self.translate_translated_attr_type = self.createCustomAttributeType(current_case, self.GBOARD_TRANSLATE_TRANSLATED_ATTRIBUTE, 'Translated Text')
            self.translate_from_attr_type = self.createCustomAttributeType(current_case, self.GBOARD_TRANSLATE_FROM_ATTRIBUTE, 'From Language')
            self.translate_to_attr_type = self.createCustomAttributeType(current_case, self.GBOARD_TRANSLATE_TO_ATTRIBUTE, 'To Language')
            self.translate_url_attr_type = self.createCustomAttributeType(current_case, self.GBOARD_TRANSLATE_URL_ATTRIBUTE, 'Request URL')

        except NoCurrentCaseException as ex:
            self.log(Level.WARNING, "No case currently open. " + ex)
Esempio n. 8
0
    def __findWWFMessagesInDB(self, wwfDb, dataSource):
        if not wwfDb:
            return

        current_case = Case.getCurrentCaseThrows()

        # Create a helper to parse the DB
        wwfDbHelper = CommunicationArtifactsHelper(
            current_case.getSleuthkitCase(), self._PARSER_NAME,
            wwfDb.getDBFile(), wwfAccountType)

        uuid = UUID.randomUUID().toString()

        resultSet = None
        try:
            resultSet = wwfDb.runQuery(
                "SELECT message, strftime('%s' ,created_at) as datetime, user_id, game_id FROM chat_messages ORDER BY game_id DESC, created_at DESC;"
            )

            while resultSet.next():
                message = resultSet.getString("message")  # WWF Message
                created_at = resultSet.getLong("datetime")
                user_id = resultSet.getString(
                    "user_id"
                )  # the ID of the user who sent/received the message.
                game_id = resultSet.getString(
                    "game_id"
                )  # ID of the game which the the message was sent.
                thread_id = "{0}-{1}".format(uuid, user_id)

                messageArtifact = wwfDbHelper.addMessage(
                    self._MESSAGE_TYPE,
                    CommunicationDirection.UNKNOWN,
                    user_id,  # fromId
                    None,  # toId
                    created_at,
                    MessageReadStatus.UNKNOWN,
                    "",  # subject
                    message,
                    thread_id)

        except SQLException as ex:
            self._logger.log(Level.WARNING,
                             "Error processing query result for WWF messages",
                             ex)
            self._logger.log(Level.WARNING, traceback.format_exc())
        except TskCoreException as ex:
            self._logger.log(Level.SEVERE,
                             "Failed to add WWF 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:
            wwfDb.close()
Esempio n. 9
0
    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()
Esempio n. 10
0
    def analyze(self, dataSource, fileManager, context):
        try:
            self.current_case = Case.getCurrentCaseThrows()
        except NoCurrentCaseException as ex:
            self._logger.log(Level.WARNING, "No case currently open.", ex)
            self._logger.log(Level.WARNING, traceback.format_exc())
            return

        self.analyzeContacts(dataSource, fileManager, context)
        self.analyzeMessagesAndCallLogs(dataSource, fileManager, context)
Esempio n. 11
0
    def __findTangoMessagesInDB(self, tangoDb, dataSource):
        if not tangoDb:
            return

        try:
            current_case = Case.getCurrentCaseThrows()

            # Create a helper to parse the DB
            tangoDbHelper = CommunicationArtifactsHelper(current_case.getSleuthkitCase(),
                                                    self._PARSER_NAME,
                                                    tangoDb.getDBFile(),
                                                    Account.Type.TANGO )  

            resultSet = tangoDb.runQuery(
                "SELECT conv_id, create_time, direction, payload FROM messages ORDER BY create_time DESC;")

            while resultSet.next():
                fromId = None
                toId = None
                conv_id = resultSet.getString("conv_id") # seems to wrap around the message found in payload after decoding from base-64
                create_time = Long.valueOf(resultSet.getString("create_time")) / 1000
                
                if resultSet.getString("direction") == "1": # 1 incoming, 2 outgoing
                    direction = CommunicationDirection.INCOMING
                else:
                    direction = CommunicationDirection.OUTGOING
                    
                payload = resultSet.getString("payload")
                msgBody = TangoMessageAnalyzer.decodeMessage(conv_id, payload)
                
                messageArtifact = tangoDbHelper.addMessage( 
                                                            self._MESSAGE_TYPE,
                                                            direction,
                                                            fromId,
                                                            toId,
                                                            create_time,
                                                            MessageReadStatus.UNKNOWN,
                                                            "",     # subject
                                                            msgBody,
                                                            "")

        except SQLException as ex:
            self._logger.log(Level.WARNING, "Error processing query result for Tango messages", ex)
            self._logger.log(Level.WARNING, traceback.format_exc())
        except TskCoreException as ex:
            self._logger.log(Level.SEVERE, "Failed to add Tango 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:
            tangoDb.close()
Esempio n. 12
0
    def analyze(self, dataSource, fileManager, context):
        oruxMapsTrackpointsDbs = AppSQLiteDB.findAppDatabases(
            dataSource, "oruxmapstracks.db", True, self._PACKAGE_NAME)
        for oruxMapsTrackpointsDb in oruxMapsTrackpointsDbs:
            try:
                current_case = Case.getCurrentCaseThrows()
                oruxDbHelper = ArtifactsHelper(
                    current_case.getSleuthkitCase(), self._MODULE_NAME,
                    oruxMapsTrackpointsDb.getDBFile())

                poiQueryString = "SELECT poilat, poilon, poitime, poiname FROM pois"
                poisResultSet = oruxMapsTrackpointsDb.runQuery(poiQueryString)
                if poisResultSet is not None:
                    while poisResultSet.next():
                        oruxDbHelper.addGPSLocation(
                            poisResultSet.getDouble("poilat"),
                            poisResultSet.getDouble("poilon"),
                            poisResultSet.getLong("poitime") /
                            1000,  # milliseconds since unix epoch
                            poisResultSet.getString("poiname"),
                            self._PROGRAM_NAME)

                trackpointsQueryString = "SELECT trkptlat, trkptlon, trkpttime FROM trackpoints"
                trackpointsResultSet = oruxMapsTrackpointsDb.runQuery(
                    trackpointsQueryString)
                if trackpointsResultSet is not None:
                    while trackpointsResultSet.next():
                        oruxDbHelper.addGPSLocation(
                            trackpointsResultSet.getDouble("trkptlat"),
                            trackpointsResultSet.getDouble("trkptlon"),
                            trackpointsResultSet.getLong("trkpttime") /
                            1000,  # milliseconds since unix epoch
                            "",
                            self._PROGRAM_NAME)
            except SQLException as ex:
                self._logger.log(
                    Level.WARNING,
                    "Error processing query result for Orux Map trackpoints.",
                    ex)
                self._logger.log(Level.WARNING, traceback.format_exc())
            except TskCoreException as ex:
                self._logger.log(
                    Level.SEVERE,
                    "Failed to add Orux Map trackpoint 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:
                oruxMapsTrackpointsDb.close()
Esempio n. 13
0
    def analyze(self, dataSource, fileManager, context):
        """
            Extract, Transform and Load all TSK contact, message
            and calllog artifacts from the WhatsApp databases.
        """

        try:
            contact_dbs = AppSQLiteDB.findAppDatabases(
                dataSource, "wa.db", True, self._WHATSAPP_PACKAGE_NAME)
            calllog_and_message_dbs = AppSQLiteDB.findAppDatabases(
                dataSource, "msgstore.db", True, self._WHATSAPP_PACKAGE_NAME)

            #Extract TSK_CONTACT information
            for contact_db in contact_dbs:
                current_case = Case.getCurrentCaseThrows()
                helper = CommunicationArtifactsHelper(
                    current_case.getSleuthkitCase(), self._PARSER_NAME,
                    contact_db.getDBFile(), Account.Type.WHATSAPP)
                self.parse_contacts(contact_db, helper)

            for calllog_and_message_db in calllog_and_message_dbs:
                current_case = Case.getCurrentCaseThrows()
                helper = CommunicationArtifactsHelper(
                    current_case.getSleuthkitCase(), self._PARSER_NAME,
                    calllog_and_message_db.getDBFile(), Account.Type.WHATSAPP)
                self.parse_calllogs(calllog_and_message_db, helper)
                self.parse_messages(dataSource, calllog_and_message_db, helper,
                                    current_case)

        except NoCurrentCaseException as ex:
            #If there is no current case, bail out immediately.
            self._logger.log(Level.WARNING, "No case currently open.", ex)
            self._logger.log(Level.WARNING, traceback.format_exec())

        #Clean up open file handles.
        for contact_db in contact_dbs:
            contact_db.close()

        for calllog_and_message_db in calllog_and_message_dbs:
            calllog_and_message_db.close()
Esempio n. 14
0
    def analyze(self, dataSource, fileManager, context):
        """
            Extract, Transform and Load all messages, contacts and 
            calllogs from the Viber databases.
        """

        try:
            contact_and_calllog_dbs = AppSQLiteDB.findAppDatabases(
                dataSource, "viber_data", True, self._VIBER_PACKAGE_NAME)
            message_dbs = AppSQLiteDB.findAppDatabases(
                dataSource, "viber_messages", True, self._VIBER_PACKAGE_NAME)

            #Extract TSK_CONTACT and TSK_CALLLOG information
            for contact_and_calllog_db in contact_and_calllog_dbs:
                current_case = Case.getCurrentCaseThrows()
                helper = CommunicationArtifactsHelper(
                    current_case.getSleuthkitCase(), self._PARSER_NAME,
                    contact_and_calllog_db.getDBFile(), Account.Type.VIBER)
                self.parse_contacts(contact_and_calllog_db, helper)
                self.parse_calllogs(contact_and_calllog_db, helper)

            #Extract TSK_MESSAGE information
            for message_db in message_dbs:
                current_case = Case.getCurrentCaseThrows()
                helper = CommunicationArtifactsHelper(
                    current_case.getSleuthkitCase(), self._PARSER_NAME,
                    message_db.getDBFile(), Account.Type.VIBER)
                self.parse_messages(message_db, helper, current_case)

        except NoCurrentCaseException as ex:
            self._logger.log(Level.WARNING, "No case currently open.", ex)
            self._logger.log(Level.WARNING, traceback.format_exc())

        for message_db in message_dbs:
            message_db.close()

        for contact_and_calllog_db in contact_and_calllog_dbs:
            contact_and_calllog_db.close()
Esempio n. 15
0
    def analyze(self, dataSource, fileManager, context):
        ## open current case
        try:
            self.current_case = Case.getCurrentCaseThrows()
        except NoCurrentCaseException as ex:
            self._logger.log(Level.WARNING, "No case currently open.", ex)
            self._logger.log(Level.WARNING, traceback.format_exc())
            return

        self.analyzeBookmarks(dataSource, fileManager, context)
        self.analyzeCookies(dataSource, fileManager, context)
        self.analyzeHistory(dataSource, fileManager, context)
        self.analyzeDownloads(dataSource, fileManager, context)
        self.analyzeAutofill(dataSource, fileManager, context)
        self.analyzeWebFormAddress(dataSource, fileManager, context)
Esempio n. 16
0
    def analyze(self, dataSource, fileManager, context):
        #Skype databases are of the form: live:XYZ.db, where
        #XYZ is the skype id of the user. The following search
        #does a generic substring match for 'live' in the skype
        #package.
        skype_dbs = AppSQLiteDB.findAppDatabases(dataSource, "live:", False,
                                                 self._SKYPE_PACKAGE_NAME)
        try:
            for skype_db in skype_dbs:
                #Attempt to get the user account id from the database
                user_account_instance = None
                try:
                    user_account_instance = self.get_user_account(skype_db)
                except SQLException as ex:
                    self._logger.log(
                        Level.WARNING,
                        "Error querying for the user account in the Skype db.",
                        ex)
                    self._logger.log(Level.WARNING, traceback.format_exc())

                current_case = Case.getCurrentCaseThrows()

                if user_account_instance is None:
                    helper = CommunicationArtifactsHelper(
                        current_case.getSleuthkitCase(), self._PARSER_NAME,
                        skype_db.getDBFile(), Account.Type.SKYPE)
                else:
                    helper = CommunicationArtifactsHelper(
                        current_case.getSleuthkitCase(), self._PARSER_NAME,
                        skype_db.getDBFile(), Account.Type.SKYPE,
                        Account.Type.SKYPE, user_account_instance)
                self.parse_contacts(skype_db, helper)
                self.parse_calllogs(skype_db, helper)
                self.parse_messages(skype_db, helper)
        except NoCurrentCaseException as ex:
            self._logger.log(Level.WARNING, "No case currently open.", ex)
            self._logger.log(Level.WARNING, traceback.format_exc())

        for skype_db in skype_dbs:
            skype_db.close()
Esempio n. 17
0
    def analyze(self, dataSource, fileManager, context):
        libraryDbs = AppSQLiteDB.findAppDatabases(dataSource, "library.db",
                                                  True, self._PACKAGE_NAME)
        for libraryDb in libraryDbs:
            try:
                current_case = Case.getCurrentCaseThrows()
                libraryDbHelper = ArtifactsHelper(
                    current_case.getSleuthkitCase(), self._MODULE_NAME,
                    libraryDb.getDBFile())
                queryString = "SELECT doc_id, purchase_time FROM ownership"
                ownershipResultSet = libraryDb.runQuery(queryString)
                if ownershipResultSet is not None:
                    while ownershipResultSet.next():
                        purchase_time = ownershipResultSet.getLong(
                            "purchase_time") / 1000
                        libraryDbHelper.addInstalledProgram(
                            ownershipResultSet.getString("doc_id"),
                            purchase_time)

            except SQLException as ex:
                self._logger.log(
                    Level.WARNING,
                    "Error processing query result for installed applications. ",
                    ex)
                self._logger.log(Level.WARNING, traceback.format_exc())
            except TskCoreException as ex:
                self._logger.log(
                    Level.SEVERE,
                    "Failed to adding installed application 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:
                libraryDb.close()
Esempio n. 18
0
    def analyze(self, dataSource, fileManager, context):
        oruxMapsTrackpointsDbs = AppSQLiteDB.findAppDatabases(
            dataSource, "oruxmapstracks.db", True, self._PACKAGE_NAME)
        for oruxMapsTrackpointsDb in oruxMapsTrackpointsDbs:
            try:
                current_case = Case.getCurrentCaseThrows()

                skCase = Case.getCurrentCase().getSleuthkitCase()
                geoArtifactHelper = GeoArtifactsHelper(
                    skCase, self._MODULE_NAME, self._PROGRAM_NAME,
                    oruxMapsTrackpointsDb.getDBFile())

                poiQueryString = "SELECT poilat, poilon, poialt, poitime, poiname FROM pois"
                poisResultSet = oruxMapsTrackpointsDb.runQuery(poiQueryString)
                abstractFile = oruxMapsTrackpointsDb.getDBFile()
                if poisResultSet is not None:
                    while poisResultSet.next():
                        latitude = poisResultSet.getDouble("poilat")
                        longitude = poisResultSet.getDouble("poilon")
                        time = poisResultSet.getLong(
                            "poitime") / 1000  # milliseconds since unix epoch
                        name = poisResultSet.getString("poiname")
                        altitude = poisResultSet.getDouble("poialt")

                        attributes = ArrayList()
                        artifact = abstractFile.newArtifact(
                            BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK)
                        attributes.add(
                            BlackboardAttribute(
                                BlackboardAttribute.ATTRIBUTE_TYPE.
                                TSK_DATETIME, self._MODULE_NAME, time))
                        attributes.add(
                            BlackboardAttribute(
                                BlackboardAttribute.ATTRIBUTE_TYPE.
                                TSK_GEO_LATITUDE, self._MODULE_NAME, latitude))
                        attributes.add(
                            BlackboardAttribute(
                                BlackboardAttribute.ATTRIBUTE_TYPE.
                                TSK_GEO_LONGITUDE, self._MODULE_NAME,
                                longitude))
                        attributes.add(
                            BlackboardAttribute(
                                BlackboardAttribute.ATTRIBUTE_TYPE.
                                TSK_GEO_ALTITUDE, self._MODULE_NAME, altitude))
                        attributes.add(
                            BlackboardAttribute(
                                BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME,
                                self._MODULE_NAME, name))
                        attributes.add(
                            BlackboardAttribute(
                                BlackboardAttribute.ATTRIBUTE_TYPE.
                                TSK_PROG_NAME, self._MODULE_NAME,
                                self._PROGRAM_NAME))

                        artifact.addAttributes(attributes)
                        try:
                            # index the artifact for keyword search
                            blackboard = Case.getCurrentCase(
                            ).getSleuthkitCase().getBlackboard()
                            blackboard.postArtifact(artifact,
                                                    self._MODULE_NAME)
                        except Blackboard.BlackboardException as ex:
                            self._logger.log(
                                Level.SEVERE,
                                "Unable to index blackboard artifact " +
                                str(artifact.getArtifactID()), ex)
                            self._logger.log(Level.SEVERE,
                                             traceback.format_exc())
                            MessageNotifyUtil.Notify.error(
                                "Failed to index trackpoint artifact for keyword search.",
                                artifact.getDisplayName())

                # tracks -> segments -> trackpoints
                #
                # The reason that the track and the segment are put into arrays is that once the segment query is run an error occurs that it cannot find the
                # trackname column in the track query.  This is avoided if all the tracks/segments are found and put into an array(s) that can then be processed all at once.
                trackQueryString = "SELECT _id, trackname, trackciudad FROM tracks"
                trackResultSet = oruxMapsTrackpointsDb.runQuery(
                    trackQueryString)
                if trackResultSet is not None:
                    trackResults = ArrayList()
                    while trackResultSet.next():
                        tempTrack = ArrayList()
                        trackName = trackResultSet.getString(
                            "trackname") + " - " + trackResultSet.getString(
                                "trackciudad")
                        trackId = str(trackResultSet.getInt("_id"))
                        tempTrack.append(trackId)
                        tempTrack.append(trackName)
                        trackResults.append(tempTrack)
                    for trackResult in trackResults:
                        trackId = trackResult[0]
                        trackName = trackResult[1]
                        segmentQueryString = "SELECT _id, segname FROM segments WHERE segtrack = " + trackId
                        segmentResultSet = oruxMapsTrackpointsDb.runQuery(
                            segmentQueryString)
                        if segmentResultSet is not None:
                            segmentResults = ArrayList()
                            while segmentResultSet.next():
                                segmentName = trackName + " - " + segmentResultSet.getString(
                                    "segname")
                                segmentId = str(segmentResultSet.getInt("_id"))
                                tempSegment = ArrayList()
                                tempSegment.append(segmentId)
                                tempSegment.append(segmentName)
                                segmentResults.append(tempSegment)
                            for segmentResult in segmentResults:
                                segmentId = segmentResult[0]
                                segmentName = segmentResult[1]
                                trackpointsQueryString = "SELECT trkptlat, trkptlon, trkptalt, trkpttime FROM trackpoints WHERE trkptseg = " + segmentId
                                trackpointsResultSet = oruxMapsTrackpointsDb.runQuery(
                                    trackpointsQueryString)
                                if trackpointsResultSet is not None:
                                    geoPointList = GeoTrackPoints()
                                    while trackpointsResultSet.next():
                                        latitude = trackpointsResultSet.getDouble(
                                            "trkptlat")
                                        longitude = trackpointsResultSet.getDouble(
                                            "trkptlon")
                                        altitude = trackpointsResultSet.getDouble(
                                            "trkptalt")
                                        time = trackpointsResultSet.getLong(
                                            "trkpttime"
                                        ) / 1000  # milliseconds since unix epoch

                                        geoPointList.addPoint(
                                            TrackPoint(latitude, longitude,
                                                       altitude, segmentName,
                                                       0, 0, 0, time))

                                    try:
                                        geoartifact = geoArtifactHelper.addTrack(
                                            segmentName, geoPointList, None)
                                    except Blackboard.BlackboardException as ex:
                                        self._logger.log(
                                            Level.SEVERE,
                                            "Error using geo artifact helper with blackboard",
                                            ex)
                                        self._logger.log(
                                            Level.SEVERE,
                                            traceback.format_exc())
                                        MessageNotifyUtil.Notify.error(
                                            "Failed to add track artifact.",
                                            "geoArtifactHelper")
                                    except TskCoreException as e:
                                        self._logger.log(
                                            Level.SEVERE,
                                            "Error using geo artifact helper with TskCoreException",
                                            ex)
                                        self._logger.log(
                                            Level.SEVERE,
                                            traceback.format_exc())
                                        MessageNotifyUtil.Notify.error(
                                            "Failed to add track artifact with TskCoreException.",
                                            "geoArtifactHelper")

            except SQLException as ex:
                self._logger.log(
                    Level.WARNING,
                    "Error processing query result for Orux Map trackpoints.",
                    ex)
                self._logger.log(Level.WARNING, traceback.format_exc())
            except TskCoreException as ex:
                self._logger.log(
                    Level.SEVERE,
                    "Failed to add Orux Map trackpoint 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:
                oruxMapsTrackpointsDb.close()
Esempio n. 19
0
    def __findContactsInDB(self, contactDb, dataSource):
        if not contactDb:
            return

        try:
            current_case = Case.getCurrentCaseThrows()

            # Create a helper to parse the DB
            contactDbHelper = CommunicationArtifactsHelper(current_case.getSleuthkitCase(),
                                                    self._PARSER_NAME,
                                                    contactDb.getDBFile(),
                                                    Account.Type.PHONE )
            
            # get display_name, mimetype(email or phone number) and data1 (phonenumber or email address depending on mimetype)
            # sorted by name, so phonenumber/email would be consecutive for a person if they exist.
            # check if contacts.name_raw_contact_id exists. Modify the query accordingly.
            columnFound = contactDb.columnExists("contacts", "name_raw_contact_id")
            if columnFound:
                resultSet = contactDb.runQuery(
                    "SELECT mimetype, data1, name_raw_contact.display_name AS display_name \n"
                    + "FROM raw_contacts JOIN contacts ON (raw_contacts.contact_id=contacts._id) \n"
                    + "JOIN raw_contacts AS name_raw_contact ON(name_raw_contact_id=name_raw_contact._id) "
                    + "LEFT OUTER JOIN data ON (data.raw_contact_id=raw_contacts._id) \n"
                    + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id=mimetypes._id) \n"
                    + "WHERE mimetype = 'vnd.android.cursor.item/phone_v2' OR mimetype = 'vnd.android.cursor.item/email_v2'\n"
                    + "ORDER BY name_raw_contact.display_name ASC;")
            else:
                resultSet = contactDb.runQuery(
                    "SELECT mimetype, data1, raw_contacts.display_name AS display_name \n"
                    + "FROM raw_contacts JOIN contacts ON (raw_contacts.contact_id=contacts._id) \n"
                    + "LEFT OUTER JOIN data ON (data.raw_contact_id=raw_contacts._id) \n"
                    + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id=mimetypes._id) \n"
                    + "WHERE mimetype = 'vnd.android.cursor.item/phone_v2' OR mimetype = 'vnd.android.cursor.item/email_v2'\n"
                    + "ORDER BY raw_contacts.display_name ASC;")

            contactArtifact = None
            oldName = None
            phoneNumber = None
            emailAddr = None
            name = None              
            while resultSet.next():
                name = resultSet.getString("display_name")
                data1 = resultSet.getString("data1") # the phone number or email
                mimetype = resultSet.getString("mimetype") # either phone or email
                if oldName and (name != oldName):
                    if phoneNumber or emailAddr:
                        contactArtifact = contactDbHelper.addContact(oldName,
                                                            phoneNumber,    # phoneNumber,
                                                            None,           # homePhoneNumber,
                                                            None,           # mobilePhoneNumber,
                                                            emailAddr)      # emailAddr

                        oldName = name
                        phoneNumber = None
                        emailAddr = None
                        name = None

                if mimetype == "vnd.android.cursor.item/phone_v2":
                    phoneNumber = data1                                      
                else:
                    emailAddr = data1
                    
                if name:
                    oldName = name


            # create contact for last row
            if oldName and (phoneNumber or emailAddr):
                contactArtifact = contactDbHelper.addContact(oldName,
                            phoneNumber,    # phoneNumber,
                            None,           # homePhoneNumber,
                            None,           # mobilePhoneNumber,
                            emailAddr)      # emailAddr                                            
                                                                     
        except SQLException as ex:
                self._logger.log(Level.WARNING, "Error processing query result for Android messages.", ex)
                self._logger.log(Level.WARNING, traceback.format_exc())
        except TskCoreException as ex:
                self._logger.log(Level.SEVERE, "Failed to add Android 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:
            contactDb.close()
Esempio n. 20
0
    def analyze(self, dataSource, fileManager, context):
        selfAccountId = None
        messageDbs = AppSQLiteDB.findAppDatabases(dataSource, "mmssms.db",
                                                  True, self._PACKAGE_NAME)
        for messageDb in messageDbs:
            try:
                current_case = Case.getCurrentCaseThrows()
                if selfAccountId is not None:
                    messageDbHelper = CommunicationArtifactsHelper(
                        current_case.getSleuthkitCase(), self._PARSER_NAME,
                        messageDb.getDBFile(), Account.Type.PHONE,
                        Account.Type.IMO, selfAccountId)
                else:
                    messageDbHelper = CommunicationArtifactsHelper(
                        current_case.getSleuthkitCase(), self._PARSER_NAME,
                        messageDb.getDBFile(), Account.Type.PHONE)

                uuid = UUID.randomUUID().toString()
                messagesResultSet = messageDb.runQuery(
                    "SELECT address, date, read, type, subject, body, thread_id FROM sms;"
                )
                if messagesResultSet is not None:
                    while messagesResultSet.next():
                        direction = ""
                        address = None
                        fromId = None
                        toId = None

                        address = messagesResultSet.getString(
                            "address"
                        )  # may be phone number, or other addresses
                        timeStamp = Long.valueOf(
                            messagesResultSet.getString("date")) / 1000
                        read = messagesResultSet.getInt(
                            "read")  # may be unread = 0, read = 1
                        subject = messagesResultSet.getString(
                            "subject")  # message subject
                        msgBody = messagesResultSet.getString(
                            "body")  # message body
                        thread_id = "{0}-{1}".format(
                            uuid, messagesResultSet.getInt("thread_id"))
                        if messagesResultSet.getString("type") == "1":
                            direction = CommunicationDirection.INCOMING
                            fromId = address
                        else:
                            direction = CommunicationDirection.OUTGOING
                            toId = address

                        message_read = messagesResultSet.getInt(
                            "read")  # may be unread = 0, read = 1
                        if (message_read == 1):
                            msgReadStatus = MessageReadStatus.READ
                        elif (message_read == 0):
                            msgReadStatus = MessageReadStatus.UNREAD
                        else:
                            msgReadStatus = MessageReadStatus.UNKNOWN

                        ## add a message
                        if address is not None:
                            messageArtifact = messageDbHelper.addMessage(
                                self._MESSAGE_TYPE,
                                direction,
                                fromId,
                                toId,
                                timeStamp,
                                msgReadStatus,
                                subject,  # subject
                                msgBody,
                                thread_id)

            except SQLException as ex:
                self._logger.log(
                    Level.WARNING,
                    "Error processing query result for Android messages.", ex)
                self._logger.log(Level.WARNING, traceback.format_exc())
            except TskCoreException as ex:
                self._logger.log(Level.SEVERE,
                                 "Failed to add Android 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:
                messageDb.close()
Esempio n. 21
0
    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


                        messageArtifact = friendsDBHelper.addMessage( 
                                                            self._MESSAGE_TYPE,
                                                            direction,
                                                            fromId,
                                                            toId,
                                                            timeStamp,
                                                            msgReadStatus,
                                                            "",     # subject
                                                            messagesResultSet.getString("last_message"),
                                                            "")   # thread id
                                                                                                
                        # TBD: parse the imdata JSON structure to figure out if there is an attachment.
                        #      If one exists, add the attachment as a derived file and a child of the message artifact.

                    
            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()
Esempio n. 22
0
    def analyze(self, dataSource, fileManager, context):
        oruxMapsTrackpointsDbs = AppSQLiteDB.findAppDatabases(
            dataSource, "oruxmapstracks.db", True, self._PACKAGE_NAME)
        for oruxMapsTrackpointsDb in oruxMapsTrackpointsDbs:
            try:
                current_case = Case.getCurrentCaseThrows()

                poiQueryString = "SELECT poilat, poilon, poitime, poiname FROM pois"
                poisResultSet = oruxMapsTrackpointsDb.runQuery(poiQueryString)
                abstractFile = oruxMapsTrackpointsDb.getDBFile()
                if poisResultSet is not None:
                    while poisResultSet.next():
                        latitude = poisResultSet.getDouble("poilat")
                        longitude = poisResultSet.getDouble("poilon")
                        time = poisResultSet.getLong(
                            "poitime") / 1000  # milliseconds since unix epoch
                        name = poisResultSet.getString("poiname")

                        attributes = ArrayList()
                        artifact = abstractFile.newArtifact(
                            BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT
                        )
                        attributes.add(
                            BlackboardAttribute(
                                BlackboardAttribute.ATTRIBUTE_TYPE.
                                TSK_DATETIME, self._MODULE_NAME, time))
                        attributes.add(
                            BlackboardAttribute(
                                BlackboardAttribute.ATTRIBUTE_TYPE.
                                TSK_GEO_LATITUDE, self._MODULE_NAME, latitude))
                        attributes.add(
                            BlackboardAttribute(
                                BlackboardAttribute.ATTRIBUTE_TYPE.
                                TSK_GEO_LONGITUDE, self._MODULE_NAME,
                                longitude))
                        attributes.add(
                            BlackboardAttribute(
                                BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME,
                                self._MODULE_NAME, name))
                        attributes.add(
                            BlackboardAttribute(
                                BlackboardAttribute.ATTRIBUTE_TYPE.
                                TSK_PROG_NAME, self._MODULE_NAME,
                                self._PROGRAM_NAME))

                        artifact.addAttributes(attributes)
                        try:
                            # index the artifact for keyword search
                            blackboard = Case.getCurrentCase(
                            ).getSleuthkitCase().getBlackboard()
                            blackboard.postArtifact(artifact,
                                                    self._MODULE_NAME)
                        except Blackboard.BlackboardException as ex:
                            self._logger.log(
                                Level.SEVERE,
                                "Unable to index blackboard artifact " +
                                str(artifact.getArtifactID()), ex)
                            self._logger.log(Level.SEVERE,
                                             traceback.format_exc())
                            MessageNotifyUtil.Notify.error(
                                "Failed to index trackpoint artifact for keyword search.",
                                artifact.getDisplayName())

                trackpointsQueryString = "SELECT trkptlat, trkptlon, trkpttime FROM trackpoints"
                trackpointsResultSet = oruxMapsTrackpointsDb.runQuery(
                    trackpointsQueryString)
                if trackpointsResultSet is not None:
                    while trackpointsResultSet.next():
                        latitude = trackpointsResultSet.getDouble("trkptlat")
                        longitude = trackpointsResultSet.getDouble("trkptlon")
                        time = trackpointsResultSet.getLong(
                            "trkpttime"
                        ) / 1000  # milliseconds since unix epoch
                        name = ""

                        attributes = ArrayList()
                        artifact = abstractFile.newArtifact(
                            BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT
                        )
                        attributes.add(
                            BlackboardAttribute(
                                BlackboardAttribute.ATTRIBUTE_TYPE.
                                TSK_DATETIME, self._MODULE_NAME, time))
                        attributes.add(
                            BlackboardAttribute(
                                BlackboardAttribute.ATTRIBUTE_TYPE.
                                TSK_GEO_LATITUDE, self._MODULE_NAME, latitude))
                        attributes.add(
                            BlackboardAttribute(
                                BlackboardAttribute.ATTRIBUTE_TYPE.
                                TSK_GEO_LONGITUDE, self._MODULE_NAME,
                                longitude))
                        attributes.add(
                            BlackboardAttribute(
                                BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME,
                                self._MODULE_NAME, name))
                        attributes.add(
                            BlackboardAttribute(
                                BlackboardAttribute.ATTRIBUTE_TYPE.
                                TSK_PROG_NAME, self._MODULE_NAME,
                                self._PROGRAM_NAME))

                        artifact.addAttributes(attributes)
                        try:
                            # index the artifact for keyword search
                            blackboard = Case.getCurrentCase(
                            ).getSleuthkitCase().getBlackboard()
                            blackboard.postArtifact(artifact,
                                                    self._MODULE_NAME)
                        except Blackboard.BlackboardException as ex:
                            self._logger.log(
                                Level.SEVERE,
                                "Unable to index blackboard artifact " +
                                str(artifact.getArtifactID()), ex)
                            self._logger.log(Level.SEVERE,
                                             traceback.format_exc())
                            MessageNotifyUtil.Notify.error(
                                "Failed to index trackpoint artifact for keyword search.",
                                artifact.getDisplayName())

            except SQLException as ex:
                self._logger.log(
                    Level.WARNING,
                    "Error processing query result for Orux Map trackpoints.",
                    ex)
                self._logger.log(Level.WARNING, traceback.format_exc())
            except TskCoreException as ex:
                self._logger.log(
                    Level.SEVERE,
                    "Failed to add Orux Map trackpoint 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:
                oruxMapsTrackpointsDb.close()
Esempio n. 23
0
    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())
Esempio n. 24
0
    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, f_create_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
                    
                        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")                          

                        msgBody = ""    # there is no body.
                        attachments = [messagesResultSet.getString("f_path")]
                        msgBody = general.appendAttachmentList(msgBody, attachments)
                        
                        timeStamp = messagesResultSet.getLong("f_create_time") / 1000
                        messageArtifact = transactionDbHelper.addMessage( 
                                                            self._MESSAGE_TYPE,
                                                            direction,
                                                            fromId,
                                                            toId,
                                                            timeStamp,
                                                            MessageReadStatus.UNKNOWN,
                                                            None,   # subject
                                                            msgBody,
                                                            messagesResultSet.getString("c_session_id") )
                                                                                                
                        # TBD: add the file as attachment ??

            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()
Esempio n. 25
0
    def analyze(self, dataSource, fileManager, context):
        for _dbFileName in CallLogAnalyzer._dbFileNames:
            selfAccountId = None
            callLogDbs = AppSQLiteDB.findAppDatabases(dataSource, _dbFileName,
                                                      True, self._PACKAGE_NAME)
            for callLogDb in callLogDbs:
                try:
                    current_case = Case.getCurrentCaseThrows()
                    if selfAccountId is not None:
                        callLogDbHelper = CommunicationArtifactsHelper(
                            current_case.getSleuthkitCase(), self._PARSER_NAME,
                            callLogDb.getDBFile(), Account.Type.PHONE,
                            Account.Type.PHONE, selfAccountId)
                    else:
                        callLogDbHelper = CommunicationArtifactsHelper(
                            current_case.getSleuthkitCase(), self._PARSER_NAME,
                            callLogDb.getDBFile(), Account.Type.PHONE)

                    for tableName in CallLogAnalyzer._tableNames:
                        try:
                            tableFound = callLogDb.tableExists(tableName)
                            if tableFound:
                                resultSet = callLogDb.runQuery(
                                    "SELECT number, date, duration, type, name FROM "
                                    + tableName + " ORDER BY date DESC;")
                                self._logger.log(
                                    Level.INFO,
                                    "Reading call log from table {0} in db {1}",
                                    [
                                        tableName,
                                        callLogDb.getDBFile().getName()
                                    ])
                                if resultSet is not None:
                                    while resultSet.next():
                                        direction = ""
                                        callerId = None
                                        calleeId = None

                                        timeStamp = resultSet.getLong(
                                            "date") / 1000

                                        number = resultSet.getString("number")
                                        duration = resultSet.getLong(
                                            "duration"
                                        )  # duration of call is in seconds
                                        name = resultSet.getString(
                                            "name"
                                        )  # name of person dialed or called. None if unregistered

                                        calltype = resultSet.getInt("type")
                                        if calltype == 1 or calltype == 3:
                                            direction = CommunicationDirection.INCOMING
                                            callerId = number
                                        elif calltype == 2 or calltype == 5:
                                            direction = CommunicationDirection.OUTGOING
                                            calleeId = number
                                        else:
                                            direction = CommunicationDirection.UNKNOWN

                                        ## add a call log
                                        if callerId is not None or calleeId is not None:
                                            callLogArtifact = callLogDbHelper.addCalllog(
                                                direction,
                                                callerId,
                                                calleeId,
                                                timeStamp,  ## start time
                                                timeStamp +
                                                duration * 1000,  ## end time
                                                CallMediaType.AUDIO)

                        except SQLException as ex:
                            self._logger.log(
                                Level.WARNING,
                                "Error processing query result for Android messages.",
                                ex)
                            self._logger.log(Level.WARNING,
                                             traceback.format_exc())
                        except TskCoreException as ex:
                            self._logger.log(
                                Level.SEVERE,
                                "Failed to add Android call log 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 TskCoreException as ex:
                    self._logger.log(
                        Level.SEVERE,
                        "Failed to create CommunicationArtifactsHelper.", ex)
                    self._logger.log(Level.SEVERE, 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:
                    callLogDb.close()