From 91bd0e9e9d81ec5f8914e970baf86bcfc7dd2d8e Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 5 Mar 2019 15:46:01 -0500 Subject: [PATCH 1/9] Inital work on zone identifier parsing --- .../keywordsearch/Bundle.properties-MERGED | 2 +- .../recentactivity/ExtractZoneIdentifier.java | 381 ++++++++++++++++++ .../recentactivity/RAImageIngestModule.java | 2 + 3 files changed, 384 insertions(+), 1 deletion(-) create mode 100755 RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED index 61c0d2d2c7..f4febc1d7c 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED @@ -34,7 +34,7 @@ KeywordSearchIngestModule.startupMessage.failedToGetIndexSchema=Failed to get sc KeywordSearchResultFactory.createNodeForKey.noResultsFound.text=No results found. KeywordSearchResultFactory.query.exception.msg=Could not perform the query OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\nThe module indexes files found in the disk image at ingest time.\nIt then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\nThe module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword seach bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found. +OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\n\The module indexes files found in the disk image at ingest time.\n\It then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\n\The module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword seach bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found. OpenIDE-Module-Name=KeywordSearch OptionsCategory_Name_KeywordSearchOptions=Keyword Search OptionsCategory_Keywords_KeywordSearchOptions=Keyword Search diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java new file mode 100755 index 0000000000..86bc8b8eb1 --- /dev/null +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java @@ -0,0 +1,381 @@ +/* + * + * Autopsy Forensic Browser + * + * Copyright 2019 Basis Technology Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.recentactivity; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.logging.Level; +import org.openide.util.NbBundle.Messages; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.NetworkUtils; +import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.autopsy.ingest.IngestJobContext; +import org.sleuthkit.autopsy.ingest.IngestServices; +import org.sleuthkit.autopsy.ingest.ModuleDataEvent; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * Extract the :Zone.Indentifier files and create Artifact objects for them. + */ +final class ExtractZoneIdentifier extends Extract{ + + private static final Logger LOG = Logger.getLogger(ExtractEdge.class.getName()); + + private final IngestServices services = IngestServices.getInstance(); + + private static final String ZONE_IDENIFIER_FILE = "%:Zone.Identifier"; //NON-NLS + private static final String ZONE_IDENIFIER = ":Zone.Identifier"; //NON-NLS + + @Override + void process(Content dataSource, IngestJobContext context) { + + List zoneFiles = null; + try{ + zoneFiles = findZoneFiles(dataSource); + } catch(TskCoreException ex){ + + } + + if(zoneFiles == null || zoneFiles.isEmpty()) + return; + + Collection sourceArtifacts = new ArrayList<>(); + Collection downloadArtifacts = new ArrayList<>(); + + for(AbstractFile zoneFile: zoneFiles){ + processZoneFile(context, dataSource, zoneFile, sourceArtifacts, downloadArtifacts); + } + + if (!sourceArtifacts.isEmpty()) { + services.fireModuleDataEvent(new ModuleDataEvent( + RecentActivityExtracterModuleFactory.getModuleName(), + BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE, sourceArtifacts)); + } + + if (!downloadArtifacts.isEmpty()) { + services.fireModuleDataEvent(new ModuleDataEvent( + RecentActivityExtracterModuleFactory.getModuleName(), + BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadArtifacts)); + } + } + + /** + * Process a single Zone Identifier file. + * + * @param context IngetJobContext + * @param dataSource Content + * @param zoneFile Zone Indentifier file + * @param sourceArtifacts List for TSK_DOWNLOAD_SOURCE artifacts + * @param downloadArtifacts List for TSK_WEB_DOWNLOAD aritfacts + */ + private void processZoneFile(IngestJobContext context, Content dataSource, + AbstractFile zoneFile, Collection sourceArtifacts, + Collection downloadArtifacts){ + + File tempFile = null; + ZoneIdentifierInfo zoneInfo = null; + try{ + tempFile = createTemporaryZoneFile(context, zoneFile); + } catch(IOException ex) { + String message = String.format("Unable to create temporary File for %s", zoneFile.getName()); //NON-NLS + LOG.log(Level.WARNING, message, ex); + } + + try{ + zoneInfo = new ZoneIdentifierInfo(tempFile); + } catch(IOException ex){ + String message = String.format("Unable to parse temporary File for %s", zoneFile.getName()); //NON-NLS + LOG.log(Level.WARNING, message, ex); + } finally { + if(tempFile != null){ + tempFile.delete(); + } + } + + if(zoneInfo == null) { + return; + } + + AbstractFile downloadFile = null; + try{ + downloadFile = getDownloadFile(dataSource, zoneFile); + } catch(TskCoreException ex) { + + } + + if(downloadFile != null){ + BlackboardArtifact sourcebba = createDownloadSourceArtifact(downloadFile, zoneInfo); + if(sourcebba != null){ + sourceArtifacts.add(sourcebba); + } + + try{ + if(downloadFile.getArtifactsCount(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) == 0){ + BlackboardArtifact downloadbba = createDownloadArtifact(zoneFile, zoneInfo); + if(downloadbba != null){ + downloadArtifacts.add(downloadbba); + } + } + } catch(TskCoreException ex) { + + } + } + } + + /** + * Returns a list of all the file that end in :Zone.Identifier + * + * @param dataSource Content + * + * @return A list of zone identifier files + * + * @throws TskCoreException + */ + private List findZoneFiles(Content dataSource) throws TskCoreException { + org.sleuthkit.autopsy.casemodule.services.FileManager fileManager + = currentCase.getServices().getFileManager(); + + return fileManager.findFiles(dataSource, ZONE_IDENIFIER_FILE); + } + + /** + * Finds the file that is represently by the Zone Indentifer file. + * + * @param dataSource Content + * @param zoneFile The zone identifier case file + * + * @return The downloaded file or null if a file was not found + * + * @throws TskCoreException + */ + private AbstractFile getDownloadFile(Content dataSource, AbstractFile zoneFile) throws TskCoreException { + AbstractFile downloadFile = null; + + org.sleuthkit.autopsy.casemodule.services.FileManager fileManager + = currentCase.getServices().getFileManager(); + + String downloadFileName = zoneFile.getName().replace(ZONE_IDENIFIER, ""); //NON-NLS + + List fileList = fileManager.findFiles(dataSource, downloadFileName, zoneFile.getParentPath()); + + if(fileList.size() == 1) { + downloadFile = fileList.get(0); + } + + return downloadFile; + } + + /** + * Creates a Download Source Artifact for the given ZoneIdentifierInfo object. + * + * @param downloadFile AbstractFile representing the file downloaded, not the zone indentifier file. + * @param zoneInfo Zone Indentifer file wrapper object + * + * @return TSK_DOWNLOAD_SOURCE object for given parameters + */ + private BlackboardArtifact createDownloadSourceArtifact(AbstractFile downloadFile, ZoneIdentifierInfo zoneInfo){ + + Collection bbattributes = new ArrayList<>(); + + bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL, + RecentActivityExtracterModuleFactory.getModuleName(), + (zoneInfo.getURL() != null) ? zoneInfo.getURL() : "")); //NON-NLS + + bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN, + RecentActivityExtracterModuleFactory.getModuleName(), + (zoneInfo.getURL() != null) ? NetworkUtils.extractDomain(zoneInfo.getURL()) : "")); //NON-NLS + + bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION, + RecentActivityExtracterModuleFactory.getModuleName(), + (zoneInfo.getZoneIdAsString() != null) ? zoneInfo.getZoneIdAsString() : "")); //NON-NLS + + return addArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE, downloadFile, bbattributes); + } + + /** + * Create a TSK_WEB_DOWNLOAD Artifact for the given zone indentifier file. + * + * @param zoneFile Zone identifier file + * @param zoneInfo ZoneIdentifierInfo file wrapper object + * + * @return BlackboardArifact for the given parameters + */ + private BlackboardArtifact createDownloadArtifact(AbstractFile zoneFile, ZoneIdentifierInfo zoneInfo){ + + Collection bbattributes = createDownloadAttributes( + null, null, + zoneInfo.getURL(), null, + (zoneInfo.getURL() != null ? NetworkUtils.extractDomain(zoneInfo.getURL()) : ""), + null); + return addArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, zoneFile, bbattributes); + } + + /** + * Creates a copy of the given zoneFile. + * + * @param context IngestJobContext + * @param file zoneFile from case + * + * @return File object representing the newly created file + * + * @throws IOException + */ + private File createTemporaryZoneFile(IngestJobContext context, AbstractFile zoneFile) throws IOException{ + // Replace the invalid character in the file name. + String fileName = zoneFile.getName().replace(":", "_"); //NON-NLS + + Path tempFilePath = Paths.get(RAImageIngestModule.getRATempPath( + getCurrentCase(), getName()), fileName + zoneFile.getId()); + java.io.File tempFile = tempFilePath.toFile(); + + try { + ContentUtils.writeToFile(zoneFile, tempFile, context::dataSourceIngestIsCancelled); + } catch (IOException ex) { + throw new IOException("Error writingToFile: " + zoneFile, ex); //NON-NLS + } + + return tempFile; + } + + @Messages({ + "LOCAL_MACHINE_ZONE=Local Machine Zone", + "LOCAL_INTRANET_ZONE=Local Intranet Zone", + "TRUSTED_ZONE=Trusted Sites Zone", + "INTENET_ZONE=Internet Zone", + "RESTRICTED_ZONE=Restricted Sites Zone" + }) + + /** + * Wrapper class for information in the :ZoneIdentifier file. The ZoneIdentifier + * file has a simple format of key=value. There are four known + * keys: ZoneId, ReferrerUrl, HostUrl, and LastWriterPackageFamilyName. Not + * all browsers will put all values in the file, in fact most will only supply + * the ZoneId. Only Edge supplies the LastWriterPackageFamilyName. + */ + private final class ZoneIdentifierInfo{ + private static final String ZONE_ID = "zoneid"; //NON-NLS + private static final String REFERRER_URL = "referrerurl"; //NON-NLS + private static final String HOST_URL = "hosturl"; //NON-NLS + private static final String FAMILY_NAME = "lastwriterpackagefamilyname"; //NON-NLS + + private final HashMap dataMap = new HashMap<>(); + + /** + * Opens the zone file, reading for the key\value pairs and puts them + * into a HashMap. + * + * @param zoneFile The ZoneIdentifier file + * + * @throws FileNotFoundException + * @throws IOException + */ + ZoneIdentifierInfo(File zoneFile) throws FileNotFoundException, IOException{ + String line; + try(BufferedReader reader = new BufferedReader(new FileReader(zoneFile))) { + while((line = reader.readLine()) != null){ + String[] tokens = line.split("="); + + if(tokens.length < 2){ + continue; //Nothing interesting in this line + } + + dataMap.put(tokens[0].trim().toLowerCase(), tokens[1].trim()); + } + } + } + + /** + * Returns the integer zone id + * + * @return interger zone id or -1 if unknown + */ + int getZoneId(){ + int zoneValue = -1; + String value = dataMap.get(ZONE_ID); + if(value != null){ + zoneValue = Integer.parseInt(value); + } + + return zoneValue; + } + + /** + * Get the string description of the zone id. + * + * @return String description or null if a zone id was not found + */ + String getZoneIdAsString(){ + switch(getZoneId()){ + case 0: + return Bundle.LOCAL_MACHINE_ZONE(); + case 1: + return Bundle.LOCAL_INTRANET_ZONE(); + case 2: + return Bundle.TRUSTED_ZONE(); + case 3: + return Bundle.INTENET_ZONE(); + case 4: + return Bundle.RESTRICTED_ZONE(); + default: + return null; + } + } + + /** + * Get the URL from which the file was downloaded. + * + * @return String url or null if a host url was not found + */ + String getURL(){ + return dataMap.get(HOST_URL); + } + + /** + * Get the referrer url. + * + * @return String url or null if a host url was not found + */ + String getReferrer(){ + return dataMap.get(REFERRER_URL); + } + + /** + * Gets the string value for the key LastWriterPackageFamilyName. + * + * @return String value or null if the value was not found + */ + String getFamilyName(){ + return dataMap.get(FAMILY_NAME); + } + } + +} diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java index 0a42d7a031..f6e1d5b737 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java @@ -76,6 +76,7 @@ public final class RAImageIngestModule implements DataSourceIngestModule { Extract osExtract = new ExtractOs(); Extract dataSourceAnalyzer = new DataSourceUsageAnalyzer(); Extract safari = new ExtractSafari(); + Extract zoneInfo = new ExtractZoneIdentifier(); extractors.add(chrome); extractors.add(firefox); @@ -87,6 +88,7 @@ public final class RAImageIngestModule implements DataSourceIngestModule { extractors.add(registry); // this should run after quicker modules like the browser modules and needs to run before the DataSourceUsageAnalyzer extractors.add(osExtract); // this needs to run before the DataSourceUsageAnalyzer extractors.add(dataSourceAnalyzer); //this needs to run after ExtractRegistry and ExtractOs + extractors.add(zoneInfo); browserExtractors.add(chrome); browserExtractors.add(firefox); From 4421caef7446ef247512aad06df35ca6b199eb6f Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 5 Mar 2019 15:56:15 -0500 Subject: [PATCH 2/9] Removed a \ from the keywordsearch bundles.properties file --- .../src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties | 2 +- .../sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties index 9d82d32924..32a83d5c0f 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties @@ -1,5 +1,5 @@ OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\n\The module indexes files found in the disk image at ingest time.\n\It then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\n\The module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword seach bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found. +OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\nThe module indexes files found in the disk image at ingest time.\n\It then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\n\The module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword seach bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found. OpenIDE-Module-Name=KeywordSearch OptionsCategory_Name_KeywordSearchOptions=Keyword Search OptionsCategory_Keywords_KeywordSearchOptions=Keyword Search diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED index f4febc1d7c..8d37566beb 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED @@ -34,7 +34,7 @@ KeywordSearchIngestModule.startupMessage.failedToGetIndexSchema=Failed to get sc KeywordSearchResultFactory.createNodeForKey.noResultsFound.text=No results found. KeywordSearchResultFactory.query.exception.msg=Could not perform the query OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\n\The module indexes files found in the disk image at ingest time.\n\It then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\n\The module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword seach bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found. +OpenIDE-Module-Long-Description=Keyword Search ingest module.\n\nThe module indexes files found in the disk image at ingest time.\n\It then periodically runs the search on the indexed files using one or more keyword lists (containing pure words and/or regular expressions) and posts results.\n\n\The module also contains additional tools integrated in the main GUI, such as keyword list configuration, keyword seach bar in the top-right corner, extracted text viewer and search results viewer showing highlighted keywords found. OpenIDE-Module-Name=KeywordSearch OptionsCategory_Name_KeywordSearchOptions=Keyword Search OptionsCategory_Keywords_KeywordSearchOptions=Keyword Search From c14b8d55fcf9f53538f7443f18ba55b62c8f905d Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Wed, 6 Mar 2019 15:44:14 -0500 Subject: [PATCH 3/9] Updated based on Brian's comments --- .../recentactivity/ExtractZoneIdentifier.java | 80 ++++++++----------- .../recentactivity/RAImageIngestModule.java | 2 +- 2 files changed, 35 insertions(+), 47 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java index f8fbfea832..3cfae0969d 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java @@ -19,12 +19,9 @@ package org.sleuthkit.autopsy.recentactivity; import java.io.BufferedReader; -import java.io.File; import java.io.FileNotFoundException; -import java.io.FileReader; import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; +import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -33,7 +30,6 @@ import java.util.logging.Level; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.NetworkUtils; -import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress; import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestServices; @@ -42,6 +38,7 @@ import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.ReadContentInputStream; import org.sleuthkit.datamodel.TskCoreException; /** @@ -53,7 +50,7 @@ final class ExtractZoneIdentifier extends Extract { private static final String ZONE_IDENIFIER_FILE = "%:Zone.Identifier"; //NON-NLS private static final String ZONE_IDENIFIER = ":Zone.Identifier"; //NON-NLS - + @Messages({ "ExtractZone_process_errMsg_find=A failure occured while searching for :Zone.Indentifier files.", "ExtractZone_process_errMsg=A error occured processing ':Zone.Indentifier' files.", @@ -64,7 +61,7 @@ final class ExtractZoneIdentifier extends Extract { void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) { progressBar.progress(Bundle.ExtractZone_progress_Msg()); - + List zoneFiles = null; try { zoneFiles = findZoneFiles(dataSource); @@ -81,15 +78,15 @@ final class ExtractZoneIdentifier extends Extract { Collection downloadArtifacts = new ArrayList<>(); for (AbstractFile zoneFile : zoneFiles) { - try{ + try { processZoneFile(context, dataSource, zoneFile, sourceArtifacts, downloadArtifacts); - } catch(TskCoreException ex) { + } catch (TskCoreException ex) { addErrorMessage(Bundle.ExtractZone_process_errMsg()); String message = String.format("Failed to process zone identifier file %s", zoneFile.getName()); //NON-NLS LOG.log(Level.WARNING, message, ex); } } - + IngestServices services = IngestServices.getInstance(); if (!sourceArtifacts.isEmpty()) { @@ -118,24 +115,13 @@ final class ExtractZoneIdentifier extends Extract { AbstractFile zoneFile, Collection sourceArtifacts, Collection downloadArtifacts) throws TskCoreException { - File tempFile = null; ZoneIdentifierInfo zoneInfo = null; - try { - tempFile = createTemporaryZoneFile(context, zoneFile); - } catch (IOException ex) { - String message = String.format("Unable to create temporary File for %s", zoneFile.getName()); //NON-NLS - LOG.log(Level.WARNING, message, ex); - } try { - zoneInfo = new ZoneIdentifierInfo(tempFile); + zoneInfo = new ZoneIdentifierInfo(zoneFile); } catch (IOException ex) { String message = String.format("Unable to parse temporary File for %s", zoneFile.getName()); //NON-NLS LOG.log(Level.WARNING, message, ex); - } finally { - if (tempFile != null) { - tempFile.delete(); - } } if (zoneInfo == null) { @@ -145,12 +131,14 @@ final class ExtractZoneIdentifier extends Extract { AbstractFile downloadFile = getDownloadFile(dataSource, zoneFile); if (downloadFile != null) { - BlackboardArtifact sourcebba = createDownloadSourceArtifact(downloadFile, zoneInfo); - if (sourcebba != null) { - sourceArtifacts.add(sourcebba); + if (getArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE, zoneFile) == null) { + BlackboardArtifact sourcebba = createDownloadSourceArtifact(downloadFile, zoneInfo); + if (sourcebba != null) { + sourceArtifacts.add(sourcebba); + } } - if (downloadFile.getArtifactsCount(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD) == 0) { + if (getArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadFile) == null) { BlackboardArtifact downloadbba = createDownloadArtifact(zoneFile, zoneInfo); if (downloadbba != null) { downloadArtifacts.add(downloadbba); @@ -197,6 +185,13 @@ final class ExtractZoneIdentifier extends Extract { if (fileList.size() == 1) { downloadFile = fileList.get(0); + + // Check that the download file and the zone file came from the same dir + if (!downloadFile.getParentPath().equals(zoneFile.getParentPath())) { + downloadFile = null; + } else if (zoneFile.getMetaAddr() != downloadFile.getMetaAddr()) { + downloadFile = null; + } } return downloadFile; @@ -250,30 +245,23 @@ final class ExtractZoneIdentifier extends Extract { } /** - * Create a copy of the given zone file. + * Determine if an artifact of the given type exists for the AbstractFile. * - * @param context IngestJobContext - * @param file zoneFile from case + * @param type BlackboardArtifact type + * @param file AbstraceFile * - * @return File object representing the newly created file + * @return Returns the existing BlackboardArtifact or null if none exists * - * @throws IOException + * @throws TskCoreException */ - private File createTemporaryZoneFile(IngestJobContext context, AbstractFile zoneFile) throws IOException { - // Replace the invalid character in the file name. - String fileName = zoneFile.getName().replace(":", "_"); //NON-NLS - - Path tempFilePath = Paths.get(RAImageIngestModule.getRATempPath( - getCurrentCase(), getName()), fileName + zoneFile.getId()); - java.io.File tempFile = tempFilePath.toFile(); - - try { - ContentUtils.writeToFile(zoneFile, tempFile, context::dataSourceIngestIsCancelled); - } catch (IOException ex) { - throw new IOException("Error writingToFile: " + zoneFile, ex); //NON-NLS + private BlackboardArtifact getArtifact(BlackboardArtifact.ARTIFACT_TYPE type, AbstractFile file) throws TskCoreException { + for (BlackboardArtifact artifact : currentCase.getSleuthkitCase().getBlackboardArtifacts(type)) { + if (artifact.getDataSource().getId() == file.getDataSourceObjectId()) { + return artifact; + } } - return tempFile; + return null; } @Messages({ @@ -310,9 +298,9 @@ final class ExtractZoneIdentifier extends Extract { * @throws FileNotFoundException * @throws IOException */ - ZoneIdentifierInfo(File zoneFile) throws FileNotFoundException, IOException { + ZoneIdentifierInfo(AbstractFile zoneFile) throws FileNotFoundException, IOException { String line; - try (BufferedReader reader = new BufferedReader(new FileReader(zoneFile))) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(new ReadContentInputStream(zoneFile)))) { while ((line = reader.readLine()) != null) { String[] tokens = line.split("="); diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java index cb960576bc..db815e9274 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java @@ -88,7 +88,7 @@ public final class RAImageIngestModule implements DataSourceIngestModule { extractors.add(registry); // this should run after quicker modules like the browser modules and needs to run before the DataSourceUsageAnalyzer extractors.add(osExtract); // this needs to run before the DataSourceUsageAnalyzer extractors.add(dataSourceAnalyzer); //this needs to run after ExtractRegistry and ExtractOs - extractors.add(zoneInfo); + extractors.add(zoneInfo); // this needs to run after the web browser modules browserExtractors.add(chrome); browserExtractors.add(firefox); From 05da0c83b5cb74d19beed72f9b192f263ccb772b Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Wed, 6 Mar 2019 17:25:01 -0500 Subject: [PATCH 4/9] Changed the logic per Brian's comments --- .../recentactivity/Bundle.properties-MERGED | 14 +++-- .../recentactivity/ExtractZoneIdentifier.java | 51 ++++++++++++------- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED index 937b659039..4377fe936f 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED @@ -2,7 +2,6 @@ cannotBuildXmlParser=Unable to build XML parser: cannotLoadSEUQA=Unable to load Search Engine URL Query Analyzer settings file, SEUQAMappings.xml: cannotParseXml=Unable to parse XML file: ChromeCacheExtractor.moduleName=ChromeCacheExtractor -# {0} - OS name DataSourceUsageAnalyzer.customVolume.label=OS Drive ({0}) DataSourceUsageAnalyzer.parentModuleName=Recent Activity Extract.indexError.message=Failed to index artifact for keyword search. @@ -48,8 +47,14 @@ ExtractSafari_Error_Getting_History=An error occurred while processing Safari hi ExtractSafari_Error_Parsing_Bookmark=An error occured while processing Safari Bookmark files ExtractSafari_Error_Parsing_Cookies=An error occured while processing Safari Cookies files ExtractSafari_Module_Name=Safari +ExtractZone_process_errMsg=A error occured processing ':Zone.Indentifier' files. +ExtractZone_process_errMsg_find=A failure occured while searching for :Zone.Indentifier files. +ExtractZone_progress_Msg=Extracting :Zone.Identifer files +INTENET_ZONE=Internet Zone +LOCAL_INTRANET_ZONE=Local Intranet Zone +LOCAL_MACHINE_ZONE=Local Machine Zone OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\n\The module extracts useful information about the recent user activity on the disk image being ingested, such as:\n\n- Recently open documents,\n- Web acitivity (sites visited, stored cookies, bookmarked sites, search engine queries, file downloads),\n- Recently attached devices,\n- Installed programs.\n\n\The module currently supports Windows only disk images.\n\The plugin is also fully functional when deployed on Windows version of Autopsy. +OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\nThe module extracts useful information about the recent user activity on the disk image being ingested, such as:\n\n- Recently open documents,\n- Web acitivity (sites visited, stored cookies, bookmarked sites, search engine queries, file downloads),\n- Recently attached devices,\n- Installed programs.\n\nThe module currently supports Windows only disk images.\nThe plugin is also fully functional when deployed on Windows version of Autopsy. OpenIDE-Module-Name=RecentActivity OpenIDE-Module-Short-Description=Recent Activity finder ingest module Chrome.moduleName=Chrome @@ -173,12 +178,13 @@ RecentDocumentsByLnk.parentModuleName.noSpace=RecentActivity RecentDocumentsByLnk.parentModuleName=Recent Activity RegRipperFullNotFound=Full version RegRipper executable not found. RegRipperNotFound=Autopsy RegRipper executable not found. -# {0} - file name +RESTRICTED_ZONE=Restricted Sites Zone SearchEngineURLQueryAnalyzer.init.exception.msg=Unable to find {0}. SearchEngineURLQueryAnalyzer.moduleName.text=Search Engine SearchEngineURLQueryAnalyzer.engineName.none=NONE SearchEngineURLQueryAnalyzer.domainSubStr.none=NONE -SearchEngineURLQueryAnalyzer.toString=Name: {0}\nDomain Substring: {1}\n\count: {2}\nSplit Tokens: \n{3} +SearchEngineURLQueryAnalyzer.toString=Name: {0}\nDomain Substring: {1}\ncount: {2}\nSplit Tokens: \n{3} SearchEngineURLQueryAnalyzer.parentModuleName.noSpace=RecentActivity SearchEngineURLQueryAnalyzer.parentModuleName=Recent Activity +TRUSTED_ZONE=Trusted Sites Zone UsbDeviceIdMapper.parseAndLookup.text=Product: {0} diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java index 3cfae0969d..4020e61153 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java @@ -73,6 +73,18 @@ final class ExtractZoneIdentifier extends Extract { if (zoneFiles == null || zoneFiles.isEmpty()) { return; } + + ArrayList knownPathIDs = null; + try { + knownPathIDs = getPathIDsForType(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD); + } catch (TskCoreException ex) { + addErrorMessage(Bundle.ExtractZone_process_errMsg()); + LOG.log(Level.SEVERE, "Failed to build PathIDs List for TSK_WEB_DOWNLOAD", ex); + } + + if (knownPathIDs == null) { + return; + } Collection sourceArtifacts = new ArrayList<>(); Collection downloadArtifacts = new ArrayList<>(); @@ -129,21 +141,22 @@ final class ExtractZoneIdentifier extends Extract { } AbstractFile downloadFile = getDownloadFile(dataSource, zoneFile); + ArrayList knownPathIDs = getPathIDsForType(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD); if (downloadFile != null) { - if (getArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE, zoneFile) == null) { - BlackboardArtifact sourcebba = createDownloadSourceArtifact(downloadFile, zoneInfo); - if (sourcebba != null) { - sourceArtifacts.add(sourcebba); - } - } - - if (getArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadFile) == null) { + if (!knownPathIDs.contains(downloadFile.getDataSourceObjectId())) { BlackboardArtifact downloadbba = createDownloadArtifact(zoneFile, zoneInfo); if (downloadbba != null) { downloadArtifacts.add(downloadbba); } } + + if (downloadFile.getArtifactsCount(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE) == 0) { + BlackboardArtifact sourcebba = createDownloadSourceArtifact(downloadFile, zoneInfo); + if (sourcebba != null) { + sourceArtifacts.add(sourcebba); + } + } } } @@ -245,23 +258,27 @@ final class ExtractZoneIdentifier extends Extract { } /** - * Determine if an artifact of the given type exists for the AbstractFile. + * Creates a list of PathIDs for the given Artifact type. * - * @param type BlackboardArtifact type - * @param file AbstraceFile + * @param type BlackboardArtifact.ARTIFACT_TYPE * - * @return Returns the existing BlackboardArtifact or null if none exists + * @return A list of PathIDs * * @throws TskCoreException */ - private BlackboardArtifact getArtifact(BlackboardArtifact.ARTIFACT_TYPE type, AbstractFile file) throws TskCoreException { + private ArrayList getPathIDsForType(BlackboardArtifact.ARTIFACT_TYPE type) throws TskCoreException { + ArrayList idList = new ArrayList(); for (BlackboardArtifact artifact : currentCase.getSleuthkitCase().getBlackboardArtifacts(type)) { - if (artifact.getDataSource().getId() == file.getDataSourceObjectId()) { - return artifact; + BlackboardAttribute pathIDAttribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID)); + + if (pathIDAttribute != null) { + long contentID = pathIDAttribute.getValueLong(); + if (contentID != -1) { + idList.add(contentID); + } } } - - return null; + return idList; } @Messages({ From b6a552c2a153878665749324c42f2e97add0f910 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 7 Mar 2019 11:00:45 -0500 Subject: [PATCH 5/9] Addressed Jonathan's review comments --- .../recentactivity/Bundle.properties-MERGED | 2 +- .../recentactivity/ExtractZoneIdentifier.java | 119 ++++++++---------- 2 files changed, 52 insertions(+), 69 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED index 4377fe936f..0e2992d9b2 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED @@ -47,7 +47,7 @@ ExtractSafari_Error_Getting_History=An error occurred while processing Safari hi ExtractSafari_Error_Parsing_Bookmark=An error occured while processing Safari Bookmark files ExtractSafari_Error_Parsing_Cookies=An error occured while processing Safari Cookies files ExtractSafari_Module_Name=Safari -ExtractZone_process_errMsg=A error occured processing ':Zone.Indentifier' files. +ExtractZone_process_errMsg=An error occured processing ':Zone.Indentifier' files. ExtractZone_process_errMsg_find=A failure occured while searching for :Zone.Indentifier files. ExtractZone_progress_Msg=Extracting :Zone.Identifer files INTENET_ZONE=Internet Zone diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java index 4020e61153..4235cdd295 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java @@ -18,15 +18,17 @@ */ package org.sleuthkit.autopsy.recentactivity; -import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.IOException; -import java.io.InputStreamReader; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; -import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Properties; +import java.util.Set; import java.util.logging.Level; +import org.apache.commons.lang3.StringUtils; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.NetworkUtils; @@ -42,7 +44,9 @@ import org.sleuthkit.datamodel.ReadContentInputStream; import org.sleuthkit.datamodel.TskCoreException; /** - * Extract the :Zone.Indentifier alternate data stream files. + * Extract the :Zone.Indentifier alternate data stream files. A file with + * a :Zone.Indentifier extention contains information about the similarly + * named (with out zone identifer extention) downloaded file. */ final class ExtractZoneIdentifier extends Extract { @@ -53,7 +57,7 @@ final class ExtractZoneIdentifier extends Extract { @Messages({ "ExtractZone_process_errMsg_find=A failure occured while searching for :Zone.Indentifier files.", - "ExtractZone_process_errMsg=A error occured processing ':Zone.Indentifier' files.", + "ExtractZone_process_errMsg=An error occured processing ':Zone.Indentifier' files.", "ExtractZone_progress_Msg=Extracting :Zone.Identifer files" }) @@ -64,22 +68,23 @@ final class ExtractZoneIdentifier extends Extract { List zoneFiles = null; try { - zoneFiles = findZoneFiles(dataSource); + zoneFiles = currentCase.getServices().getFileManager().findFiles(dataSource, ZONE_IDENIFIER_FILE) + ; } catch (TskCoreException ex) { addErrorMessage(Bundle.ExtractZone_process_errMsg_find()); - LOG.log(Level.SEVERE, "Unable to find zone identifier files, exception thrown. ", ex); + LOG.log(Level.SEVERE, "Unable to find zone identifier files, exception thrown. ", ex); // NON-NLS } if (zoneFiles == null || zoneFiles.isEmpty()) { return; } - ArrayList knownPathIDs = null; + Set knownPathIDs = null; try { knownPathIDs = getPathIDsForType(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD); } catch (TskCoreException ex) { addErrorMessage(Bundle.ExtractZone_process_errMsg()); - LOG.log(Level.SEVERE, "Failed to build PathIDs List for TSK_WEB_DOWNLOAD", ex); + LOG.log(Level.SEVERE, "Failed to build PathIDs List for TSK_WEB_DOWNLOAD", ex); // NON-NLS } if (knownPathIDs == null) { @@ -91,7 +96,7 @@ final class ExtractZoneIdentifier extends Extract { for (AbstractFile zoneFile : zoneFiles) { try { - processZoneFile(context, dataSource, zoneFile, sourceArtifacts, downloadArtifacts); + processZoneFile(context, dataSource, zoneFile, sourceArtifacts, downloadArtifacts, knownPathIDs); } catch (TskCoreException ex) { addErrorMessage(Bundle.ExtractZone_process_errMsg()); String message = String.format("Failed to process zone identifier file %s", zoneFile.getName()); //NON-NLS @@ -125,7 +130,8 @@ final class ExtractZoneIdentifier extends Extract { */ private void processZoneFile(IngestJobContext context, Content dataSource, AbstractFile zoneFile, Collection sourceArtifacts, - Collection downloadArtifacts) throws TskCoreException { + Collection downloadArtifacts, + Set knownPathIDs) throws TskCoreException { ZoneIdentifierInfo zoneInfo = null; @@ -141,16 +147,19 @@ final class ExtractZoneIdentifier extends Extract { } AbstractFile downloadFile = getDownloadFile(dataSource, zoneFile); - ArrayList knownPathIDs = getPathIDsForType(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD); if (downloadFile != null) { + // Only create a new TSK_WEB_DOWNLOAD artifact if one does not exist for downloadFile if (!knownPathIDs.contains(downloadFile.getDataSourceObjectId())) { + // The zone identifier file is the parent of this artifact + // because it is the file we parsed to get the data BlackboardArtifact downloadbba = createDownloadArtifact(zoneFile, zoneInfo); if (downloadbba != null) { downloadArtifacts.add(downloadbba); } } - + + // check if download has a child TSK_DOWNLOAD_SOURCE artifact, if not create one if (downloadFile.getArtifactsCount(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE) == 0) { BlackboardArtifact sourcebba = createDownloadSourceArtifact(downloadFile, zoneInfo); if (sourcebba != null) { @@ -160,22 +169,6 @@ final class ExtractZoneIdentifier extends Extract { } } - /** - * Find a list of all the file that end in :Zone.Identifier. - * - * @param dataSource Content - * - * @return A list of zone identifier files - * - * @throws TskCoreException - */ - private List findZoneFiles(Content dataSource) throws TskCoreException { - org.sleuthkit.autopsy.casemodule.services.FileManager fileManager - = currentCase.getServices().getFileManager(); - - return fileManager.findFiles(dataSource, ZONE_IDENIFIER_FILE); - } - /** * Find the file that the Zone.Identifer file was created alongside. * @@ -223,18 +216,19 @@ final class ExtractZoneIdentifier extends Extract { private BlackboardArtifact createDownloadSourceArtifact(AbstractFile downloadFile, ZoneIdentifierInfo zoneInfo) { Collection bbattributes = new ArrayList<>(); - - bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL, + + bbattributes.addAll(Arrays.asList( + new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL, RecentActivityExtracterModuleFactory.getModuleName(), - (zoneInfo.getURL() != null) ? zoneInfo.getURL() : "")); //NON-NLS - - bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN, + StringUtils.defaultString(zoneInfo.getURL(), "")), + + new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN, RecentActivityExtracterModuleFactory.getModuleName(), - (zoneInfo.getURL() != null) ? NetworkUtils.extractDomain(zoneInfo.getURL()) : "")); //NON-NLS - - bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION, + (zoneInfo.getURL() != null) ? NetworkUtils.extractDomain(zoneInfo.getURL()) : ""), + + new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION, RecentActivityExtracterModuleFactory.getModuleName(), - (zoneInfo.getZoneIdAsString() != null) ? zoneInfo.getZoneIdAsString() : "")); //NON-NLS + StringUtils.defaultString(zoneInfo.getZoneIdAsString(), "")))); //NON-NLS return addArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE, downloadFile, bbattributes); } @@ -266,8 +260,8 @@ final class ExtractZoneIdentifier extends Extract { * * @throws TskCoreException */ - private ArrayList getPathIDsForType(BlackboardArtifact.ARTIFACT_TYPE type) throws TskCoreException { - ArrayList idList = new ArrayList(); + private Set getPathIDsForType(BlackboardArtifact.ARTIFACT_TYPE type) throws TskCoreException { + Set idList = new HashSet<>(); for (BlackboardArtifact artifact : currentCase.getSleuthkitCase().getBlackboardArtifacts(type)) { BlackboardAttribute pathIDAttribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID)); @@ -297,14 +291,14 @@ final class ExtractZoneIdentifier extends Extract { * file, in fact most will only supply the ZoneId. Only Edge supplies the * LastWriterPackageFamilyName. */ - private final class ZoneIdentifierInfo { + private final static class ZoneIdentifierInfo { - private static final String ZONE_ID = "zoneid"; //NON-NLS - private static final String REFERRER_URL = "referrerurl"; //NON-NLS - private static final String HOST_URL = "hosturl"; //NON-NLS - private static final String FAMILY_NAME = "lastwriterpackagefamilyname"; //NON-NLS + private static final String ZONE_ID = "ZoneId"; //NON-NLS + private static final String REFERRER_URL = "ReferrerUrl"; //NON-NLS + private static final String HOST_URL = "HostUrl"; //NON-NLS + private static final String FAMILY_NAME = "LastWriterPackageFamilyName"; //NON-NLS - private final HashMap dataMap = new HashMap<>(); + private final Properties properties = new Properties(null); /** * Opens the zone file, reading for the key\value pairs and puts them @@ -315,19 +309,8 @@ final class ExtractZoneIdentifier extends Extract { * @throws FileNotFoundException * @throws IOException */ - ZoneIdentifierInfo(AbstractFile zoneFile) throws FileNotFoundException, IOException { - String line; - try (BufferedReader reader = new BufferedReader(new InputStreamReader(new ReadContentInputStream(zoneFile)))) { - while ((line = reader.readLine()) != null) { - String[] tokens = line.split("="); - - if (tokens.length < 2) { - continue; //Nothing interesting in this line - } - - dataMap.put(tokens[0].trim().toLowerCase(), tokens[1].trim()); - } - } + ZoneIdentifierInfo(AbstractFile zoneFile) throws IOException { + properties.load(new ReadContentInputStream(zoneFile)); } /** @@ -335,9 +318,9 @@ final class ExtractZoneIdentifier extends Extract { * * @return interger zone id or -1 if unknown */ - int getZoneId() { + private int getZoneId() { int zoneValue = -1; - String value = dataMap.get(ZONE_ID); + String value = properties.getProperty(ZONE_ID); if (value != null) { zoneValue = Integer.parseInt(value); } @@ -350,7 +333,7 @@ final class ExtractZoneIdentifier extends Extract { * * @return String description or null if a zone id was not found */ - String getZoneIdAsString() { + private String getZoneIdAsString() { switch (getZoneId()) { case 0: return Bundle.LOCAL_MACHINE_ZONE(); @@ -372,8 +355,8 @@ final class ExtractZoneIdentifier extends Extract { * * @return String url or null if a host url was not found */ - String getURL() { - return dataMap.get(HOST_URL); + private String getURL() { + return properties.getProperty(HOST_URL); } /** @@ -381,8 +364,8 @@ final class ExtractZoneIdentifier extends Extract { * * @return String url or null if a host url was not found */ - String getReferrer() { - return dataMap.get(REFERRER_URL); + private String getReferrer() { + return properties.getProperty(REFERRER_URL); } /** @@ -390,8 +373,8 @@ final class ExtractZoneIdentifier extends Extract { * * @return String value or null if the value was not found */ - String getFamilyName() { - return dataMap.get(FAMILY_NAME); + private String getFamilyName() { + return properties.getProperty(FAMILY_NAME); } } From 637f8c6a4fc9005881dfd85506ab0858a853d302 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 7 Mar 2019 11:36:41 -0500 Subject: [PATCH 6/9] Added static imports --- .../recentactivity/ExtractZoneIdentifier.java | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java index 4235cdd295..63c24558f0 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java @@ -38,7 +38,13 @@ import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; +import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE; +import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD; import org.sleuthkit.datamodel.BlackboardAttribute; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ReadContentInputStream; import org.sleuthkit.datamodel.TskCoreException; @@ -81,7 +87,7 @@ final class ExtractZoneIdentifier extends Extract { Set knownPathIDs = null; try { - knownPathIDs = getPathIDsForType(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD); + knownPathIDs = getPathIDsForType(TSK_WEB_DOWNLOAD); } catch (TskCoreException ex) { addErrorMessage(Bundle.ExtractZone_process_errMsg()); LOG.log(Level.SEVERE, "Failed to build PathIDs List for TSK_WEB_DOWNLOAD", ex); // NON-NLS @@ -109,13 +115,13 @@ final class ExtractZoneIdentifier extends Extract { if (!sourceArtifacts.isEmpty()) { services.fireModuleDataEvent(new ModuleDataEvent( RecentActivityExtracterModuleFactory.getModuleName(), - BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE, sourceArtifacts)); + TSK_DOWNLOAD_SOURCE, sourceArtifacts)); } if (!downloadArtifacts.isEmpty()) { services.fireModuleDataEvent(new ModuleDataEvent( RecentActivityExtracterModuleFactory.getModuleName(), - BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadArtifacts)); + TSK_WEB_DOWNLOAD, downloadArtifacts)); } } @@ -160,7 +166,7 @@ final class ExtractZoneIdentifier extends Extract { } // check if download has a child TSK_DOWNLOAD_SOURCE artifact, if not create one - if (downloadFile.getArtifactsCount(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE) == 0) { + if (downloadFile.getArtifactsCount(TSK_DOWNLOAD_SOURCE) == 0) { BlackboardArtifact sourcebba = createDownloadSourceArtifact(downloadFile, zoneInfo); if (sourcebba != null) { sourceArtifacts.add(sourcebba); @@ -218,19 +224,19 @@ final class ExtractZoneIdentifier extends Extract { Collection bbattributes = new ArrayList<>(); bbattributes.addAll(Arrays.asList( - new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL, + new BlackboardAttribute(TSK_URL, RecentActivityExtracterModuleFactory.getModuleName(), StringUtils.defaultString(zoneInfo.getURL(), "")), - new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN, + new BlackboardAttribute(TSK_DOMAIN, RecentActivityExtracterModuleFactory.getModuleName(), (zoneInfo.getURL() != null) ? NetworkUtils.extractDomain(zoneInfo.getURL()) : ""), - new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION, + new BlackboardAttribute(TSK_LOCATION, RecentActivityExtracterModuleFactory.getModuleName(), StringUtils.defaultString(zoneInfo.getZoneIdAsString(), "")))); //NON-NLS - return addArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_DOWNLOAD_SOURCE, downloadFile, bbattributes); + return addArtifact(TSK_DOWNLOAD_SOURCE, downloadFile, bbattributes); } /** @@ -248,7 +254,7 @@ final class ExtractZoneIdentifier extends Extract { zoneInfo.getURL(), null, (zoneInfo.getURL() != null ? NetworkUtils.extractDomain(zoneInfo.getURL()) : ""), null); - return addArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, zoneFile, bbattributes); + return addArtifact(TSK_WEB_DOWNLOAD, zoneFile, bbattributes); } /** @@ -263,7 +269,7 @@ final class ExtractZoneIdentifier extends Extract { private Set getPathIDsForType(BlackboardArtifact.ARTIFACT_TYPE type) throws TskCoreException { Set idList = new HashSet<>(); for (BlackboardArtifact artifact : currentCase.getSleuthkitCase().getBlackboardArtifacts(type)) { - BlackboardAttribute pathIDAttribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID)); + BlackboardAttribute pathIDAttribute = artifact.getAttribute(new BlackboardAttribute.Type(TSK_PATH_ID)); if (pathIDAttribute != null) { long contentID = pathIDAttribute.getValueLong(); From 260014d0a087626770b0b3b9a6b77b0eb70cfc5a Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 7 Mar 2019 11:44:21 -0500 Subject: [PATCH 7/9] moved semi-colon --- .../autopsy/recentactivity/ExtractZoneIdentifier.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java index 63c24558f0..83148d04c6 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java @@ -74,8 +74,7 @@ final class ExtractZoneIdentifier extends Extract { List zoneFiles = null; try { - zoneFiles = currentCase.getServices().getFileManager().findFiles(dataSource, ZONE_IDENIFIER_FILE) - ; + zoneFiles = currentCase.getServices().getFileManager().findFiles(dataSource, ZONE_IDENIFIER_FILE); } catch (TskCoreException ex) { addErrorMessage(Bundle.ExtractZone_process_errMsg_find()); LOG.log(Level.SEVERE, "Unable to find zone identifier files, exception thrown. ", ex); // NON-NLS From 459e558593bb118a9373428e882e7717ceb4c23f Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Mon, 11 Mar 2019 10:41:42 -0400 Subject: [PATCH 8/9] Addressed review comments from Raman --- .../recentactivity/ExtractZoneIdentifier.java | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java index 83148d04c6..9211b479ab 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java @@ -52,14 +52,14 @@ import org.sleuthkit.datamodel.TskCoreException; /** * Extract the :Zone.Indentifier alternate data stream files. A file with * a :Zone.Indentifier extention contains information about the similarly - * named (with out zone identifer extention) downloaded file. + * named (with out zone identifer extension) downloaded file. */ final class ExtractZoneIdentifier extends Extract { private static final Logger LOG = Logger.getLogger(ExtractEdge.class.getName()); - private static final String ZONE_IDENIFIER_FILE = "%:Zone.Identifier"; //NON-NLS - private static final String ZONE_IDENIFIER = ":Zone.Identifier"; //NON-NLS + private static final String ZONE_IDENTIFIER_FILE = "%:Zone.Identifier"; //NON-NLS + private static final String ZONE_IDENTIFIER = ":Zone.Identifier"; //NON-NLS @Messages({ "ExtractZone_process_errMsg_find=A failure occured while searching for :Zone.Indentifier files.", @@ -74,7 +74,7 @@ final class ExtractZoneIdentifier extends Extract { List zoneFiles = null; try { - zoneFiles = currentCase.getServices().getFileManager().findFiles(dataSource, ZONE_IDENIFIER_FILE); + zoneFiles = currentCase.getServices().getFileManager().findFiles(dataSource, ZONE_IDENTIFIER_FILE); } catch (TskCoreException ex) { addErrorMessage(Bundle.ExtractZone_process_errMsg_find()); LOG.log(Level.SEVERE, "Unable to find zone identifier files, exception thrown. ", ex); // NON-NLS @@ -132,6 +132,8 @@ final class ExtractZoneIdentifier extends Extract { * @param zoneFile Zone Indentifier file * @param sourceArtifacts List for TSK_DOWNLOAD_SOURCE artifacts * @param downloadArtifacts List for TSK_WEB_DOWNLOAD aritfacts + * + * @throws TskCoreException */ private void processZoneFile(IngestJobContext context, Content dataSource, AbstractFile zoneFile, Collection sourceArtifacts, @@ -158,17 +160,17 @@ final class ExtractZoneIdentifier extends Extract { if (!knownPathIDs.contains(downloadFile.getDataSourceObjectId())) { // The zone identifier file is the parent of this artifact // because it is the file we parsed to get the data - BlackboardArtifact downloadbba = createDownloadArtifact(zoneFile, zoneInfo); - if (downloadbba != null) { - downloadArtifacts.add(downloadbba); + BlackboardArtifact downloadBba = createDownloadArtifact(zoneFile, zoneInfo); + if (downloadBba != null) { + downloadArtifacts.add(downloadBba); } } // check if download has a child TSK_DOWNLOAD_SOURCE artifact, if not create one if (downloadFile.getArtifactsCount(TSK_DOWNLOAD_SOURCE) == 0) { - BlackboardArtifact sourcebba = createDownloadSourceArtifact(downloadFile, zoneInfo); - if (sourcebba != null) { - sourceArtifacts.add(sourcebba); + BlackboardArtifact sourceBba = createDownloadSourceArtifact(downloadFile, zoneInfo); + if (sourceBba != null) { + sourceArtifacts.add(sourceBba); } } } @@ -190,7 +192,7 @@ final class ExtractZoneIdentifier extends Extract { org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager(); - String downloadFileName = zoneFile.getName().replace(ZONE_IDENIFIER, ""); //NON-NLS + String downloadFileName = zoneFile.getName().replace(ZONE_IDENTIFIER, ""); //NON-NLS List fileList = fileManager.findFiles(dataSource, downloadFileName, zoneFile.getParentPath()); @@ -284,7 +286,7 @@ final class ExtractZoneIdentifier extends Extract { "LOCAL_MACHINE_ZONE=Local Machine Zone", "LOCAL_INTRANET_ZONE=Local Intranet Zone", "TRUSTED_ZONE=Trusted Sites Zone", - "INTENET_ZONE=Internet Zone", + "INTERNET_ZONE=Internet Zone", "RESTRICTED_ZONE=Restricted Sites Zone" }) From 1636a5d8154ae0f0e79c7335d317543b3f74bf35 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 12 Mar 2019 09:27:53 -0400 Subject: [PATCH 9/9] Fixed zone string format --- .../recentactivity/Bundle.properties-MERGED | 12 ++++++----- .../recentactivity/ExtractZoneIdentifier.java | 20 +++++++++---------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED index 0e2992d9b2..282fa33b81 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED @@ -2,6 +2,7 @@ cannotBuildXmlParser=Unable to build XML parser: cannotLoadSEUQA=Unable to load Search Engine URL Query Analyzer settings file, SEUQAMappings.xml: cannotParseXml=Unable to parse XML file: ChromeCacheExtractor.moduleName=ChromeCacheExtractor +# {0} - OS name DataSourceUsageAnalyzer.customVolume.label=OS Drive ({0}) DataSourceUsageAnalyzer.parentModuleName=Recent Activity Extract.indexError.message=Failed to index artifact for keyword search. @@ -47,12 +48,14 @@ ExtractSafari_Error_Getting_History=An error occurred while processing Safari hi ExtractSafari_Error_Parsing_Bookmark=An error occured while processing Safari Bookmark files ExtractSafari_Error_Parsing_Cookies=An error occured while processing Safari Cookies files ExtractSafari_Module_Name=Safari +ExtractZone_Internet=Internet Zone +ExtractZone_Local_Intranet=Local Intranet Zone +ExtractZone_Local_Machine=Local Machine Zone ExtractZone_process_errMsg=An error occured processing ':Zone.Indentifier' files. ExtractZone_process_errMsg_find=A failure occured while searching for :Zone.Indentifier files. ExtractZone_progress_Msg=Extracting :Zone.Identifer files -INTENET_ZONE=Internet Zone -LOCAL_INTRANET_ZONE=Local Intranet Zone -LOCAL_MACHINE_ZONE=Local Machine Zone +ExtractZone_Restricted=Restricted Sites Zone +ExtractZone_Trusted=Trusted Sites Zone OpenIDE-Module-Display-Category=Ingest Module OpenIDE-Module-Long-Description=Recent Activity ingest module.\n\nThe module extracts useful information about the recent user activity on the disk image being ingested, such as:\n\n- Recently open documents,\n- Web acitivity (sites visited, stored cookies, bookmarked sites, search engine queries, file downloads),\n- Recently attached devices,\n- Installed programs.\n\nThe module currently supports Windows only disk images.\nThe plugin is also fully functional when deployed on Windows version of Autopsy. OpenIDE-Module-Name=RecentActivity @@ -178,7 +181,7 @@ RecentDocumentsByLnk.parentModuleName.noSpace=RecentActivity RecentDocumentsByLnk.parentModuleName=Recent Activity RegRipperFullNotFound=Full version RegRipper executable not found. RegRipperNotFound=Autopsy RegRipper executable not found. -RESTRICTED_ZONE=Restricted Sites Zone +# {0} - file name SearchEngineURLQueryAnalyzer.init.exception.msg=Unable to find {0}. SearchEngineURLQueryAnalyzer.moduleName.text=Search Engine SearchEngineURLQueryAnalyzer.engineName.none=NONE @@ -186,5 +189,4 @@ SearchEngineURLQueryAnalyzer.domainSubStr.none=NONE SearchEngineURLQueryAnalyzer.toString=Name: {0}\nDomain Substring: {1}\ncount: {2}\nSplit Tokens: \n{3} SearchEngineURLQueryAnalyzer.parentModuleName.noSpace=RecentActivity SearchEngineURLQueryAnalyzer.parentModuleName=Recent Activity -TRUSTED_ZONE=Trusted Sites Zone UsbDeviceIdMapper.parseAndLookup.text=Product: {0} diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java index 9211b479ab..56c6748712 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractZoneIdentifier.java @@ -283,11 +283,11 @@ final class ExtractZoneIdentifier extends Extract { } @Messages({ - "LOCAL_MACHINE_ZONE=Local Machine Zone", - "LOCAL_INTRANET_ZONE=Local Intranet Zone", - "TRUSTED_ZONE=Trusted Sites Zone", - "INTERNET_ZONE=Internet Zone", - "RESTRICTED_ZONE=Restricted Sites Zone" + "ExtractZone_Local_Machine=Local Machine Zone", + "ExtractZone_Local_Intranet=Local Intranet Zone", + "ExtractZone_Trusted=Trusted Sites Zone", + "ExtractZone_Internet=Internet Zone", + "ExtractZone_Restricted=Restricted Sites Zone" }) /** @@ -343,15 +343,15 @@ final class ExtractZoneIdentifier extends Extract { private String getZoneIdAsString() { switch (getZoneId()) { case 0: - return Bundle.LOCAL_MACHINE_ZONE(); + return Bundle.ExtractZone_Local_Machine(); case 1: - return Bundle.LOCAL_INTRANET_ZONE(); + return Bundle.ExtractZone_Local_Intranet(); case 2: - return Bundle.TRUSTED_ZONE(); + return Bundle.ExtractZone_Trusted(); case 3: - return Bundle.INTENET_ZONE(); + return Bundle.ExtractZone_Internet(); case 4: - return Bundle.RESTRICTED_ZONE(); + return Bundle.ExtractZone_Restricted(); default: return null; }