From 4d78270c16bbadcea555deeb35b0114c796a9f62 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Wed, 18 May 2022 16:19:42 -0400 Subject: [PATCH 1/4] Update Chromium.java Add Chrome profiles to be processed --- .../autopsy/recentactivity/Chromium.java | 74 ++++++++++++++----- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java index 1d22f930b9..3815ebfcb8 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java @@ -93,6 +93,8 @@ class Chromium extends Extract { private static final String WEB_DATA_FILE_NAME = "Web Data"; 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 = "Google Chrome Profile"; + private static final String GOOGLE_PROFILE = "Google Chrome "; private Boolean databaseEncrypted = false; private Boolean fieldEncrypted = false; @@ -109,6 +111,7 @@ class Chromium extends Extract { .put("UC Browser", "UCBrowser/User Data%/Default") .put("Brave", "BraveSoftware/Brave-Browser/User Data/Default") .put("Google Chrome", "Chrome/User Data/Default") + .put("Google Chrome Profile", "Chrome/User Data/Profile %") .build(); @Messages({"# {0} - browserName", @@ -190,9 +193,10 @@ class Chromium extends Extract { */ private void getHistory(String browser, String browserLocation, long ingestJobId) { FileManager fileManager = currentCase.getServices().getFileManager(); + String browserName = browser; List historyFiles; String historyFileName = HISTORY_FILE_NAME; - if (browser.equals(UC_BROWSER_NAME)) { + if (browserName.equals(UC_BROWSER_NAME)) { historyFileName = HISTORY_FILE_NAME + "%"; } try { @@ -223,7 +227,11 @@ class Chromium extends Extract { Collection bbartifacts = new ArrayList<>(); int j = 0; while (j < allocatedHistoryFiles.size()) { - String temps = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + allocatedHistoryFiles.get(j).getName() + j + ".db"; //NON-NLS + if (browser.equals(GOOGLE_PROFILE_NAME)) { + String parentPath = FilenameUtils.normalizeNoEndSeparator(allocatedHistoryFiles.get(j).getParentPath()); + browserName = GOOGLE_PROFILE + " " + FilenameUtils.getBaseName(parentPath); + } + String temps = RAImageIngestModule.getRATempPath(currentCase, browserName, ingestJobId) + File.separator + allocatedHistoryFiles.get(j).getName() + j + ".db"; //NON-NLS final AbstractFile historyFile = allocatedHistoryFiles.get(j++); if ((historyFile.getSize() == 0) || (historyFile.getName().toLowerCase().contains("-slack")) || (historyFile.getName().toLowerCase().contains("cache")) || (historyFile.getName().toLowerCase().contains("media")) @@ -263,7 +271,7 @@ class Chromium extends Extract { (Long.valueOf(result.get("last_visit_time").toString()) / 1000000) - Long.valueOf("11644473600"), result.get("from_visit") == null ? "" : result.get("from_visit").toString(), result.get("title") == null ? "" : result.get("title").toString(), - browser, + browserName, extractedDomain, ""); @@ -290,8 +298,9 @@ class Chromium extends Extract { private void getBookmark(String browser, String browserLocation, long ingestJobId) { FileManager fileManager = currentCase.getServices().getFileManager(); List bookmarkFiles; + String browserName = browser; String bookmarkFileName = BOOKMARK_FILE_NAME; - if (browser.equals(UC_BROWSER_NAME)) { + if (browserName.equals(UC_BROWSER_NAME)) { bookmarkFileName = BOOKMARK_FILE_NAME + "%"; } try { @@ -312,6 +321,11 @@ class Chromium extends Extract { Collection bbartifacts = new ArrayList<>(); int j = 0; while (j < bookmarkFiles.size()) { + if (browser.equals(GOOGLE_PROFILE_NAME)) { + String parentPath = FilenameUtils.normalizeNoEndSeparator(bookmarkFiles.get(j).getParentPath()); + browserName = GOOGLE_PROFILE + " " + FilenameUtils.getBaseName(parentPath); + } + AbstractFile bookmarkFile = bookmarkFiles.get(j++); if ((bookmarkFile.getSize() == 0) || (bookmarkFile.getName().toLowerCase().contains("-slack")) || (bookmarkFile.getName().toLowerCase().contains("extras")) || (bookmarkFile.getName().toLowerCase().contains("log")) @@ -319,7 +333,7 @@ class Chromium extends Extract { || (bookmarkFile.getName().toLowerCase().contains("bak")) || (bookmarkFile.getParentPath().toLowerCase().contains("backup"))) { continue; } - String temps = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + bookmarkFile.getName() + j + ".db"; //NON-NLS + String temps = RAImageIngestModule.getRATempPath(currentCase, browserName, ingestJobId) + File.separator + bookmarkFile.getName() + j + ".db"; //NON-NLS try { ContentUtils.writeToFile(bookmarkFile, new File(temps), context::dataSourceIngestIsCancelled); } catch (ReadContentInputStreamException ex) { @@ -404,7 +418,7 @@ class Chromium extends Extract { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED, RecentActivityExtracterModuleFactory.getModuleName(), (date / 1000000) - Long.valueOf("11644473600"))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, - RecentActivityExtracterModuleFactory.getModuleName(), browser)); + RecentActivityExtracterModuleFactory.getModuleName(), browserName)); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, RecentActivityExtracterModuleFactory.getModuleName(), domain)); @@ -435,8 +449,9 @@ class Chromium extends Extract { FileManager fileManager = currentCase.getServices().getFileManager(); List cookiesFiles; + String browserName = browser; String cookieFileName = COOKIE_FILE_NAME; - if (browser.equals(UC_BROWSER_NAME)) { + if (browserName.equals(UC_BROWSER_NAME)) { // Wildcard on front and back of Cookies are there for Cookie files that start with something else // ie: UC browser has "Extension Cookies.9" as well as Cookies.9 cookieFileName = "%" + COOKIE_FILE_NAME + "%"; @@ -459,11 +474,16 @@ class Chromium extends Extract { Collection bbartifacts = new ArrayList<>(); int j = 0; while (j < cookiesFiles.size()) { + if (browser.equals(GOOGLE_PROFILE_NAME)) { + String parentPath = FilenameUtils.normalizeNoEndSeparator(cookiesFiles.get(j).getParentPath()); + browserName = GOOGLE_PROFILE + FilenameUtils.getBaseName(parentPath); + } + AbstractFile cookiesFile = cookiesFiles.get(j++); if ((cookiesFile.getSize() == 0) || (cookiesFile.getName().toLowerCase().contains("-slack"))) { continue; } - String temps = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + cookiesFile.getName() + j + ".db"; //NON-NLS + String temps = RAImageIngestModule.getRATempPath(currentCase, browserName, ingestJobId) + File.separator + cookiesFile.getName() + j + ".db"; //NON-NLS try { ContentUtils.writeToFile(cookiesFile, new File(temps), context::dataSourceIngestIsCancelled); } catch (ReadContentInputStreamException ex) { @@ -503,7 +523,7 @@ class Chromium extends Extract { RecentActivityExtracterModuleFactory.getModuleName(), ((result.get("value").toString() != null) ? result.get("value").toString() : ""))); //NON-NLS bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, - RecentActivityExtracterModuleFactory.getModuleName(), browser)); + RecentActivityExtracterModuleFactory.getModuleName(), browserName)); String domain = result.get("host_key").toString(); //NON-NLS domain = domain.replaceFirst("^\\.+(?!$)", ""); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, @@ -534,8 +554,9 @@ class Chromium extends Extract { private void getDownload(String browser, String browserLocation, long ingestJobId) { FileManager fileManager = currentCase.getServices().getFileManager(); List downloadFiles; + String browserName = browser; String historyFileName = HISTORY_FILE_NAME; - if (browser.equals(UC_BROWSER_NAME)) { + if (browserName.equals(UC_BROWSER_NAME)) { historyFileName = HISTORY_FILE_NAME + "%"; } try { @@ -556,13 +577,18 @@ class Chromium extends Extract { Collection bbartifacts = new ArrayList<>(); int j = 0; while (j < downloadFiles.size()) { + if (browser.equals(GOOGLE_PROFILE_NAME)) { + String parentPath = FilenameUtils.normalizeNoEndSeparator(downloadFiles.get(j).getParentPath()); + browserName = GOOGLE_PROFILE + FilenameUtils.getBaseName(parentPath); + } + AbstractFile downloadFile = downloadFiles.get(j++); if ((downloadFile.getSize() == 0) || (downloadFile.getName().toLowerCase().contains("-slack")) || (downloadFile.getName().toLowerCase().contains("cache")) || (downloadFile.getName().toLowerCase().contains("index"))) { continue; } - String temps = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + downloadFile.getName() + j + ".db"; //NON-NLS + String temps = RAImageIngestModule.getRATempPath(currentCase, browserName, ingestJobId) + File.separator + downloadFile.getName() + j + ".db"; //NON-NLS try { ContentUtils.writeToFile(downloadFile, new File(temps), context::dataSourceIngestIsCancelled); } catch (ReadContentInputStreamException ex) { @@ -618,7 +644,7 @@ class Chromium extends Extract { bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, RecentActivityExtracterModuleFactory.getModuleName(), domain)); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, - RecentActivityExtracterModuleFactory.getModuleName(), browser)); + RecentActivityExtracterModuleFactory.getModuleName(), browserName)); // find the downloaded file and create a TSK_ASSOCIATED_OBJECT for it, associating it with the TSK_WEB_DOWNLOAD artifact. try { @@ -653,8 +679,9 @@ class Chromium extends Extract { FileManager fileManager = currentCase.getServices().getFileManager(); List loginDataFiles; + String browserName = browser; String loginDataFileName = LOGIN_DATA_FILE_NAME; - if (browser.equals(UC_BROWSER_NAME)) { + if (browserName.equals(UC_BROWSER_NAME)) { loginDataFileName = LOGIN_DATA_FILE_NAME + "%"; } @@ -676,11 +703,15 @@ class Chromium extends Extract { Collection bbartifacts = new ArrayList<>(); int j = 0; while (j < loginDataFiles.size()) { + if (browser.equals(GOOGLE_PROFILE_NAME)) { + String parentPath = FilenameUtils.normalizeNoEndSeparator(loginDataFiles.get(j).getParentPath()); + browserName = GOOGLE_PROFILE_NAME + FilenameUtils.getBaseName(parentPath); + } AbstractFile loginDataFile = loginDataFiles.get(j++); if ((loginDataFile.getSize() == 0) || (loginDataFile.getName().toLowerCase().contains("-slack"))) { continue; } - String temps = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + loginDataFile.getName() + j + ".db"; //NON-NLS + String temps = RAImageIngestModule.getRATempPath(currentCase, browserName, ingestJobId) + File.separator + loginDataFile.getName() + j + ".db"; //NON-NLS try { ContentUtils.writeToFile(loginDataFile, new File(temps), context::dataSourceIngestIsCancelled); } catch (ReadContentInputStreamException ex) { @@ -731,7 +762,7 @@ class Chromium extends Extract { result.containsKey("signon_realm") ? NetworkUtils.extractDomain(result.get("signon_realm").toString()) : "")); //NON-NLS bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, - RecentActivityExtracterModuleFactory.getModuleName(), browser)); + RecentActivityExtracterModuleFactory.getModuleName(), browserName)); try { bbartifacts.add(createArtifactWithAttributes(BlackboardArtifact.Type.TSK_SERVICE_ACCOUNT, loginDataFile, bbattributes)); @@ -760,8 +791,9 @@ class Chromium extends Extract { FileManager fileManager = currentCase.getServices().getFileManager(); List webDataFiles; + String browserName = browser; String webDataFileName = WEB_DATA_FILE_NAME; - if (browser.equals(UC_BROWSER_NAME)) { + if (browserName.equals(UC_BROWSER_NAME)) { webDataFileName = WEB_DATA_FILE_NAME + "%"; } @@ -783,12 +815,16 @@ class Chromium extends Extract { Collection bbartifacts = new ArrayList<>(); int j = 0; while (j < webDataFiles.size()) { + if (browser.equals(GOOGLE_PROFILE_NAME)) { + String parentPath = FilenameUtils.normalizeNoEndSeparator(webDataFiles.get(j).getParentPath()); + browserName = GOOGLE_PROFILE_NAME + FilenameUtils.getBaseName(parentPath); + } databaseEncrypted = false; AbstractFile webDataFile = webDataFiles.get(j++); if ((webDataFile.getSize() == 0) || (webDataFile.getName().toLowerCase().contains("-slack"))) { continue; } - String tempFilePath = RAImageIngestModule.getRATempPath(currentCase, browser, ingestJobId) + File.separator + webDataFile.getName() + j + ".db"; //NON-NLS + String tempFilePath = RAImageIngestModule.getRATempPath(currentCase, browserName, ingestJobId) + File.separator + webDataFile.getName() + j + ".db"; //NON-NLS try { ContentUtils.writeToFile(webDataFile, new File(tempFilePath), context::dataSourceIngestIsCancelled); } catch (ReadContentInputStreamException ex) { @@ -814,12 +850,12 @@ class Chromium extends Extract { boolean isSchemaV8X = Util.checkColumn("date_created", "autofill", tempFilePath); // get form autofill artifacts - bbartifacts.addAll(getFormAutofillArtifacts(webDataFile, tempFilePath, isSchemaV8X, browser)); + bbartifacts.addAll(getFormAutofillArtifacts(webDataFile, tempFilePath, isSchemaV8X, browserName)); try { // get form address atifacts getFormAddressArtifacts(webDataFile, tempFilePath, isSchemaV8X); if (databaseEncrypted) { - String comment = String.format("%s Autofill Database Encryption Detected", browser); + String comment = String.format("%s Autofill Database Encryption Detected", browserName); Collection bbattributes = Arrays.asList( new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COMMENT, RecentActivityExtracterModuleFactory.getModuleName(), comment)); From 70846566df1bfa8c3fa64059d3d58ca5ab9d133e Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Fri, 17 Jun 2022 09:51:50 -0400 Subject: [PATCH 2/4] Update Chromium.java Add System profile along with other profiles --- .../autopsy/recentactivity/Chromium.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java index 3815ebfcb8..a773891373 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java @@ -93,7 +93,7 @@ class Chromium extends Extract { private static final String WEB_DATA_FILE_NAME = "Web Data"; 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 = "Google Chrome Profile"; + private static final String GOOGLE_PROFILE_NAME = "Profile"; private static final String GOOGLE_PROFILE = "Google Chrome "; private Boolean databaseEncrypted = false; @@ -112,6 +112,7 @@ class Chromium extends Extract { .put("Brave", "BraveSoftware/Brave-Browser/User Data/Default") .put("Google Chrome", "Chrome/User Data/Default") .put("Google Chrome Profile", "Chrome/User Data/Profile %") + .put("Google Chrome System Profile", "Chrome/User Data/System Profile") .build(); @Messages({"# {0} - browserName", @@ -227,7 +228,7 @@ class Chromium extends Extract { Collection bbartifacts = new ArrayList<>(); int j = 0; while (j < allocatedHistoryFiles.size()) { - if (browser.equals(GOOGLE_PROFILE_NAME)) { + if (browser.contains(GOOGLE_PROFILE_NAME)) { String parentPath = FilenameUtils.normalizeNoEndSeparator(allocatedHistoryFiles.get(j).getParentPath()); browserName = GOOGLE_PROFILE + " " + FilenameUtils.getBaseName(parentPath); } @@ -321,7 +322,7 @@ class Chromium extends Extract { Collection bbartifacts = new ArrayList<>(); int j = 0; while (j < bookmarkFiles.size()) { - if (browser.equals(GOOGLE_PROFILE_NAME)) { + if (browser.contains(GOOGLE_PROFILE_NAME)) { String parentPath = FilenameUtils.normalizeNoEndSeparator(bookmarkFiles.get(j).getParentPath()); browserName = GOOGLE_PROFILE + " " + FilenameUtils.getBaseName(parentPath); } @@ -474,7 +475,7 @@ class Chromium extends Extract { Collection bbartifacts = new ArrayList<>(); int j = 0; while (j < cookiesFiles.size()) { - if (browser.equals(GOOGLE_PROFILE_NAME)) { + if (browser.contains(GOOGLE_PROFILE_NAME)) { String parentPath = FilenameUtils.normalizeNoEndSeparator(cookiesFiles.get(j).getParentPath()); browserName = GOOGLE_PROFILE + FilenameUtils.getBaseName(parentPath); } @@ -577,7 +578,7 @@ class Chromium extends Extract { Collection bbartifacts = new ArrayList<>(); int j = 0; while (j < downloadFiles.size()) { - if (browser.equals(GOOGLE_PROFILE_NAME)) { + if (browser.contains(GOOGLE_PROFILE_NAME)) { String parentPath = FilenameUtils.normalizeNoEndSeparator(downloadFiles.get(j).getParentPath()); browserName = GOOGLE_PROFILE + FilenameUtils.getBaseName(parentPath); } @@ -703,7 +704,7 @@ class Chromium extends Extract { Collection bbartifacts = new ArrayList<>(); int j = 0; while (j < loginDataFiles.size()) { - if (browser.equals(GOOGLE_PROFILE_NAME)) { + if (browser.contains(GOOGLE_PROFILE_NAME)) { String parentPath = FilenameUtils.normalizeNoEndSeparator(loginDataFiles.get(j).getParentPath()); browserName = GOOGLE_PROFILE_NAME + FilenameUtils.getBaseName(parentPath); } @@ -815,7 +816,7 @@ class Chromium extends Extract { Collection bbartifacts = new ArrayList<>(); int j = 0; while (j < webDataFiles.size()) { - if (browser.equals(GOOGLE_PROFILE_NAME)) { + if (browser.contains(GOOGLE_PROFILE_NAME)) { String parentPath = FilenameUtils.normalizeNoEndSeparator(webDataFiles.get(j).getParentPath()); browserName = GOOGLE_PROFILE_NAME + FilenameUtils.getBaseName(parentPath); } From f3ecd2828234f30ebd05464a59b1bb0bdd932ebf Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Tue, 21 Jun 2022 10:05:13 -0400 Subject: [PATCH 3/4] Add FAVICON artifact to RA Add Favicon artifact to RA --- .../autopsy/recentactivity/Bundle.properties | 3 + .../recentactivity/Bundle.properties-MERGED | 13 +- .../autopsy/recentactivity/Chromium.java | 141 ++++++++++++++++++ 3 files changed, 149 insertions(+), 8 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties index 602dc5b0a0..2388a93446 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 c73bf456d5..00df8b89d8 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 a773891373..09d5725bfd 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 @@ class Chromium extends Extract { 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 @@ class Chromium extends Extract { } } + /** + * 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 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 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> 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 result : tempList) { + Collection 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 @@ class Chromium extends Extract { 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; + } + } From 596d888f09efee8dc44e2164d4351233f92f7bc1 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Wed, 3 Aug 2022 13:35:47 -0400 Subject: [PATCH 4/4] Address Comments Address comments from PR --- .../src/org/sleuthkit/autopsy/recentactivity/Chromium.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java index 09d5725bfd..2133633891 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chromium.java @@ -709,7 +709,7 @@ class Chromium extends Extract { Collection bbartifacts = new ArrayList<>(); int j = 0; while (j < faviconFiles.size()) { - if (browser.equals(GOOGLE_PROFILE_NAME)) { + if (browser.contains(GOOGLE_PROFILE_NAME)) { String parentPath = FilenameUtils.normalizeNoEndSeparator(faviconFiles.get(j).getParentPath()); browserName = GOOGLE_PROFILE + FilenameUtils.getBaseName(parentPath); } @@ -827,7 +827,7 @@ class Chromium extends Extract { while (j < loginDataFiles.size()) { if (browser.contains(GOOGLE_PROFILE_NAME)) { String parentPath = FilenameUtils.normalizeNoEndSeparator(loginDataFiles.get(j).getParentPath()); - browserName = GOOGLE_PROFILE_NAME + FilenameUtils.getBaseName(parentPath); + browserName = GOOGLE_PROFILE + FilenameUtils.getBaseName(parentPath); } AbstractFile loginDataFile = loginDataFiles.get(j++); if ((loginDataFile.getSize() == 0) || (loginDataFile.getName().toLowerCase().contains("-slack"))) { @@ -939,7 +939,7 @@ class Chromium extends Extract { while (j < webDataFiles.size()) { if (browser.contains(GOOGLE_PROFILE_NAME)) { String parentPath = FilenameUtils.normalizeNoEndSeparator(webDataFiles.get(j).getParentPath()); - browserName = GOOGLE_PROFILE_NAME + FilenameUtils.getBaseName(parentPath); + browserName = GOOGLE_PROFILE + FilenameUtils.getBaseName(parentPath); } databaseEncrypted = false; AbstractFile webDataFile = webDataFiles.get(j++);