diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties index 602dc5b0a07aa4352f7a1374e828a45a07495219..2388a93446f00eb24f2eb64064fd0dd6d16bfaee 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties @@ -15,6 +15,9 @@ Chrome.getCookie.errMsg.errGettingFiles=Error when trying to get Chrome history Chrome.getCookie.errMsg.errAnalyzeFile={0}: Error while trying to analyze file:{1} Chrome.getDownload.errMsg.errGettingFiles=Error when trying to get Chrome history files. Chrome.getDownload.errMsg.errAnalyzeFiles1={0}: Error while trying to analyze file:{1} +Chrome.getFavicon.errMsg.errGettingFiles=Error when trying to get Chrome favicon files. +Chrome.getFavicon.errMsg.errAnalyzeFiles1={0}: Error while trying to analyze file:{1} +Chrome.getFavicon.errMsg.errCreateArtifact=Error creating Favicon artifact Chrome.getLogin.errMsg.errGettingFiles=Error when trying to get Chrome history files. Chrome.getLogin.errMsg.errAnalyzingFiles={0}: Error while trying to analyze file:{1} Chrome.getAutofill.errMsg.errGettingFiles=Error when trying to get Chrome Web Data files. diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED index c73bf456d5b0d22afe493e3b1ebb70f39b322c03..00df8b89d8c1469eb34be911773066b410a76b0f 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED @@ -4,15 +4,10 @@ cannotParseXml=Unable to parse XML file: ChromeCacheExtract_adding_artifacts_msg=Chrome Cache: Adding %d artifacts for analysis. ChromeCacheExtract_adding_extracted_files_msg=Chrome Cache: Adding %d extracted files for analysis. ChromeCacheExtract_loading_files_msg=Chrome Cache: Loading files from %s. -# {0} - module name -# {1} - row number -# {2} - table length -# {3} - cache path ChromeCacheExtractor.progressMsg={0}: Extracting cache entry {1} of {2} entries from {3} DataSourceUsage_AndroidMedia=Android Media Card DataSourceUsage_DJU_Drone_DAT=DJI Internal SD Card DataSourceUsage_FlashDrive=Flash Drive -# {0} - OS name DataSourceUsageAnalyzer.customVolume.label=OS Drive ({0}) DataSourceUsageAnalyzer.displayName=Data Source Usage Analyzer DefaultPriorityDomainCategorizer_searchEngineCategory=Search Engine @@ -25,7 +20,7 @@ ExtractEdge_process_errMsg_errGettingWebCacheFiles=Error trying to retrieving Ed ExtractEdge_process_errMsg_spartanFail=Failure processing Microsoft Edge spartan.edb file ExtractEdge_process_errMsg_unableFindESEViewer=Unable to find ESEDatabaseViewer ExtractEdge_process_errMsg_webcacheFail=Failure processing Microsoft Edge WebCacheV01.dat file -# {0} - sub module name +ExtractFavicon_Display_Name=Favicon ExtractIE_executePasco_errMsg_errorRunningPasco={0}: Error analyzing Internet Explorer web history ExtractOs.androidOs.label=Android ExtractOs.androidVolume.label=OS Drive (Android) @@ -58,7 +53,6 @@ ExtractOs.windowsVolume.label=OS Drive (Windows) ExtractOs.yellowDogLinuxOs.label=Linux (Yellow Dog) ExtractOs.yellowDogLinuxVolume.label=OS Drive (Linux Yellow Dog) ExtractOS_progressMessage=Checking for OS -# {0} - sub module name ExtractPrefetch_errMsg_prefetchParsingFailed={0}: Error analyzing prefetch files ExtractPrefetch_module_name=Windows Prefetch Analyzer ExtractRecycleBin_module_name=Recycle Bin Analyzer @@ -105,6 +99,9 @@ Chrome.getCookie.errMsg.errGettingFiles=Error when trying to get Chrome history Chrome.getCookie.errMsg.errAnalyzeFile={0}: Error while trying to analyze file:{1} Chrome.getDownload.errMsg.errGettingFiles=Error when trying to get Chrome history files. Chrome.getDownload.errMsg.errAnalyzeFiles1={0}: Error while trying to analyze file:{1} +Chrome.getFavicon.errMsg.errGettingFiles=Error when trying to get Chrome favicon files. +Chrome.getFavicon.errMsg.errAnalyzeFiles1={0}: Error while trying to analyze file:{1} +Chrome.getFavicon.errMsg.errCreateArtifact=Error creating Favicon artifact Chrome.getLogin.errMsg.errGettingFiles=Error when trying to get Chrome history files. Chrome.getLogin.errMsg.errAnalyzingFiles={0}: Error while trying to analyze file:{1} Chrome.getAutofill.errMsg.errGettingFiles=Error when trying to get Chrome Web Data files. @@ -166,6 +163,7 @@ Progress_Message_Chrome_Cache=Chrome Cache Progress_Message_Chrome_Cookies=Chrome Cookies Browser {0} # {0} - browserName Progress_Message_Chrome_Downloads=Chrome Downloads Browser {0} +Progress_Message_Chrome_Favicons=Chrome Downloads Favicons {0} Progress_Message_Chrome_FormHistory=Chrome Form History # {0} - browserName Progress_Message_Chrome_History=Chrome History Browser {0} @@ -225,7 +223,6 @@ Recently_Used_Artifacts_Winrar=Recently opened according to WinRAR MRU Registry_System_Bam=Recently Executed according to Background Activity Moderator (BAM) RegRipperFullNotFound=Full version RegRipper executable not found. RegRipperNotFound=Autopsy RegRipper executable not found. -# {0} - file name SearchEngineURLQueryAnalyzer.init.exception.msg=Unable to find {0}. SearchEngineURLQueryAnalyzer.moduleName.text=Search Engine Query Analyzer SearchEngineURLQueryAnalyzer.engineName.none=NONE diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java index a77389137354fb390dec432417742e3ff7f6e79a..09d5725bfd674bddd0881111364501b433028e9e 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java @@ -86,15 +86,19 @@ class Chromium extends Extract { private static final String WEBFORM_ADDRESS_QUERY_V8X = "SELECT first_name, middle_name, last_name, full_name, street_address, city, state, zipcode, country_code, number, email, date_modified, use_date, use_count" + " FROM autofill_profiles, autofill_profile_names, autofill_profile_emails, autofill_profile_phones" + " WHERE autofill_profiles.guid = autofill_profile_names.guid AND autofill_profiles.guid = autofill_profile_emails.guid AND autofill_profiles.guid = autofill_profile_phones.guid"; + private static final String FAVICON_QUERY = "SELECT page_url, last_updated, last_requested FROM icon_mapping, favicon_bitmaps " + + " WHERE icon_mapping.icon_id = favicon_bitmaps.icon_id"; private static final String HISTORY_FILE_NAME = "History"; private static final String BOOKMARK_FILE_NAME = "Bookmarks"; private static final String COOKIE_FILE_NAME = "Cookies"; private static final String LOGIN_DATA_FILE_NAME = "Login Data"; private static final String WEB_DATA_FILE_NAME = "Web Data"; + private static final String FAVICON_DATA_FILE_NAME = "Favicons"; private static final String UC_BROWSER_NAME = "UC Browser"; private static final String ENCRYPTED_FIELD_MESSAGE = "The data was encrypted."; private static final String GOOGLE_PROFILE_NAME = "Profile"; private static final String GOOGLE_PROFILE = "Google Chrome "; + private static final String FAVICON_ARTIFACT_NAME = "TSK_FAVICON"; //NON-NLS private Boolean databaseEncrypted = false; private Boolean fieldEncrypted = false; @@ -123,6 +127,7 @@ class Chromium extends Extract { "Progress_Message_Chrome_Cookies=Chrome Cookies Browser {0}", "# {0} - browserName", "Progress_Message_Chrome_Downloads=Chrome Downloads Browser {0}", + "Progress_Message_Chrome_Favicons=Chrome Downloads Favicons {0}", "Progress_Message_Chrome_FormHistory=Chrome Form History", "# {0} - browserName", "Progress_Message_Chrome_AutoFill=Chrome Auto Fill Browser {0}", @@ -178,6 +183,12 @@ public void process(Content dataSource, DataSourceIngestModuleProgress progressB if (context.dataSourceIngestIsCancelled()) { return; } + + progressBar.progress(NbBundle.getMessage(this.getClass(), "Progress_Message_Chrome_Favicons", browserName)); + this.getFavicons(browser.getKey(), browser.getValue(), ingestJobId); + if (context.dataSourceIngestIsCancelled()) { + return; + } } progressBar.progress(Bundle.Progress_Message_Chrome_Cache()); @@ -669,6 +680,116 @@ private void getDownload(String browser, String browserLocation, long ingestJobI } } + /** + * Queries the Favicons table and adds artifacts + * + * @param browser + * @param browserLocation + * @param ingestJobId The ingest job id. + */ + private void getFavicons(String browser, String browserLocation, long ingestJobId) { + FileManager fileManager = currentCase.getServices().getFileManager(); + List<AbstractFile> faviconFiles; + String browserName = browser; + try { + faviconFiles = fileManager.findFiles(dataSource, FAVICON_DATA_FILE_NAME, browserLocation); //NON-NLS + } catch (TskCoreException ex) { + String msg = NbBundle.getMessage(this.getClass(), "Chrome.getFavicon.errMsg.errGettingFiles"); + logger.log(Level.SEVERE, msg, ex); + this.addErrorMessage(this.getDisplayName() + ": " + msg); + return; + } + + if (faviconFiles.isEmpty()) { + logger.log(Level.INFO, "Didn't find any Chrome favicon files."); //NON-NLS + return; + } + + dataFound = true; + Collection<BlackboardArtifact> bbartifacts = new ArrayList<>(); + int j = 0; + while (j < faviconFiles.size()) { + if (browser.equals(GOOGLE_PROFILE_NAME)) { + String parentPath = FilenameUtils.normalizeNoEndSeparator(faviconFiles.get(j).getParentPath()); + browserName = GOOGLE_PROFILE + FilenameUtils.getBaseName(parentPath); + } + AbstractFile faviconFile = faviconFiles.get(j++); + if ((faviconFile.getSize() == 0) || (faviconFile.getName().toLowerCase().contains("-slack")) + || (faviconFile.getName().toLowerCase().contains("cache")) || (faviconFile.getName().toLowerCase().contains("index"))) { + continue; + } + + String temps = RAImageIngestModule.getRATempPath(currentCase, browserName, ingestJobId) + File.separator + faviconFile.getName() + j + ".db"; //NON-NLS + try { + ContentUtils.writeToFile(faviconFile, new File(temps), context::dataSourceIngestIsCancelled); + } catch (ReadContentInputStreamException ex) { + logger.log(Level.WARNING, String.format("Error reading Chrome favicons artifacts file '%s' (id=%d).", + faviconFile.getName(), faviconFile.getId()), ex); //NON-NLS + this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getFavicon.errMsg.errAnalyzeFiles1", + this.getDisplayName(), faviconFile.getName())); + continue; + } catch (IOException ex) { + logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Chrome favicon artifacts file '%s' (id=%d).", + temps, faviconFile.getName(), faviconFile.getId()), ex); //NON-NLS + this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getfavicon.errMsg.errAnalyzeFiles1", + this.getDisplayName(), faviconFile.getName())); + continue; + } + File dbFile = new File(temps); + if (context.dataSourceIngestIsCancelled()) { + dbFile.delete(); + break; + } + + BlackboardArtifact.Type faviconArtifactType; + + try { + faviconArtifactType = createFaviconArtifactType(); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Error creating artifact type for Chrome favicon."), ex); //NON-NLS + this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getfavicon.errMsg.errCreateArtifact")); + continue; + + } + + List<HashMap<String, Object>> tempList; + + tempList = this.querySQLiteDb(temps, FAVICON_QUERY); + + logger.log(Level.INFO, "{0}- Now getting favicons from {1} with {2} artifacts identified.", new Object[]{getDisplayName(), temps, tempList.size()}); //NON-NLS + for (HashMap<String, Object> result : tempList) { + Collection<BlackboardAttribute> bbattributes = new ArrayList<>(); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL, + RecentActivityExtracterModuleFactory.getModuleName(), + ((result.get("page_url").toString() != null) ? result.get("page_url").toString() : ""))); //NON-NLS + Long updatedTime = (Long.valueOf(result.get("last_updated").toString()) / 1000000) - Long.valueOf("11644473600"); //NON-NLS + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED, + RecentActivityExtracterModuleFactory.getModuleName(), updatedTime)); + Long requestedTime = (Long.valueOf(result.get("last_requested").toString()) / 1000000) - Long.valueOf("11644473600"); //NON-NLS + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, + RecentActivityExtracterModuleFactory.getModuleName(), requestedTime)); + String domain = NetworkUtils.extractDomain((result.get("page_url").toString() != null) ? result.get("page_url").toString() : ""); //NON-NLS + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, + RecentActivityExtracterModuleFactory.getModuleName(), domain)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, + RecentActivityExtracterModuleFactory.getModuleName(), browserName)); + + try { + bbartifacts.add(createArtifactWithAttributes(faviconArtifactType, faviconFile, bbattributes)); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Failed to create cookie artifact for file (%d)", faviconFile.getId()), ex); + } + + } + + dbFile.delete(); + } + + if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) { + postArtifacts(bbartifacts); + } + } + /** * Gets user logins from Login Data sqlite database * @@ -1068,4 +1189,24 @@ private boolean isChromePreVersion30(String temps) { return false; } + + @Messages({ + "ExtractFavicon_Display_Name=Favicon" + }) + /** + * Create TSK_FAVICON artifact type. + * + * @return the BlackboardArtifact.type of the artifact created + * @throws TskCoreException + */ + private BlackboardArtifact.Type createFaviconArtifactType() throws TskCoreException { + BlackboardArtifact.Type faviconArtifactType; + try { + faviconArtifactType = tskCase.getBlackboard().getOrAddArtifactType(FAVICON_ARTIFACT_NAME, Bundle.ExtractFavicon_Display_Name()); //NON-NLS + } catch (Blackboard.BlackboardException ex) { + throw new TskCoreException(String.format("An exception was thrown while defining artifact type %s", FAVICON_ARTIFACT_NAME), ex); + } + return faviconArtifactType; + } + }