Merge branch 'postArtifacts_recent_activity' into postArtifacts_fallout_2

This commit is contained in:
millmanorama 2018-08-16 10:48:24 +02:00
commit 740e1b0e9a
14 changed files with 1555 additions and 1516 deletions

View File

@ -30,7 +30,7 @@ import java.sql.Statement;
import java.util.logging.Level; import java.util.logging.Level;
/** /**
* Database connection class & utilities * * Database connection class & utilities.
*/ */
public class SQLiteDBConnect implements AutoCloseable { public class SQLiteDBConnect implements AutoCloseable {
@ -127,6 +127,7 @@ public class SQLiteDBConnect implements AutoCloseable {
} catch (SQLException ex) { } catch (SQLException ex) {
logger.log(Level.WARNING, "Unable to close connection to SQLite DB at " + sUrl, ex); logger.log(Level.WARNING, "Unable to close connection to SQLite DB at " + sUrl, ex);
} }
//Implementing Autoclosable.close() allows this class to be used in try-with-resources.
} }
@Override @Override

View File

@ -34,13 +34,10 @@ import java.util.logging.Level;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.casemodule.services.FileManager;
import org.sleuthkit.autopsy.casemodule.services.Services;
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress; import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress;
import org.sleuthkit.autopsy.ingest.IngestModule; import org.sleuthkit.autopsy.ingest.IngestModule;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.FsContent;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.DataSourceIngestModule; import org.sleuthkit.autopsy.ingest.DataSourceIngestModule;

View File

@ -80,8 +80,8 @@ public class PlasoIngestModule implements DataSourceIngestModule {
@NbBundle.Messages({ @NbBundle.Messages({
"PlasoIngestModule_error_running=Error running Plaso, see log file.", "PlasoIngestModule_error_running=Error running Plaso, see log file.",
"PlasoIngestModule_log2timeline_executable_not_found=Log2timeline Executable Not Found", "PlasoIngestModule_log2timeline_executable_not_found=Log2timeline Executable Not Found",
"PlasoIngestModule_psort_executable_not_found=psort Executable Not Found",}) "PlasoIngestModule_psort_executable_not_found=psort Executable Not Found"
})
@Override @Override
public void startUp(IngestJobContext context) throws IngestModuleException { public void startUp(IngestJobContext context) throws IngestModuleException {
this.context = context; this.context = context;
@ -111,8 +111,8 @@ public class PlasoIngestModule implements DataSourceIngestModule {
"PlasoIngestModule_running_log2timeline=Running Log2timeline", "PlasoIngestModule_running_log2timeline=Running Log2timeline",
"PlasoIngestModule_running_psort=Running Psort", "PlasoIngestModule_running_psort=Running Psort",
"PlasoIngestModule_completed=Plaso Processing Completed", "PlasoIngestModule_completed=Plaso Processing Completed",
"PlasoIngestModule_has_run=Plaso Plugin has been run.",}) "PlasoIngestModule_has_run=Plaso Plugin has been run."
})
@Override @Override
public ProcessResult process(Content dataSource, DataSourceIngestModuleProgress statusHelper) { public ProcessResult process(Content dataSource, DataSourceIngestModuleProgress statusHelper) {
statusHelper.switchToIndeterminate(); statusHelper.switchToIndeterminate();

View File

@ -63,6 +63,15 @@
<specification-version>10.12</specification-version> <specification-version>10.12</specification-version>
</run-dependency> </run-dependency>
</dependency> </dependency>
<dependency>
<code-name-base>org.sleuthkit.autopsy.corelibs</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>3</release-version>
<specification-version>1.2</specification-version>
</run-dependency>
</dependency>
</module-dependencies> </module-dependencies>
<public-packages> <public-packages>
<package>org.sleuthkit.autopsy.recentactivity</package> <package>org.sleuthkit.autopsy.recentactivity</package>

View File

@ -83,6 +83,7 @@ RAImageIngestModule.complete.errMsg.failed={0} failed to complete - see log for
RAImageIngestModule.getName=Recent Activity RAImageIngestModule.getName=Recent Activity
RAImageIngestModule.getDesc=Extracts recent user activity, such as Web browsing, recently used documents and installed programs. RAImageIngestModule.getDesc=Extracts recent user activity, such as Web browsing, recently used documents and installed programs.
RecentDocumentsByLnk.getRecDoc.errMsg.errGetLnkFiles={0}\: Error getting lnk Files. RecentDocumentsByLnk.getRecDoc.errMsg.errGetLnkFiles={0}\: Error getting lnk Files.
RecentDocumentsByLnk.getRecDoc.errMsg.errCreatingArtifact={0}\: Error creating Recent Document artifact.
RecentDocumentsByLnk.getRecDoc.errParsingFile={0}\: Error parsing Recent File {1} RecentDocumentsByLnk.getRecDoc.errParsingFile={0}\: Error parsing Recent File {1}
RecentDocumentsByLnk.parentModuleName.noSpace=RecentActivity RecentDocumentsByLnk.parentModuleName.noSpace=RecentActivity
RecentDocumentsByLnk.parentModuleName=Recent Activity RecentDocumentsByLnk.parentModuleName=Recent Activity

View File

@ -22,30 +22,43 @@
*/ */
package org.sleuthkit.autopsy.recentactivity; package org.sleuthkit.autopsy.recentactivity;
import com.google.common.collect.Lists;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonElement; import com.google.gson.JsonElement;
import com.google.gson.JsonIOException; import com.google.gson.JsonIOException;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException; import com.google.gson.JsonSyntaxException;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import java.util.logging.Level;
import java.util.*;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import org.sleuthkit.autopsy.casemodule.services.FileManager; import java.util.*;
import java.util.logging.Level;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Blackboard;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_ACCOUNT;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_REFERRER;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL_DECODED;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException; import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
@ -54,20 +67,25 @@ import org.sleuthkit.datamodel.TskData;
/** /**
* Chrome recent activity extraction * Chrome recent activity extraction
*/ */
class Chrome extends Extract { final class Chrome extends Extract {
private static final Logger logger = Logger.getLogger(Chrome.class.getName());
private static final String PARENT_MODULE_NAME = NbBundle.getMessage(Chrome.class, "Chrome.parentModuleName");
private static final String HISTORY_QUERY = "SELECT urls.url, urls.title, urls.visit_count, urls.typed_count, " //NON-NLS private static final String HISTORY_QUERY = "SELECT urls.url, urls.title, urls.visit_count, urls.typed_count, " //NON-NLS
+ "last_visit_time, urls.hidden, visits.visit_time, (SELECT urls.url FROM urls WHERE urls.id=visits.url) AS from_visit, visits.transition FROM urls, visits WHERE urls.id = visits.url"; //NON-NLS + "last_visit_time, urls.hidden, visits.visit_time, (SELECT urls.url FROM urls WHERE urls.id=visits.url) AS from_visit, visits.transition FROM urls, visits WHERE urls.id = visits.url"; //NON-NLS
private static final String COOKIE_QUERY = "SELECT name, value, host_key, expires_utc,last_access_utc, creation_utc FROM cookies"; //NON-NLS private static final String COOKIE_QUERY = "SELECT name, value, host_key, expires_utc,last_access_utc, creation_utc FROM cookies"; //NON-NLS
private static final String DOWNLOAD_QUERY = "SELECT full_path, url, start_time, received_bytes FROM downloads"; //NON-NLS private static final String DOWNLOAD_QUERY = "SELECT full_path, url, start_time, received_bytes FROM downloads"; //NON-NLS
private static final String DOWNLOAD_QUERY_V30 = "SELECT current_path AS full_path, url, start_time, received_bytes FROM downloads, downloads_url_chains WHERE downloads.id=downloads_url_chains.id"; //NON-NLS private static final String DOWNLOAD_QUERY_V30 = "SELECT current_path AS full_path, url, start_time, received_bytes FROM downloads, downloads_url_chains WHERE downloads.id=downloads_url_chains.id"; //NON-NLS
private static final String LOGIN_QUERY = "SELECT origin_url, username_value, signon_realm from logins"; //NON-NLS private static final String LOGIN_QUERY = "SELECT origin_url, username_value, signon_realm from logins"; //NON-NLS
private final Logger logger = Logger.getLogger(this.getClass().getName());
private static final long SECONDS_SINCE_JAN_1_1601 = 11_644_473_600L;
private Content dataSource; private Content dataSource;
private IngestJobContext context; private IngestJobContext context;
Chrome() { @Override
moduleName = NbBundle.getMessage(Chrome.class, "Chrome.moduleName"); protected String getModuleName() {
return NbBundle.getMessage(Chrome.class, "Chrome.moduleName");
} }
@Override @Override
@ -85,15 +103,17 @@ class Chrome extends Extract {
/** /**
* Query for history databases and add artifacts * Query for history databases and add artifacts
*/ */
@NbBundle.Messages({"# {0} - Extractor / program name",
"Extractor.errPostingArtifacts={0}:Error while trying to post artifacts."})
private void getHistory() { private void getHistory() {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> historyFiles; List<AbstractFile> historyFiles;
try { try {
historyFiles = fileManager.findFiles(dataSource, "History", "Chrome"); //NON-NLS historyFiles = fileManager.findFiles(dataSource, "History", "Chrome"); //NON-NLS
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
String msg = NbBundle.getMessage(this.getClass(), "Chrome.getHistory.errMsg.errGettingFiles"); String msg = NbBundle.getMessage(Chrome.class, "Chrome.getHistory.errMsg.errGettingFiles");
logger.log(Level.SEVERE, msg, ex); logger.log(Level.SEVERE, msg, ex);
this.addErrorMessage(this.getName() + ": " + msg); this.addErrorMessage(this.getModuleName() + ": " + msg);
return; return;
} }
@ -107,11 +127,12 @@ class Chrome extends Extract {
// log a message if we don't have any allocated history files // log a message if we don't have any allocated history files
if (allocatedHistoryFiles.isEmpty()) { if (allocatedHistoryFiles.isEmpty()) {
String msg = NbBundle.getMessage(this.getClass(), "Chrome.getHistory.errMsg.couldntFindAnyFiles"); String msg = NbBundle.getMessage(Chrome.class, "Chrome.getHistory.errMsg.couldntFindAnyFiles");
logger.log(Level.INFO, msg); logger.log(Level.INFO, msg);
return; return;
} }
//TODO why are we using historyFiles instead of allocatedHistoryfiles here?
dataFound = true; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>(); Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0; int j = 0;
@ -126,14 +147,14 @@ class Chrome extends Extract {
} catch (ReadContentInputStreamException ex) { } catch (ReadContentInputStreamException ex) {
logger.log(Level.WARNING, String.format("Error reading Chrome web history artifacts file '%s' (id=%d).", logger.log(Level.WARNING, String.format("Error reading Chrome web history artifacts file '%s' (id=%d).",
historyFile.getName(), historyFile.getId()), ex); //NON-NLS historyFile.getName(), historyFile.getId()), ex); //NON-NLS
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getHistory.errMsg.errAnalyzingFile", this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getHistory.errMsg.errAnalyzingFile",
this.getName(), historyFile.getName())); this.getModuleName(), historyFile.getName()));
continue; continue;
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Chrome web history artifacts file '%s' (id=%d).", logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Chrome web history artifacts file '%s' (id=%d).",
temps, historyFile.getName(), historyFile.getId()), ex); //NON-NLS temps, historyFile.getName(), historyFile.getId()), ex); //NON-NLS
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getHistory.errMsg.errAnalyzingFile", this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getHistory.errMsg.errAnalyzingFile",
this.getName(), historyFile.getName())); this.getModuleName(), historyFile.getName()));
continue; continue;
} }
File dbFile = new File(temps); File dbFile = new File(temps);
@ -143,53 +164,57 @@ class Chrome extends Extract {
} }
List<HashMap<String, Object>> tempList; List<HashMap<String, Object>> tempList;
tempList = this.dbConnect(temps, HISTORY_QUERY); tempList = this.dbConnect(temps, HISTORY_QUERY);
logger.log(Level.INFO, "{0}- Now getting history from {1} with {2}artifacts identified.", new Object[]{moduleName, temps, tempList.size()}); //NON-NLS logger.log(Level.INFO, "{0}- Now getting history from {1} with {2}artifacts identified.", new Object[]{getModuleName(), temps, tempList.size()}); //NON-NLS
for (HashMap<String, Object> result : tempList) { for (HashMap<String, Object> result : tempList) {
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>(); Collection<BlackboardAttribute> bbattributes = Arrays.asList(new BlackboardAttribute(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL, TSK_URL, PARENT_MODULE_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), Objects.toString(result.get("url"), "")), //NON-NLS
((result.get("url").toString() != null) ? result.get("url").toString() : ""))); //NON-NLS new BlackboardAttribute(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, TSK_DATETIME_ACCESSED, PARENT_MODULE_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), (Long.valueOf(result.get("last_visit_time").toString()) / 1000000) - SECONDS_SINCE_JAN_1_1601),
(Long.valueOf(result.get("last_visit_time").toString()) / 1000000) - Long.valueOf("11644473600"))); //NON-NLS new BlackboardAttribute(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER, TSK_REFERRER, PARENT_MODULE_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), Objects.toString(result.get("from_visit"), "")), //NON-NLS
((result.get("from_visit").toString() != null) ? result.get("from_visit").toString() : ""))); //NON-NLS new BlackboardAttribute(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE, TSK_TITLE, PARENT_MODULE_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), Objects.toString(result.get("title"), "")), //NON-NLS
((result.get("title").toString() != null) ? result.get("title").toString() : ""))); //NON-NLS new BlackboardAttribute(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, TSK_PROG_NAME, PARENT_MODULE_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), getModuleName()),
NbBundle.getMessage(this.getClass(), "Chrome.moduleName"))); new BlackboardAttribute(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, TSK_DOMAIN, PARENT_MODULE_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), Util.extractDomain(Objects.toString(result.get("url"), "")))); //NON-NLS
(Util.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : "")))); //NON-NLS try {
BlackboardArtifact bbart = historyFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY);
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, historyFile, bbattributes); bbart.addAttributes(bbattributes);
if (bbart != null) {
bbartifacts.add(bbart); bbartifacts.add(bbart);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error while trying to create Chrome history artifact.", ex); //NON-NLS
this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getHistory.errMsg.errAnalyzingFile",
this.getModuleName(), historyFile.getName()));
} }
} }
dbFile.delete(); dbFile.delete();
} }
try {
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent( blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), } catch (Blackboard.BlackboardException ex) {
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, bbartifacts)); logger.log(Level.SEVERE, "Error while trying to post Chrome history artifact.", ex); //NON-NLS
this.addErrorMessage(Bundle.Extractor_errPostingArtifacts(getModuleName()));
}
} }
/** /**
* Search for bookmark files and make artifacts. * Search for bookmark files and make artifacts.
*/ */
private void getBookmark() { private void getBookmark() {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> bookmarkFiles; List<AbstractFile> bookmarkFiles;
try { try {
bookmarkFiles = fileManager.findFiles(dataSource, "Bookmarks", "Chrome"); //NON-NLS bookmarkFiles = fileManager.findFiles(dataSource, "Bookmarks", "Chrome"); //NON-NLS
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
String msg = NbBundle.getMessage(this.getClass(), "Chrome.getBookmark.errMsg.errGettingFiles"); String msg = NbBundle.getMessage(Chrome.class, "Chrome.getBookmark.errMsg.errGettingFiles");
logger.log(Level.SEVERE, msg, ex); logger.log(Level.SEVERE, msg, ex);
this.addErrorMessage(this.getName() + ": " + msg); this.addErrorMessage(this.getModuleName() + ": " + msg);
return; return;
} }
@ -200,31 +225,30 @@ class Chrome extends Extract {
dataFound = true; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>(); Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0; int index = 0;
while (index < bookmarkFiles.size()) {
while (j < bookmarkFiles.size()) { AbstractFile bookmarkFile = bookmarkFiles.get(index++);
AbstractFile bookmarkFile = bookmarkFiles.get(j++);
if (bookmarkFile.getSize() == 0) { if (bookmarkFile.getSize() == 0) {
continue; continue;
} }
String temps = RAImageIngestModule.getRATempPath(currentCase, "chrome") + File.separator + bookmarkFile.getName() + j + ".db"; //NON-NLS String temps = RAImageIngestModule.getRATempPath(currentCase, "chrome") + File.separator + bookmarkFile.getName() + index + ".db"; //NON-NLS
try { try {
ContentUtils.writeToFile(bookmarkFile, new File(temps), context::dataSourceIngestIsCancelled); ContentUtils.writeToFile(bookmarkFile, new File(temps), context::dataSourceIngestIsCancelled);
} catch (ReadContentInputStreamException ex) { } catch (ReadContentInputStreamException ex) {
logger.log(Level.WARNING, String.format("Error reading Chrome bookmark artifacts file '%s' (id=%d).", logger.log(Level.WARNING, String.format("Error reading Chrome bookmark artifacts file '%s' (id=%d).",
bookmarkFile.getName(), bookmarkFile.getId()), ex); //NON-NLS bookmarkFile.getName(), bookmarkFile.getId()), ex); //NON-NLS
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getBookmark.errMsg.errAnalyzingFile", this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getBookmark.errMsg.errAnalyzingFile",
this.getName(), bookmarkFile.getName())); this.getModuleName(), bookmarkFile.getName()));
continue; continue;
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Chrome bookmark artifacts file '%s' (id=%d).", logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Chrome bookmark artifacts file '%s' (id=%d).",
temps, bookmarkFile.getName(), bookmarkFile.getId()), ex); //NON-NLS temps, bookmarkFile.getName(), bookmarkFile.getId()), ex); //NON-NLS
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getBookmark.errMsg.errAnalyzingFile", this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getBookmark.errMsg.errAnalyzingFile",
this.getName(), bookmarkFile.getName())); this.getModuleName(), bookmarkFile.getName()));
continue; continue;
} }
logger.log(Level.INFO, "{0}- Now getting Bookmarks from {1}", new Object[]{moduleName, temps}); //NON-NLS logger.log(Level.INFO, "{0}- Now getting Bookmarks from {1}", new Object[]{getModuleName(), temps}); //NON-NLS
File dbFile = new File(temps); File dbFile = new File(temps);
if (context.dataSourceIngestIsCancelled()) { if (context.dataSourceIngestIsCancelled()) {
dbFile.delete(); dbFile.delete();
@ -236,8 +260,7 @@ class Chrome extends Extract {
tempReader = new FileReader(temps); tempReader = new FileReader(temps);
} catch (FileNotFoundException ex) { } catch (FileNotFoundException ex) {
logger.log(Level.SEVERE, "Error while trying to read into the Bookmarks for Chrome.", ex); //NON-NLS logger.log(Level.SEVERE, "Error while trying to read into the Bookmarks for Chrome.", ex); //NON-NLS
this.addErrorMessage( this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getBookmark.errMsg.errAnalyzeFile", this.getModuleName(),
NbBundle.getMessage(this.getClass(), "Chrome.getBookmark.errMsg.errAnalyzeFile", this.getName(),
bookmarkFile.getName())); bookmarkFile.getName()));
continue; continue;
} }
@ -255,8 +278,8 @@ class Chrome extends Extract {
jBookmarkArray = jBookmark.getAsJsonArray("children"); //NON-NLS jBookmarkArray = jBookmark.getAsJsonArray("children"); //NON-NLS
} catch (JsonIOException | JsonSyntaxException | IllegalStateException ex) { } catch (JsonIOException | JsonSyntaxException | IllegalStateException ex) {
logger.log(Level.WARNING, "Error parsing Json from Chrome Bookmark.", ex); //NON-NLS logger.log(Level.WARNING, "Error parsing Json from Chrome Bookmark.", ex); //NON-NLS
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getBookmark.errMsg.errAnalyzingFile3", this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getBookmark.errMsg.errAnalyzingFile3",
this.getName(), bookmarkFile.getName())); this.getModuleName(), bookmarkFile.getName()));
continue; continue;
} }
@ -288,58 +311,52 @@ class Chrome extends Extract {
} }
String domain = Util.extractDomain(url); String domain = Util.extractDomain(url);
try { try {
Collection<BlackboardAttribute> bbattributes = Arrays.asList(
new BlackboardAttribute(
TSK_URL, PARENT_MODULE_NAME,
url),
new BlackboardAttribute(
TSK_TITLE, PARENT_MODULE_NAME,
name),
new BlackboardAttribute(
TSK_DATETIME_CREATED, PARENT_MODULE_NAME,
(date / 1_000_000) - SECONDS_SINCE_JAN_1_1601),
new BlackboardAttribute(
TSK_PROG_NAME, PARENT_MODULE_NAME,
getModuleName()),
new BlackboardAttribute(
TSK_DOMAIN, PARENT_MODULE_NAME,
domain));
BlackboardArtifact bbart = bookmarkFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK); BlackboardArtifact bbart = bookmarkFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK);
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
//TODO Revisit usage of deprecated constructor as per TSK-583
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
NbBundle.getMessage(this.getClass(),
"Chrome.parentModuleName"), url));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
NbBundle.getMessage(this.getClass(),
"Chrome.parentModuleName"), name));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
NbBundle.getMessage(this.getClass(),
"Chrome.parentModuleName"), (date / 1000000) - Long.valueOf("11644473600")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
NbBundle.getMessage(this.getClass(),
"Chrome.parentModuleName"),
NbBundle.getMessage(this.getClass(), "Chrome.moduleName")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(),
"Chrome.parentModuleName"), domain));
bbart.addAttributes(bbattributes); bbart.addAttributes(bbattributes);
// index the artifact for keyword search
this.indexArtifact(bbart);
bbartifacts.add(bbart); bbartifacts.add(bbart);
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error while trying to insert Chrome bookmark artifact{0}", ex); //NON-NLS logger.log(Level.SEVERE, "Error while trying to insert Chrome bookmark artifact.", ex); //NON-NLS
this.addErrorMessage( this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getBookmark.errMsg.errAnalyzingFile4",
NbBundle.getMessage(this.getClass(), "Chrome.getBookmark.errMsg.errAnalyzingFile4", this.getModuleName(), bookmarkFile.getName()));
this.getName(), bookmarkFile.getName()));
} }
} }
dbFile.delete(); dbFile.delete();
} }
try {
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent( blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), } catch (Blackboard.BlackboardException ex) {
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bbartifacts)); logger.log(Level.SEVERE, "Error while trying to post Chrome bookmark artifact{0}", ex); //NON-NLS
this.addErrorMessage(Bundle.Extractor_errPostingArtifacts(getModuleName()));
}
} }
/** /**
* Queries for cookie files and adds artifacts * Queries for cookie files and adds artifacts
*/ */
private void getCookie() { private void getCookie() {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> cookiesFiles; List<AbstractFile> cookiesFiles;
try { try {
cookiesFiles = fileManager.findFiles(dataSource, "Cookies", "Chrome"); //NON-NLS cookiesFiles = fileManager.findFiles(dataSource, "Cookies", "Chrome"); //NON-NLS
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
String msg = NbBundle.getMessage(this.getClass(), "Chrome.getCookie.errMsg.errGettingFiles"); String msg = NbBundle.getMessage(Chrome.class, "Chrome.getCookie.errMsg.errGettingFiles");
logger.log(Level.SEVERE, msg, ex); logger.log(Level.SEVERE, msg, ex);
this.addErrorMessage(this.getName() + ": " + msg); this.addErrorMessage(this.getModuleName() + ": " + msg);
return; return;
} }
@ -350,26 +367,26 @@ class Chrome extends Extract {
dataFound = true; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>(); Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0; int index = 0;
while (j < cookiesFiles.size()) { while (index < cookiesFiles.size()) {
AbstractFile cookiesFile = cookiesFiles.get(j++); AbstractFile cookiesFile = cookiesFiles.get(index++);
if (cookiesFile.getSize() == 0) { if (cookiesFile.getSize() == 0) {
continue; continue;
} }
String temps = RAImageIngestModule.getRATempPath(currentCase, "chrome") + File.separator + cookiesFile.getName() + j + ".db"; //NON-NLS String temps = RAImageIngestModule.getRATempPath(currentCase, "chrome") + File.separator + cookiesFile.getName() + index + ".db"; //NON-NLS
try { try {
ContentUtils.writeToFile(cookiesFile, new File(temps), context::dataSourceIngestIsCancelled); ContentUtils.writeToFile(cookiesFile, new File(temps), context::dataSourceIngestIsCancelled);
} catch (ReadContentInputStreamException ex) { } catch (ReadContentInputStreamException ex) {
logger.log(Level.WARNING, String.format("Error reading Chrome cookie artifacts file '%s' (id=%d).", logger.log(Level.WARNING, String.format("Error reading Chrome cookie artifacts file '%s' (id=%d).",
cookiesFile.getName(), cookiesFile.getId()), ex); //NON-NLS cookiesFile.getName(), cookiesFile.getId()), ex); //NON-NLS
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getCookie.errMsg.errAnalyzeFile", this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getCookie.errMsg.errAnalyzeFile",
this.getName(), cookiesFile.getName())); this.getModuleName(), cookiesFile.getName()));
continue; continue;
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Chrome cookie artifacts file '%s' (id=%d).", logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Chrome cookie artifacts file '%s' (id=%d).",
temps, cookiesFile.getName(), cookiesFile.getId()), ex); //NON-NLS temps, cookiesFile.getName(), cookiesFile.getId()), ex); //NON-NLS
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getCookie.errMsg.errAnalyzeFile", this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getCookie.errMsg.errAnalyzeFile",
this.getName(), cookiesFile.getName())); this.getModuleName(), cookiesFile.getName()));
continue; continue;
} }
File dbFile = new File(temps); File dbFile = new File(temps);
@ -379,56 +396,60 @@ class Chrome extends Extract {
} }
List<HashMap<String, Object>> tempList = this.dbConnect(temps, COOKIE_QUERY); List<HashMap<String, Object>> tempList = this.dbConnect(temps, COOKIE_QUERY);
logger.log(Level.INFO, "{0}- Now getting cookies from {1} with {2}artifacts identified.", new Object[]{moduleName, temps, tempList.size()}); //NON-NLS logger.log(Level.INFO, "{0}- Now getting cookies from {1} with {2}artifacts identified.", new Object[]{getModuleName(), temps, tempList.size()}); //NON-NLS
for (HashMap<String, Object> result : tempList) { for (HashMap<String, Object> result : tempList) {
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
((result.get("host_key").toString() != null) ? result.get("host_key").toString() : ""))); //NON-NLS
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
(Long.valueOf(result.get("last_access_utc").toString()) / 1000000) - Long.valueOf("11644473600"))); //NON-NLS
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
((result.get("name").toString() != null) ? result.get("name").toString() : ""))); //NON-NLS
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
((result.get("value").toString() != null) ? result.get("value").toString() : ""))); //NON-NLS
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
NbBundle.getMessage(this.getClass(), "Chrome.moduleName")));
String domain = result.get("host_key").toString(); //NON-NLS String domain = result.get("host_key").toString(); //NON-NLS
domain = domain.replaceFirst("^\\.+(?!$)", ""); domain = domain.replaceFirst("^\\.+(?!$)", "");
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, Collection<BlackboardAttribute> bbattributes = Arrays.asList(new BlackboardAttribute(
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), domain)); TSK_DOMAIN, PARENT_MODULE_NAME,
domain),
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes); new BlackboardAttribute(
if (bbart != null) { TSK_URL, PARENT_MODULE_NAME,
Objects.toString(result.get("host_key"), "")), //NON-NLS
new BlackboardAttribute(
TSK_DATETIME, PARENT_MODULE_NAME,
(Long.valueOf(result.get("last_access_utc").toString()) / 1000000) - SECONDS_SINCE_JAN_1_1601), //NON-NLS
new BlackboardAttribute(
TSK_NAME, PARENT_MODULE_NAME,
Objects.toString(result.get("name"), "")), //NON-NLS
new BlackboardAttribute(
TSK_VALUE, PARENT_MODULE_NAME,
Objects.toString(result.get("value"), "")), //NON-NLS
new BlackboardAttribute(
TSK_PROG_NAME, PARENT_MODULE_NAME,
getModuleName()));
try {
BlackboardArtifact bbart = cookiesFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE);
bbart.addAttributes(bbattributes);
bbartifacts.add(bbart); bbartifacts.add(bbart);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error while trying to insert Chrome cookie artifact.", ex); //NON-NLS
this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getCookie.errMsg.errAnalyzingFile",
this.getModuleName(), cookiesFile.getName()));
} }
} }
dbFile.delete(); dbFile.delete();
} }
try {
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent( blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), } catch (Blackboard.BlackboardException ex) {
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE, bbartifacts)); logger.log(Level.SEVERE, "Error while trying to post Chrome cookie artifact.", ex); //NON-NLS
this.addErrorMessage(Bundle.Extractor_errPostingArtifacts(getModuleName()));
}
} }
/** /**
* Queries for download files and adds artifacts * Queries for download files and adds artifacts
*/ */
private void getDownload() { private void getDownload() {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> downloadFiles; List<AbstractFile> downloadFiles;
try { try {
downloadFiles = fileManager.findFiles(dataSource, "History", "Chrome"); //NON-NLS downloadFiles = fileManager.findFiles(dataSource, "History", "Chrome"); //NON-NLS
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
String msg = NbBundle.getMessage(this.getClass(), "Chrome.getDownload.errMsg.errGettingFiles"); String msg = NbBundle.getMessage(Chrome.class, "Chrome.getDownload.errMsg.errGettingFiles");
logger.log(Level.SEVERE, msg, ex); logger.log(Level.SEVERE, msg, ex);
this.addErrorMessage(this.getName() + ": " + msg); this.addErrorMessage(this.getModuleName() + ": " + msg);
return; return;
} }
@ -439,26 +460,26 @@ class Chrome extends Extract {
dataFound = true; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>(); Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0; int index = 0;
while (j < downloadFiles.size()) { while (index < downloadFiles.size()) {
AbstractFile downloadFile = downloadFiles.get(j++); AbstractFile downloadFile = downloadFiles.get(index++);
if (downloadFile.getSize() == 0) { if (downloadFile.getSize() == 0) {
continue; continue;
} }
String temps = RAImageIngestModule.getRATempPath(currentCase, "chrome") + File.separator + downloadFile.getName() + j + ".db"; //NON-NLS String temps = RAImageIngestModule.getRATempPath(currentCase, "chrome") + File.separator + downloadFile.getName() + index + ".db"; //NON-NLS
try { try {
ContentUtils.writeToFile(downloadFile, new File(temps), context::dataSourceIngestIsCancelled); ContentUtils.writeToFile(downloadFile, new File(temps), context::dataSourceIngestIsCancelled);
} catch (ReadContentInputStreamException ex) { } catch (ReadContentInputStreamException ex) {
logger.log(Level.WARNING, String.format("Error reading Chrome download artifacts file '%s' (id=%d).", logger.log(Level.WARNING, String.format("Error reading Chrome download artifacts file '%s' (id=%d).",
downloadFile.getName(), downloadFile.getId()), ex); //NON-NLS downloadFile.getName(), downloadFile.getId()), ex); //NON-NLS
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getDownload.errMsg.errAnalyzeFiles1", this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getDownload.errMsg.errAnalyzeFiles1",
this.getName(), downloadFile.getName())); this.getModuleName(), downloadFile.getName()));
continue; continue;
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Chrome download artifacts file '%s' (id=%d).", logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Chrome download artifacts file '%s' (id=%d).",
temps, downloadFile.getName(), downloadFile.getId()), ex); //NON-NLS temps, downloadFile.getName(), downloadFile.getId()), ex); //NON-NLS
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getDownload.errMsg.errAnalyzeFiles1", this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getDownload.errMsg.errAnalyzeFiles1",
this.getName(), downloadFile.getName())); this.getModuleName(), downloadFile.getName()));
continue; continue;
} }
File dbFile = new File(temps); File dbFile = new File(temps);
@ -467,68 +488,65 @@ class Chrome extends Extract {
break; break;
} }
List<HashMap<String, Object>> tempList; List<HashMap<String, Object>> tempList = this.dbConnect(temps,
(isChromePreVersion30(temps)) ? DOWNLOAD_QUERY : DOWNLOAD_QUERY_V30);
if (isChromePreVersion30(temps)) { logger.log(Level.INFO, "{0}- Now getting downloads from {1} with {2}artifacts identified.", new Object[]{getModuleName(), temps, tempList.size()}); //NON-NLS
tempList = this.dbConnect(temps, DOWNLOAD_QUERY);
} else {
tempList = this.dbConnect(temps, DOWNLOAD_QUERY_V30);
}
logger.log(Level.INFO, "{0}- Now getting downloads from {1} with {2}artifacts identified.", new Object[]{moduleName, temps, tempList.size()}); //NON-NLS
for (HashMap<String, Object> result : tempList) { for (HashMap<String, Object> result : tempList) {
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, Collection<BlackboardAttribute> bbattributes = Lists.newArrayList(new BlackboardAttribute(
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), (result.get("full_path").toString()))); //NON-NLS TSK_PATH, PARENT_MODULE_NAME,
Objects.toString(result.get("full_path"), "")), //NON-NLS
new BlackboardAttribute(
TSK_URL, PARENT_MODULE_NAME,
Objects.toString(result.get("url"), "")), //NON-NLS
new BlackboardAttribute(
TSK_DATETIME_ACCESSED, PARENT_MODULE_NAME,
(Long.valueOf(result.get("start_time").toString()) / 1000000) - SECONDS_SINCE_JAN_1_1601), //NON-NLS
new BlackboardAttribute(
TSK_DOMAIN, PARENT_MODULE_NAME,
Util.extractDomain(Objects.toString(result.get("url"), ""))), //NON-NLS
new BlackboardAttribute(
TSK_PROG_NAME, PARENT_MODULE_NAME,
getModuleName())
);
long pathID = Util.findID(dataSource, (result.get("full_path").toString())); //NON-NLS long pathID = Util.findID(dataSource, (result.get("full_path").toString())); //NON-NLS
if (pathID != -1) { if (pathID != -1) {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID, bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID, PARENT_MODULE_NAME, pathID));
NbBundle.getMessage(this.getClass(),
"Chrome.parentModuleName"), pathID));
} }
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL, try {
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), BlackboardArtifact bbart = downloadFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD);
((result.get("url").toString() != null) ? result.get("url").toString() : ""))); //NON-NLS bbart.addAttributes(bbattributes);
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : "")));
Long time = (Long.valueOf(result.get("start_time").toString()) / 1000000) - Long.valueOf("11644473600"); //NON-NLS
//TODO Revisit usage of deprecated constructor as per TSK-583
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "Recent Activity", "Last Visited", time));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), time));
String domain = Util.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : ""); //NON-NLS
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), domain));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
NbBundle.getMessage(this.getClass(), "Chrome.moduleName")));
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadFile, bbattributes);
if (bbart != null) {
bbartifacts.add(bbart); bbartifacts.add(bbart);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error while trying to insert Chrome download artifact.", ex); //NON-NLS
this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getDownload.errMsg.errAnalyzeFiles1",
this.getModuleName(), downloadFile.getName()));
} }
} }
dbFile.delete(); dbFile.delete();
} }
try {
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent( blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), } catch (Blackboard.BlackboardException ex) {
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, bbartifacts)); logger.log(Level.SEVERE, "Error while trying to post Chrome download artifact.", ex); //NON-NLS
this.addErrorMessage(Bundle.Extractor_errPostingArtifacts(getModuleName()));
}
} }
/** /**
* Queries for login files and adds artifacts * Queries for login files and adds artifacts
*/ */
private void getLogin() { private void getLogin() {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> signonFiles; List<AbstractFile> signonFiles;
try { try {
signonFiles = fileManager.findFiles(dataSource, "signons.sqlite", "Chrome"); //NON-NLS signonFiles = fileManager.findFiles(dataSource, "signons.sqlite", "Chrome"); //NON-NLS
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
String msg = NbBundle.getMessage(this.getClass(), "Chrome.getLogin.errMsg.errGettingFiles"); String msg = NbBundle.getMessage(Chrome.class, "Chrome.getLogin.errMsg.errGettingFiles");
logger.log(Level.SEVERE, msg, ex); logger.log(Level.SEVERE, msg, ex);
this.addErrorMessage(this.getName() + ": " + msg); this.addErrorMessage(this.getModuleName() + ": " + msg);
return; return;
} }
@ -539,26 +557,26 @@ class Chrome extends Extract {
dataFound = true; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>(); Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0; int index = 0;
while (j < signonFiles.size()) { while (index < signonFiles.size()) {
AbstractFile signonFile = signonFiles.get(j++); AbstractFile signonFile = signonFiles.get(index++);
if (signonFile.getSize() == 0) { if (signonFile.getSize() == 0) {
continue; continue;
} }
String temps = RAImageIngestModule.getRATempPath(currentCase, "chrome") + File.separator + signonFile.getName() + j + ".db"; //NON-NLS String temps = RAImageIngestModule.getRATempPath(currentCase, "chrome") + File.separator + signonFile.getName() + index + ".db"; //NON-NLS
try { try {
ContentUtils.writeToFile(signonFile, new File(temps), context::dataSourceIngestIsCancelled); ContentUtils.writeToFile(signonFile, new File(temps), context::dataSourceIngestIsCancelled);
} catch (ReadContentInputStreamException ex) { } catch (ReadContentInputStreamException ex) {
logger.log(Level.WARNING, String.format("Error reading Chrome login artifacts file '%s' (id=%d).", logger.log(Level.WARNING, String.format("Error reading Chrome login artifacts file '%s' (id=%d).",
signonFile.getName(), signonFile.getId()), ex); //NON-NLS signonFile.getName(), signonFile.getId()), ex); //NON-NLS
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getLogin.errMsg.errAnalyzingFiles", this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getLogin.errMsg.errAnalyzingFiles",
this.getName(), signonFile.getName())); this.getModuleName(), signonFile.getName()));
continue; continue;
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Chrome login artifacts file '%s' (id=%d).", logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Chrome login artifacts file '%s' (id=%d).",
temps, signonFile.getName(), signonFile.getId()), ex); //NON-NLS temps, signonFile.getName(), signonFile.getId()), ex); //NON-NLS
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getLogin.errMsg.errAnalyzingFiles", this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getLogin.errMsg.errAnalyzingFiles",
this.getName(), signonFile.getName())); this.getModuleName(), signonFile.getName()));
continue; continue;
} }
File dbFile = new File(temps); File dbFile = new File(temps);
@ -567,67 +585,78 @@ class Chrome extends Extract {
break; break;
} }
List<HashMap<String, Object>> tempList = this.dbConnect(temps, LOGIN_QUERY); List<HashMap<String, Object>> tempList = this.dbConnect(temps, LOGIN_QUERY);
logger.log(Level.INFO, "{0}- Now getting login information from {1} with {2}artifacts identified.", new Object[]{moduleName, temps, tempList.size()}); //NON-NLS logger.log(Level.INFO, "{0}- Now getting login information from {1} with {2}artifacts identified.", new Object[]{getModuleName(), temps, tempList.size()}); //NON-NLS
for (HashMap<String, Object> result : tempList) { for (HashMap<String, Object> result : tempList) {
Collection<BlackboardAttribute> bbattributes = new ArrayList<>(); Collection<BlackboardAttribute> bbattributes = Arrays.asList(new BlackboardAttribute(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL, TSK_URL, PARENT_MODULE_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), Objects.toString(result.get("origin_url"), "")), //NON-NLS
((result.get("origin_url").toString() != null) ? result.get("origin_url").toString() : ""))); //NON-NLS new BlackboardAttribute(
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "Recent Activity", ((result.get("origin_url").toString() != null) ? EscapeUtil.decodeURL(result.get("origin_url").toString()) : ""))); TSK_DATETIME_ACCESSED, PARENT_MODULE_NAME,
//TODO Revisit usage of deprecated constructor as per TSK-583 (Long.valueOf(result.get("last_visit_time").toString()) / 1000000) - SECONDS_SINCE_JAN_1_1601), //NON-NLS
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "Recent Activity", "Last Visited", ((Long.valueOf(result.get("last_visit_time").toString())) / 1000000))); new BlackboardAttribute(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, TSK_REFERRER, PARENT_MODULE_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), Objects.toString(result.get("from_visit"), "")), //NON-NLS
(Long.valueOf(result.get("last_visit_time").toString()) / 1000000) - Long.valueOf("11644473600"))); //NON-NLS new BlackboardAttribute(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER, TSK_NAME, PARENT_MODULE_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), Objects.toString(result.get("title").toString(), "")), //NON-NLS
((result.get("from_visit").toString() != null) ? result.get("from_visit").toString() : ""))); //NON-NLS new BlackboardAttribute(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, TSK_PROG_NAME, PARENT_MODULE_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), getModuleName()),
((result.get("title").toString() != null) ? result.get("title").toString() : ""))); //NON-NLS new BlackboardAttribute(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, TSK_URL_DECODED, PARENT_MODULE_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), Util.extractDomain(Objects.toString(result.get("origin_url"), ""))), //NON-NLS
NbBundle.getMessage(this.getClass(), "Chrome.moduleName"))); new BlackboardAttribute(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED, TSK_USER_NAME, PARENT_MODULE_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), Objects.toString(result.get("username_value"), "").replaceAll("'", "''")), //NON-NLS
(Util.extractDomain((result.get("origin_url").toString() != null) ? result.get("url").toString() : "")))); //NON-NLS new BlackboardAttribute(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, TSK_DOMAIN, PARENT_MODULE_NAME,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), Objects.toString(result.get("signon_realm"), ""))); //NON-NLS
((result.get("username_value").toString() != null) ? result.get("username_value").toString().replaceAll("'", "''") : ""))); //NON-NLS
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
result.get("signon_realm").toString())); //NON-NLS
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, signonFile, bbattributes); try {
if (bbart != null) { BlackboardArtifact bbart = signonFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY);
bbart.addAttributes(bbattributes);
bbartifacts.add(bbart); bbartifacts.add(bbart);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error while trying to insert Chrome login artifact.", ex); //NON-NLS
this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getLogin.errMsg.errAnalyzingFiles",
this.getModuleName(), signonFile.getName()));
} }
// Don't add TSK_OS_ACCOUNT artifacts to the ModuleDataEvent // Don't add TSK_OS_ACCOUNT artifacts to the ModuleDataEvent
Collection<BlackboardAttribute> osAcctAttributes = new ArrayList<>(); //TODO: Why not? Because it has a different artifact type? We can just post it seperately?
osAcctAttributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, try {
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), BlackboardAttribute osAcctAttribute = new BlackboardAttribute(TSK_USER_NAME, PARENT_MODULE_NAME,
((result.get("username_value").toString() != null) ? result.get("username_value").toString().replaceAll("'", "''") : ""))); //NON-NLS Objects.toString(result.get("username_value"), "").replaceAll("'", "''")); //NON-NLS
this.addArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT, signonFile, osAcctAttributes); BlackboardArtifact osAccountArtifact = signonFile.newArtifact(TSK_OS_ACCOUNT);
osAccountArtifact.addAttributes(Collections.singleton(osAcctAttribute));
blackboard.postArtifact(osAccountArtifact, PARENT_MODULE_NAME);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error while trying to insert Chrome os account artifact.", ex); //NON-NLS
this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getLogin.errMsg.errAnalyzingFiles",
this.getModuleName(), signonFile.getName()));
} catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, "Error while trying to post Chrome os account artifact.", ex); //NON-NLS
this.addErrorMessage(Bundle.Extractor_errPostingArtifacts(getModuleName()));
}
} }
dbFile.delete(); dbFile.delete();
} }
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent( try {
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, bbartifacts)); } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, "Error while trying to post Chrome login artifact.", ex); //NON-NLS
this.addErrorMessage(Bundle.Extractor_errPostingArtifacts(getModuleName()));
}
} }
private boolean isChromePreVersion30(String temps) { private boolean isChromePreVersion30(String temps) {
String query = "PRAGMA table_info(downloads)"; //NON-NLS String query = "PRAGMA table_info(downloads)"; //NON-NLS
List<HashMap<String, Object>> columns = this.dbConnect(temps, query); List<HashMap<String, Object>> columns = this.dbConnect(temps, query);
for (HashMap<String, Object> col : columns) { return columns.stream()
if (col.get("name").equals("url")) { //NON-NLS .anyMatch(col -> "url".equals(col.get("name")));
return true;
}
}
return false;
} }
} }

View File

@ -31,8 +31,8 @@ import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.casemodule.services.FileManager;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.SQLiteDBConnect; import org.sleuthkit.autopsy.coreutils.SQLiteDBConnect;
import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException; import org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException;
@ -40,21 +40,33 @@ import org.sleuthkit.datamodel.*;
abstract class Extract { abstract class Extract {
private static final Logger logger = Logger.getLogger(Extract.class.getName());
protected Case currentCase; protected Case currentCase;
protected SleuthkitCase tskCase; protected SleuthkitCase tskCase;
private final Logger logger = Logger.getLogger(this.getClass().getName()); protected Blackboard blackboard;
protected FileManager fileManager;
private final ArrayList<String> errorMessages = new ArrayList<>(); private final ArrayList<String> errorMessages = new ArrayList<>();
String moduleName = "";
boolean dataFound = false; boolean dataFound = false;
Extract() { /**
} * Returns the name of the inheriting class
*
* @return Gets the moduleName
*/
abstract protected String getModuleName();
@Messages({"Extract.indexError.message=Failed to index artifact for keyword search.",
"Extract.noOpenCase.errMsg=No open case available."})
final void init() throws IngestModuleException { final void init() throws IngestModuleException {
try { try {
currentCase = Case.getCurrentCaseThrows(); currentCase = Case.getCurrentCaseThrows();
tskCase = currentCase.getSleuthkitCase(); tskCase = currentCase.getSleuthkitCase();
blackboard = tskCase.getBlackboard();
fileManager = currentCase.getServices().getFileManager();
} catch (NoCurrentCaseException ex) { } catch (NoCurrentCaseException ex) {
//TODO: fix this error message
throw new IngestModuleException(Bundle.Extract_indexError_message(), ex); throw new IngestModuleException(Bundle.Extract_indexError_message(), ex);
} }
configExtractor(); configExtractor();
@ -91,54 +103,25 @@ abstract class Extract {
errorMessages.add(message); errorMessages.add(message);
} }
/** //
* Generic method for adding a blackboard artifact to the blackboard and // /**
* indexing it // * Method to index a blackboard artifact for keyword search
* // *
* @param type is a blackboard.artifact_type enum to determine which // * @param bbart Blackboard artifact to be indexed
* type the artifact should be // */
* @param content is the AbstractFile object that needs to have the //
* artifact added for it // void postArtifacts(Collections<BlackboardArtifact> bbarts) throws Blackboard.BlackboardException {
* @param bbattributes is the collection of blackboard attributes that need //
* to be added to the artifact after the artifact has // // index the artifact for keyword search
* been created // blackboard.postArtifact(bbarts, getModuleName());
* //// } catch (Blackboard.BlackboardException ex) {
* @return The newly-created artifact, or null on error //// logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bbart.getDisplayName(), ex); //NON-NLS
*/ //// MessageNotifyUtil.Notify.error(Bundle.Extract_indexError_message(), bbart.getDisplayName());
protected BlackboardArtifact addArtifact(BlackboardArtifact.ARTIFACT_TYPE type, AbstractFile content, Collection<BlackboardAttribute> bbattributes) { //// } catch (NoCurrentCaseException ex) {
try { //// logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS
BlackboardArtifact bbart = content.newArtifact(type); //// MessageNotifyUtil.Notify.error(Bundle.Extract_noOpenCase_errMsg(), bbart.getDisplayName());
bbart.addAttributes(bbattributes); //// }
// index the artifact for keyword search // }
this.indexArtifact(bbart);
return bbart;
} catch (TskException ex) {
logger.log(Level.SEVERE, "Error while trying to add an artifact", ex); //NON-NLS
}
return null;
}
/**
* Method to index a blackboard artifact for keyword search
*
* @param bbart Blackboard artifact to be indexed
*/
@Messages({"Extract.indexError.message=Failed to index artifact for keyword search.",
"Extract.noOpenCase.errMsg=No open case available."})
void indexArtifact(BlackboardArtifact bbart) {
try {
Blackboard blackboard = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard();
// index the artifact for keyword search
blackboard.postArtifact(bbart, NbBundle.getMessage(Extract.class, "Chrome.parentModuleName"));
} catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bbart.getDisplayName(), ex); //NON-NLS
MessageNotifyUtil.Notify.error(Bundle.Extract_indexError_message(), bbart.getDisplayName());
} catch (NoCurrentCaseException ex) {
logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS
MessageNotifyUtil.Notify.error(Bundle.Extract_noOpenCase_errMsg(), bbart.getDisplayName());
}
}
/** /**
* Returns a List from a result set based on sql query. This is used to * Returns a List from a result set based on sql query. This is used to
* query sqlite databases storing user recent activity data, such as in * query sqlite databases storing user recent activity data, such as in
@ -151,20 +134,16 @@ abstract class Extract {
* it that the query obtained * it that the query obtained
*/ */
protected List<HashMap<String, Object>> dbConnect(String path, String query) { protected List<HashMap<String, Object>> dbConnect(String path, String query) {
ResultSet temprs;
List<HashMap<String, Object>> list;
String connectionString = "jdbc:sqlite:" + path; //NON-NLS String connectionString = "jdbc:sqlite:" + path; //NON-NLS
try { try (SQLiteDBConnect tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", connectionString); //NON-NLS
SQLiteDBConnect tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", connectionString); //NON-NLS ResultSet temprs = tempdbconnect.executeQry(query);) {
temprs = tempdbconnect.executeQry(query); return this.resultSetToArrayList(temprs);
list = this.resultSetToArrayList(temprs);
tempdbconnect.closeConnection();
} catch (SQLException ex) { } catch (SQLException ex) {
logger.log(Level.SEVERE, "Error while trying to read into a sqlite db." + connectionString, ex); //NON-NLS logger.log(Level.SEVERE, "Error while trying to read into a sqlite db." + connectionString, ex); //NON-NLS
errorMessages.add(NbBundle.getMessage(this.getClass(), "Extract.dbConn.errMsg.failedToQueryDb", getName())); errorMessages.add(NbBundle.getMessage(this.getClass(), "Extract.dbConn.errMsg.failedToQueryDb", getModuleName()));
return Collections.<HashMap<String, Object>>emptyList(); return Collections.<HashMap<String, Object>>emptyList();
} }
return list;
} }
/** /**
@ -193,15 +172,6 @@ abstract class Extract {
return list; return list;
} }
/**
* Returns the name of the inheriting class
*
* @return Gets the moduleName set in the moduleName data member
*/
protected String getName() {
return moduleName;
}
public boolean foundData() { public boolean foundData() {
return dataFound; return dataFound;
} }

View File

@ -22,10 +22,9 @@
*/ */
package org.sleuthkit.autopsy.recentactivity; package org.sleuthkit.autopsy.recentactivity;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Sets;
import java.io.BufferedReader; import java.io.BufferedReader;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.ExecUtil;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -34,29 +33,46 @@ import java.io.InputStreamReader;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.Arrays;
import java.util.Set;
import java.util.HashSet;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Scanner; import java.util.Scanner;
import java.util.stream.Collectors; import java.util.Set;
import java.util.logging.Level;
import org.apache.commons.lang3.StringUtils;
import org.openide.modules.InstalledFileLocator; import org.openide.modules.InstalledFileLocator;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.autopsy.casemodule.services.FileManager;
import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.coreutils.ExecUtil;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProcessTerminator; import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProcessTerminator;
import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.datamodel.*; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Blackboard;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_ACCOUNT;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY;
import org.sleuthkit.datamodel.BlackboardAttribute;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_REFERRER;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ReadContentInputStream;
import org.sleuthkit.datamodel.TskCoreException;
/** /**
* Extracts activity from Internet Explorer browser, as well as recent documents * Extracts activity from Internet Explorer browser, as well as recent documents
@ -65,18 +81,23 @@ import org.sleuthkit.datamodel.*;
class ExtractIE extends Extract { class ExtractIE extends Extract {
private static final Logger logger = Logger.getLogger(ExtractIE.class.getName()); private static final Logger logger = Logger.getLogger(ExtractIE.class.getName());
private final IngestServices services = IngestServices.getInstance(); private static final String PARENT_MODULE_NAME
= NbBundle.getMessage(ExtractIE.class, "ExtractIE.parentModuleName.noSpace");
private static final String PASCO_DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
private final String moduleTempResultsDir; private final String moduleTempResultsDir;
private String PASCO_LIB_PATH; private final String JAVA_PATH = PlatformUtil.getJavaPath();
private final String JAVA_PATH;
private static final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
private Content dataSource; private Content dataSource;
private IngestJobContext context; private IngestJobContext context;
ExtractIE() throws NoCurrentCaseException { ExtractIE() throws NoCurrentCaseException {
moduleName = NbBundle.getMessage(ExtractIE.class, "ExtractIE.moduleName.text");
moduleTempResultsDir = RAImageIngestModule.getRATempPath(Case.getCurrentCaseThrows(), "IE") + File.separator + "results"; //NON-NLS moduleTempResultsDir = RAImageIngestModule.getRATempPath(Case.getCurrentCaseThrows(), "IE") + File.separator + "results"; //NON-NLS
JAVA_PATH = PlatformUtil.getJavaPath(); }
@Override
protected String getModuleName() {
return NbBundle.getMessage(ExtractIE.class, "ExtractIE.moduleName.text");
} }
@Override @Override
@ -93,7 +114,6 @@ class ExtractIE extends Extract {
* Finds the files storing bookmarks and creates artifacts * Finds the files storing bookmarks and creates artifacts
*/ */
private void getBookmark() { private void getBookmark() {
org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> favoritesFiles; List<AbstractFile> favoritesFiles;
try { try {
favoritesFiles = fileManager.findFiles(dataSource, "%.url", "Favorites"); //NON-NLS favoritesFiles = fileManager.findFiles(dataSource, "%.url", "Favorites"); //NON-NLS
@ -101,7 +121,7 @@ class ExtractIE extends Extract {
logger.log(Level.WARNING, "Error fetching 'url' files for Internet Explorer bookmarks.", ex); //NON-NLS logger.log(Level.WARNING, "Error fetching 'url' files for Internet Explorer bookmarks.", ex); //NON-NLS
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "ExtractIE.getBookmark.errMsg.errGettingBookmarks", NbBundle.getMessage(this.getClass(), "ExtractIE.getBookmark.errMsg.errGettingBookmarks",
this.getName())); this.getModuleName()));
return; return;
} }
@ -121,89 +141,73 @@ class ExtractIE extends Extract {
break; break;
} }
String url = getURLFromIEBookmarkFile(fav); Collection<BlackboardAttribute> bbattributes = Arrays.asList(
new BlackboardAttribute(
String name = fav.getName(); TSK_URL, PARENT_MODULE_NAME, getURLFromIEBookmarkFile(fav)),
Long datetime = fav.getCrtime(); new BlackboardAttribute(
String Tempdate = datetime.toString(); TSK_TITLE, PARENT_MODULE_NAME, fav.getName()),
datetime = Long.valueOf(Tempdate); new BlackboardAttribute(
String domain = Util.extractDomain(url); TSK_DATETIME_CREATED, PARENT_MODULE_NAME, fav.getCrtime()),
new BlackboardAttribute(
Collection<BlackboardAttribute> bbattributes = new ArrayList<>(); TSK_PROG_NAME, PARENT_MODULE_NAME,
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL, NbBundle.getMessage(this.getClass(), "ExtractIE.moduleName.text")),
NbBundle.getMessage(this.getClass(), new BlackboardAttribute(
"ExtractIE.parentModuleName.noSpace"), url)); TSK_DOMAIN, PARENT_MODULE_NAME, Util.extractDomain(getURLFromIEBookmarkFile(fav))));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE, try {
NbBundle.getMessage(this.getClass(), BlackboardArtifact bbart = fav.newArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK);
"ExtractIE.parentModuleName.noSpace"), name)); bbart.addAttributes(bbattributes);
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
NbBundle.getMessage(this.getClass(),
"ExtractIE.parentModuleName.noSpace"), datetime));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
NbBundle.getMessage(this.getClass(),
"ExtractIE.parentModuleName.noSpace"),
NbBundle.getMessage(this.getClass(), "ExtractIE.moduleName.text")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(),
"ExtractIE.parentModuleName.noSpace"), domain));
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK, fav, bbattributes);
if (bbart != null) {
bbartifacts.add(bbart); bbartifacts.add(bbart);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error while trying to create Internet Explorer bookmark artifact.", ex); //NON-NLS
this.addErrorMessage(
NbBundle.getMessage(Chrome.class, "ExtractIE.getBookmark.errMsg.errGettingBookmarks", //NON-NLS
this.getModuleName(), fav.getName()));
} }
} }
services.fireModuleDataEvent(new ModuleDataEvent( try {
NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName"), blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bbartifacts)); } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, "Error while trying to post Internet Explorer bookmark artifact.", ex); //NON-NLS
this.addErrorMessage(Bundle.Extractor_errPostingArtifacts(getModuleName()));
}
} }
private String getURLFromIEBookmarkFile(AbstractFile fav) { private String getURLFromIEBookmarkFile(AbstractFile fav) {
BufferedReader reader = new BufferedReader(new InputStreamReader(new ReadContentInputStream(fav))); String line;
String line, url = ""; try (BufferedReader reader = new BufferedReader(new InputStreamReader(new ReadContentInputStream(fav)));) {
try { while (null != (line = reader.readLine())) {
line = reader.readLine();
while (null != line) {
// The actual shortcut line we are interested in is of the // The actual shortcut line we are interested in is of the
// form URL=http://path/to/website // form URL=http://path/to/website
if (line.startsWith("URL")) { //NON-NLS if (line.startsWith("URL")) { //NON-NLS
url = line.substring(line.indexOf("=") + 1); return StringUtils.substringAfter(line, "="); //NON-NLS
break;
} }
line = reader.readLine();
} }
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.WARNING, "Failed to read from content: " + fav.getName(), ex); //NON-NLS logger.log(Level.WARNING, "Failed to read from content: " + fav.getName(), ex); //NON-NLS
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "ExtractIE.getURLFromIEBmkFile.errMsg", this.getName(), NbBundle.getMessage(this.getClass(), "ExtractIE.getURLFromIEBmkFile.errMsg", this.getModuleName(),
fav.getName())); fav.getName()));
} catch (IndexOutOfBoundsException ex) { } catch (IndexOutOfBoundsException ex) {
logger.log(Level.WARNING, "Failed while getting URL of IE bookmark. Unexpected format of the bookmark file: " + fav.getName(), ex); //NON-NLS logger.log(Level.WARNING, "Failed while getting URL of IE bookmark. Unexpected format of the bookmark file: " + fav.getName(), ex); //NON-NLS
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "ExtractIE.getURLFromIEBmkFile.errMsg2", this.getName(), NbBundle.getMessage(this.getClass(), "ExtractIE.getURLFromIEBmkFile.errMsg2", this.getModuleName(),
fav.getName())); fav.getName()));
} finally {
try {
reader.close();
} catch (IOException ex) {
logger.log(Level.WARNING, "Failed to close reader.", ex); //NON-NLS
}
} }
return url; return "";
} }
/** /**
* Finds files that store cookies and adds artifacts for them. * Finds files that store cookies and adds artifacts for them.
*/ */
private void getCookie() { private void getCookie() {
org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> cookiesFiles; List<AbstractFile> cookiesFiles;
try { try {
cookiesFiles = fileManager.findFiles(dataSource, "%.txt", "Cookies"); //NON-NLS cookiesFiles = fileManager.findFiles(dataSource, "%.txt", "Cookies"); //NON-NLS
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.WARNING, "Error getting cookie files for IE"); //NON-NLS logger.log(Level.WARNING, "Error getting cookie files for IE"); //NON-NLS
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "ExtractIE.getCookie.errMsg.errGettingFile", this.getName())); NbBundle.getMessage(this.getClass(), "ExtractIE.getCookie.errMsg.errGettingFile", this.getModuleName()));
return; return;
} }
@ -222,54 +226,56 @@ class ExtractIE extends Extract {
continue; continue;
} }
byte[] t = new byte[(int) cookiesFile.getSize()]; byte[] cookiesBuffer = new byte[(int) cookiesFile.getSize()];
try { try {
final int bytesRead = cookiesFile.read(t, 0, cookiesFile.getSize()); cookiesFile.read(cookiesBuffer, 0, cookiesFile.getSize());
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.WARNING, "Error reading bytes of Internet Explorer cookie.", ex); //NON-NLS logger.log(Level.WARNING, "Error reading bytes of Internet Explorer cookie.", ex); //NON-NLS
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "ExtractIE.getCookie.errMsg.errReadingIECookie", NbBundle.getMessage(this.getClass(), "ExtractIE.getCookie.errMsg.errReadingIECookie",
this.getName(), cookiesFile.getName())); this.getModuleName(), cookiesFile.getName()));
continue; continue;
} }
String cookieString = new String(t);
String[] values = cookieString.split("\n");
String url = values.length > 2 ? values[2] : "";
String value = values.length > 1 ? values[1] : "";
String name = values.length > 0 ? values[0] : "";
Long datetime = cookiesFile.getCrtime();
String tempDate = datetime.toString();
datetime = Long.valueOf(tempDate);
String domain = Util.extractDomain(url);
Collection<BlackboardAttribute> bbattributes = new ArrayList<>(); String[] values = new String(cookiesBuffer).split("\n");
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL, String URL = values.length > 2 ? values[2] : "";
NbBundle.getMessage(this.getClass(),
"ExtractIE.parentModuleName.noSpace"), url)); Collection<BlackboardAttribute> bbattributes = Arrays.asList(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, new BlackboardAttribute(
NbBundle.getMessage(this.getClass(), TSK_DATETIME, PARENT_MODULE_NAME,
"ExtractIE.parentModuleName.noSpace"), datetime)); cookiesFile.getCrtime()),
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, new BlackboardAttribute(
NbBundle.getMessage(this.getClass(), TSK_NAME, PARENT_MODULE_NAME,
"ExtractIE.parentModuleName.noSpace"), (name != null) ? name : "")); values.length > 0 ? values[0] : ""),
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, new BlackboardAttribute(
NbBundle.getMessage(this.getClass(), TSK_VALUE, PARENT_MODULE_NAME,
"ExtractIE.parentModuleName.noSpace"), value)); values.length > 1 ? values[1] : ""),
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, new BlackboardAttribute(
NbBundle.getMessage(this.getClass(), TSK_URL, PARENT_MODULE_NAME,
"ExtractIE.parentModuleName.noSpace"), URL),
NbBundle.getMessage(this.getClass(), "ExtractIE.moduleName.text"))); new BlackboardAttribute(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, TSK_PROG_NAME, PARENT_MODULE_NAME,
NbBundle.getMessage(this.getClass(), getModuleName()),
"ExtractIE.parentModuleName.noSpace"), domain)); new BlackboardAttribute(
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes); TSK_DOMAIN, PARENT_MODULE_NAME,
if (bbart != null) { Util.extractDomain(URL)));
try {
BlackboardArtifact bbart = cookiesFile.newArtifact(TSK_WEB_COOKIE);
bbart.addAttributes(bbattributes);
bbartifacts.add(bbart); bbartifacts.add(bbart);
} catch (TskCoreException ex) {
this.addErrorMessage(
NbBundle.getMessage(Chrome.class, "ExtractIE.getCookie.errMsg.errReadingIECookie", //NON-NLS
this.getModuleName(), cookiesFile.getName()));
} }
} }
services.fireModuleDataEvent(new ModuleDataEvent( try {
NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName"), blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE, bbartifacts)); } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, "Error while trying to post Internet Explorer cookie artifact.", ex); //NON-NLS
this.addErrorMessage(Bundle.Extractor_errPostingArtifacts(getModuleName()));
}
} }
/** /**
@ -277,12 +283,12 @@ class ExtractIE extends Extract {
*/ */
private void getHistory() { private void getHistory() {
logger.log(Level.INFO, "Pasco results path: {0}", moduleTempResultsDir); //NON-NLS logger.log(Level.INFO, "Pasco results path: {0}", moduleTempResultsDir); //NON-NLS
boolean foundHistory = false;
//TODO: Why are we getting the pasco library path for datasource we process?
final File pascoRoot = InstalledFileLocator.getDefault().locate("pasco2", ExtractIE.class.getPackage().getName(), false); //NON-NLS final File pascoRoot = InstalledFileLocator.getDefault().locate("pasco2", ExtractIE.class.getPackage().getName(), false); //NON-NLS
if (pascoRoot == null) { if (pascoRoot == null) {
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.unableToGetHist", this.getName())); NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.unableToGetHist", this.getModuleName()));
logger.log(Level.SEVERE, "Error finding pasco program "); //NON-NLS logger.log(Level.SEVERE, "Error finding pasco program "); //NON-NLS
return; return;
} }
@ -290,20 +296,20 @@ class ExtractIE extends Extract {
final String pascoHome = pascoRoot.getAbsolutePath(); final String pascoHome = pascoRoot.getAbsolutePath();
logger.log(Level.INFO, "Pasco2 home: {0}", pascoHome); //NON-NLS logger.log(Level.INFO, "Pasco2 home: {0}", pascoHome); //NON-NLS
PASCO_LIB_PATH = pascoHome + File.separator + "pasco2.jar" + File.pathSeparator //NON-NLS String pascoLibPath = pascoHome + File.separator + "pasco2.jar" + File.pathSeparator //NON-NLS
+ pascoHome + File.separator + "*"; + pascoHome + File.separator + "*";
File resultsDir = new File(moduleTempResultsDir); File resultsDir = new File(moduleTempResultsDir);
resultsDir.mkdirs(); resultsDir.mkdirs();
// get index.dat files // get index.dat files
org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager(); FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> indexFiles; List<AbstractFile> indexFiles;
try { try {
indexFiles = fileManager.findFiles(dataSource, "index.dat"); //NON-NLS indexFiles = fileManager.findFiles(dataSource, "index.dat"); //NON-NLS
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.errGettingHistFiles", this.addErrorMessage(NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.errGettingHistFiles",
this.getName())); this.getModuleName()));
logger.log(Level.WARNING, "Error fetching 'index.data' files for Internet Explorer history."); //NON-NLS logger.log(Level.WARNING, "Error fetching 'index.data' files for Internet Explorer history."); //NON-NLS
return; return;
} }
@ -315,18 +321,21 @@ class ExtractIE extends Extract {
} }
dataFound = true; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>(); boolean foundHistory = false;
String temps; Collection<BlackboardArtifact> historyArtifacts = new ArrayList<>();
String indexFileName; Collection<BlackboardArtifact> accountArtifacts = new ArrayList<>();
for (AbstractFile indexFile : indexFiles) { for (AbstractFile indexFile : indexFiles) {
// Since each result represent an index.dat file, /* Since each result represent an index.dat file, just create these
// just create these files with the following notation: * files with the following notation: index<Number>.dat (i.e.
// index<Number>.dat (i.e. index0.dat, index1.dat,..., indexN.dat) * index0.dat, index1.dat,..., indexN.dat) Write each index.dat file
// Write each index.dat file to a temp directory. * to a temp directory.
//BlackboardArtifact bbart = fsc.newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY); *
indexFileName = "index" + Integer.toString((int) indexFile.getId()) + ".dat"; //NON-NLS * TODO: this comment is not accurate. It implies we use an
//indexFileName = "index" + Long.toString(bbart.getArtifactID()) + ".dat"; * sequential id number but actualy we use the file id from the db.
temps = RAImageIngestModule.getRATempPath(currentCase, "IE") + File.separator + indexFileName; //NON-NLS */
String indexFileName = "index" + indexFile.getId() + ".dat"; //NON-NLS
String temps = RAImageIngestModule.getRATempPath(currentCase, "IE") + File.separator + indexFileName; //NON-NLS
File datFile = new File(temps); File datFile = new File(temps);
if (context.dataSourceIngestIsCancelled()) { if (context.dataSourceIngestIsCancelled()) {
break; break;
@ -336,39 +345,48 @@ class ExtractIE extends Extract {
} catch (IOException e) { } catch (IOException e) {
logger.log(Level.WARNING, "Error while trying to write index.dat file " + datFile.getAbsolutePath(), e); //NON-NLS logger.log(Level.WARNING, "Error while trying to write index.dat file " + datFile.getAbsolutePath(), e); //NON-NLS
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.errWriteFile", this.getName(), NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.errWriteFile", this.getModuleName(),
datFile.getAbsolutePath())); datFile.getAbsolutePath()));
continue; continue;
} }
String filename = "pasco2Result." + indexFile.getId() + ".txt"; //NON-NLS String filename = "pasco2Result." + indexFile.getId() + ".txt"; //NON-NLS
boolean bPascProcSuccess = executePasco(temps, filename); boolean bPascProcSuccess = executePasco(pascoLibPath, temps, filename);
if (context.dataSourceIngestIsCancelled()) { if (context.dataSourceIngestIsCancelled()) {
return; return;
} }
//At this point pasco2 proccessed the index files. //At this point pasco2 proccessed the index file.
//Now fetch the results, parse them and the delete the files. //Now fetch the results, parse them and the delete the file.
if (bPascProcSuccess) { if (bPascProcSuccess) {
// Don't add TSK_OS_ACCOUNT artifacts to the ModuleDataEvent // Don't add TSK_OS_ACCOUNT artifacts to the ModuleDataEvent
bbartifacts.addAll(parsePascoOutput(indexFile, filename).stream() HashMultimap<ARTIFACT_TYPE, BlackboardArtifact> artifacts = parsePascoOutput(indexFile, filename);
.filter(bbart -> bbart.getArtifactTypeID() == ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID()) historyArtifacts.addAll(artifacts.get(TSK_WEB_HISTORY));
.collect(Collectors.toList())); accountArtifacts.addAll(artifacts.get(TSK_OS_ACCOUNT));
foundHistory = true; foundHistory = true;
//Delete index<n>.dat file since it was succcessfully by Pasco //Delete index<n>.dat file since it was succcessfully parsed by Pasco
datFile.delete(); datFile.delete();
} else { } else {
logger.log(Level.WARNING, "pasco execution failed on: {0}", this.getName()); //NON-NLS logger.log(Level.WARNING, "pasco execution failed on: {0}", this.getModuleName()); //NON-NLS
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.errProcHist", this.getName())); NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.errProcHist", this.getModuleName()));
} }
} }
if (foundHistory) { if (foundHistory) {
services.fireModuleDataEvent(new ModuleDataEvent( try {
NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName"), blackboard.postArtifacts(historyArtifacts, PARENT_MODULE_NAME);
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, bbartifacts)); } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, "Error while trying to post Internet Explorer history artifact.", ex); //NON-NLS
this.addErrorMessage(Bundle.Extractor_errPostingArtifacts(getModuleName()));
}
try {
blackboard.postArtifacts(accountArtifacts, PARENT_MODULE_NAME);
} catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, "Error while trying to post Internet Explorer os account artifact.", ex); //NON-NLS
this.addErrorMessage(Bundle.Extractor_errPostingArtifacts(getModuleName()));
}
} }
} }
@ -378,22 +396,22 @@ class ExtractIE extends Extract {
* @param indexFilePath Path to local index.dat file to analyze * @param indexFilePath Path to local index.dat file to analyze
* @param outputFileName Name of file to save output to * @param outputFileName Name of file to save output to
* *
* @return false on error * @return the boolean
*/ */
private boolean executePasco(String indexFilePath, String outputFileName) { private boolean executePasco(String pascoLibraryPath, String indexFilePath, String outputFileName) {
boolean success = true; boolean success = true;
try { try {
final String outputFileFullPath = moduleTempResultsDir + File.separator + outputFileName; final String outputFileFullPath = moduleTempResultsDir + File.separator + outputFileName;
final String errFileFullPath = moduleTempResultsDir + File.separator + outputFileName + ".err"; //NON-NLS final String errFileFullPath = moduleTempResultsDir + File.separator + outputFileName + ".err"; //NON-NLS
logger.log(Level.INFO, "Writing pasco results to: {0}", outputFileFullPath); //NON-NLS logger.log(Level.INFO, "Writing pasco results to: {0}", outputFileFullPath); //NON-NLS
List<String> commandLine = new ArrayList<>(); List<String> commandLine = Arrays.asList(
commandLine.add(JAVA_PATH); JAVA_PATH,
commandLine.add("-cp"); //NON-NLS "-cp",//NON-NLS
commandLine.add(PASCO_LIB_PATH); pascoLibraryPath,
commandLine.add("isi.pasco2.Main"); //NON-NLS "isi.pasco2.Main", //NON-NLS
commandLine.add("-T"); //NON-NLS "-T", //NON-NLS
commandLine.add("history"); //NON-NLS "history", //NON-NLS
commandLine.add(indexFilePath); indexFilePath);
ProcessBuilder processBuilder = new ProcessBuilder(commandLine); ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
processBuilder.redirectOutput(new File(outputFileFullPath)); processBuilder.redirectOutput(new File(outputFileFullPath));
processBuilder.redirectError(new File(errFileFullPath)); processBuilder.redirectError(new File(errFileFullPath));
@ -424,15 +442,15 @@ class ExtractIE extends Extract {
* *
* @return A collection of created artifacts * @return A collection of created artifacts
*/ */
private Collection<BlackboardArtifact> parsePascoOutput(AbstractFile origFile, String pascoOutputFileName) { private HashMultimap<BlackboardArtifact.ARTIFACT_TYPE, BlackboardArtifact> parsePascoOutput(AbstractFile origFile, String pascoOutputFileName) {
HashMultimap<BlackboardArtifact.ARTIFACT_TYPE, BlackboardArtifact> bbartifacts = HashMultimap.create();
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
String fnAbs = moduleTempResultsDir + File.separator + pascoOutputFileName; String fnAbs = moduleTempResultsDir + File.separator + pascoOutputFileName;
File file = new File(fnAbs); File file = new File(fnAbs);
if (file.exists() == false) { if (file.exists() == false) {
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.notFound", this.getName(), NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.notFound", this.getModuleName(),
file.getName())); file.getName()));
logger.log(Level.WARNING, "Pasco Output not found: {0}", file.getPath()); //NON-NLS logger.log(Level.WARNING, "Pasco Output not found: {0}", file.getPath()); //NON-NLS
return bbartifacts; return bbartifacts;
@ -443,21 +461,11 @@ class ExtractIE extends Extract {
if (file.length() == 0) { if (file.length() == 0) {
return bbartifacts; return bbartifacts;
} }
try (Scanner fileScanner = new Scanner(new FileInputStream(file.toString()));) {
Scanner fileScanner; // Keep a list of reported user accounts to avoid repeats.
try { // Initialize it with the empty string to represent an unknown user.
fileScanner = new Scanner(new FileInputStream(file.toString())); Set<String> reportedUserAccounts = Sets.newHashSet("");
} catch (FileNotFoundException ex) {
this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.errParsing", this.getName(),
file.getName()));
logger.log(Level.WARNING, "Unable to find the Pasco file at " + file.getPath(), ex); //NON-NLS
return bbartifacts;
}
// Keep a list of reported user accounts to avoid repeats
Set<String> reportedUserAccounts = new HashSet<>();
while (fileScanner.hasNext()) { while (fileScanner.hasNext()) {
String line = fileScanner.nextLine(); String line = fileScanner.nextLine();
if (!line.startsWith("URL")) { //NON-NLS if (!line.startsWith("URL")) { //NON-NLS
@ -486,7 +494,7 @@ class ExtractIE extends Extract {
user = url[0]; user = url[0];
user = user.replace("Visited:", ""); //NON-NLS user = user.replace("Visited:", ""); //NON-NLS
user = user.replace(":Host:", ""); //NON-NLS user = user.replace(":Host:", ""); //NON-NLS
user = user.replaceAll("(:)(.*?)(:)", ""); user = user.replaceAll(":(.*?):", "");
user = user.trim(); user = user.trim();
realurl = url[1]; realurl = url[1];
realurl = realurl.replace("Visited:", ""); //NON-NLS realurl = realurl.replace("Visited:", ""); //NON-NLS
@ -502,64 +510,69 @@ class ExtractIE extends Extract {
if (!actime.isEmpty()) { if (!actime.isEmpty()) {
try { try {
Long epochtime = dateFormatter.parse(actime).getTime(); Long epochtime = new SimpleDateFormat(PASCO_DATE_FORMAT).parse(actime).getTime();
ftime = epochtime / 1000; ftime = epochtime / 1000;
} catch (ParseException e) { } catch (ParseException e) {
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.errParsingEntry", NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.errParsingEntry",
this.getName())); this.getModuleName()));
logger.log(Level.WARNING, String.format("Error parsing Pasco results, may have partial processing of corrupt file (id=%d)", origFile.getId()), e); //NON-NLS logger.log(Level.WARNING, String.format("Error parsing Pasco results, may have partial processing of corrupt file (id=%d)", origFile.getId()), e); //NON-NLS
} }
} }
Collection<BlackboardAttribute> bbattributes = Arrays.asList(
new BlackboardAttribute(
TSK_URL, PARENT_MODULE_NAME,
realurl),
new BlackboardAttribute(
TSK_DATETIME_ACCESSED, PARENT_MODULE_NAME,
ftime),
//TODO: why are we adding an attribute that is always blank?
new BlackboardAttribute(
TSK_REFERRER, PARENT_MODULE_NAME,
""),
// @@@ NOte that other browser modules are adding TITLE in here for the title
new BlackboardAttribute(
TSK_PROG_NAME, PARENT_MODULE_NAME,
getModuleName()),
new BlackboardAttribute(
TSK_DOMAIN, PARENT_MODULE_NAME,
domain),
new BlackboardAttribute(
TSK_USER_NAME, PARENT_MODULE_NAME,
user));
try { try {
BlackboardArtifact bbart = origFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY); BlackboardArtifact bbart = origFile.newArtifact(TSK_WEB_HISTORY);
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
NbBundle.getMessage(this.getClass(),
"ExtractIE.parentModuleName.noSpace"), realurl));
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", EscapeUtil.decodeURL(realurl)));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
NbBundle.getMessage(this.getClass(),
"ExtractIE.parentModuleName.noSpace"), ftime));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER,
NbBundle.getMessage(this.getClass(),
"ExtractIE.parentModuleName.noSpace"), ""));
// @@@ NOte that other browser modules are adding TITLE in hre for the title
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
NbBundle.getMessage(this.getClass(),
"ExtractIE.parentModuleName.noSpace"),
NbBundle.getMessage(this.getClass(),
"ExtractIE.moduleName.text")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(),
"ExtractIE.parentModuleName.noSpace"), domain));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
NbBundle.getMessage(this.getClass(),
"ExtractIE.parentModuleName.noSpace"), user));
bbart.addAttributes(bbattributes); bbart.addAttributes(bbattributes);
bbartifacts.put(TSK_WEB_HISTORY, bbart);
// index the artifact for keyword search
this.indexArtifact(bbart);
bbartifacts.add(bbart);
if ((!user.isEmpty()) && (!reportedUserAccounts.contains(user))) {
BlackboardArtifact osAttr = origFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
osAttr.addAttribute(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName.noSpace"), user));
// index the artifact for keyword search
this.indexArtifact(osAttr);
bbartifacts.add(osAttr);
reportedUserAccounts.add(user);
}
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error writing Internet Explorer web history artifact to the blackboard.", ex); //NON-NLS logger.log(Level.SEVERE, "Error while trying to create Internet Explorer history artifact.", ex); //NON-NLS
this.addErrorMessage(
NbBundle.getMessage(Chrome.class, "ExtractIE.getHistory.errMsg.errProcHist", //NON-NLS
origFile.getName()));
}
if (reportedUserAccounts.contains(user) == false) {
try {
BlackboardArtifact osAttr = origFile.newArtifact(TSK_OS_ACCOUNT);
osAttr.addAttribute(new BlackboardAttribute(TSK_USER_NAME, PARENT_MODULE_NAME, user));
bbartifacts.put(TSK_OS_ACCOUNT, osAttr);
reportedUserAccounts.add(user);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error while trying to create Internet Explorer os account artifact.", ex); //NON-NLS
this.addErrorMessage(
NbBundle.getMessage(Chrome.class, "ExtractIE.getHistory.errMsg.errProcHist", //NON-NLS
origFile.getName()));
} }
} }
fileScanner.close(); }
return bbartifacts;
} catch (FileNotFoundException ex) {
this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.errParsing", this.getModuleName(),
file.getName()));
logger.log(Level.WARNING, "Unable to find the Pasco file at " + file.getPath(), ex); //NON-NLS
return bbartifacts; return bbartifacts;
} }
}
} }

View File

@ -22,8 +22,16 @@
*/ */
package org.sleuthkit.autopsy.recentactivity; package org.sleuthkit.autopsy.recentactivity;
import java.io.*; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringReader;
import java.nio.file.Path;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.*; import java.util.*;
@ -32,30 +40,62 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import org.openide.modules.InstalledFileLocator; import org.openide.modules.InstalledFileLocator;
import org.openide.util.Lookup;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.services.FileManager;
import org.sleuthkit.autopsy.coreutils.ExecUtil; import org.sleuthkit.autopsy.coreutils.ExecUtil;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProcessTerminator; import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProcessTerminator;
import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException;
import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
import org.sleuthkit.autopsy.recentactivity.UsbDeviceIdMapper.USBInfo; import org.sleuthkit.autopsy.recentactivity.UsbDeviceIdMapper.USBInfo;
import org.sleuthkit.datamodel.*; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Blackboard;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_ACCOUNT;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_OS_INFO;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_REMOTE_DRIVE;
import org.sleuthkit.datamodel.BlackboardAttribute;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_ID;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_MAKE;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_MODEL;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCAL_PATH;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ORGANIZATION;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_OWNER;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PRODUCT_ID;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_REMOTE_PATH;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEMP_DIR;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_ID;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VERSION;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
import org.sleuthkit.datamodel.Report;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import java.nio.file.Path;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException;
import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
/** /**
* Extract windows registry data using regripper. Runs two versions of * Extract windows registry data using regripper. Runs two versions of
@ -69,92 +109,93 @@ import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamExce
}) })
class ExtractRegistry extends Extract { class ExtractRegistry extends Extract {
private final Logger logger = Logger.getLogger(this.getClass().getName()); private static final Logger logger = Logger.getLogger(ExtractRegistry.class.getName());
private String RR_PATH; private final static String PARENT_MODULE_NAME = NbBundle.getMessage(ExtractRegistry.class, "ExtractRegistry.parentModuleName.noSpace");
private String RR_FULL_PATH;
private Path rrHome; // Path to the Autopsy version of RegRipper
private Path rrFullHome; // Path to the full version of RegRipper
private Content dataSource;
private IngestJobContext context;
final private static UsbDeviceIdMapper USB_MAPPER = new UsbDeviceIdMapper(); final private static UsbDeviceIdMapper USB_MAPPER = new UsbDeviceIdMapper();
final private static String RIP_EXE = "rip.exe"; final private static String RIP_EXE = "rip.exe";
final private static String RIP_PL = "rip.pl"; final private static String RIP_PL = "rip.pl";
private final List<String> rrCmd = new ArrayList<>(); final private static ImmutableList<String> REG_FILE_NAMES = ImmutableList.of("system", "software", "security", "sam"); //NON-NLS
private final List<String> rrFullCmd= new ArrayList<>(); private final Path rrHome; // Path to the Autopsy version of RegRipper
private final Path rrFullHome; // Path to the full version of RegRipper
private Content dataSource;
private IngestJobContext context;
private final List<String> rrCmd = new ArrayList<>();
private final List<String> rrFullCmd = new ArrayList<>();
ExtractRegistry() throws IngestModuleException { ExtractRegistry() throws IngestModuleException {
moduleName = NbBundle.getMessage(ExtractIE.class, "ExtractRegistry.moduleName.text"); InstalledFileLocator installedFileLocator = InstalledFileLocator.getDefault();
final File rrRoot = installedFileLocator.locate("rr", ExtractRegistry.class.getPackage().getName(), false); //NON-NLS
final File rrRoot = InstalledFileLocator.getDefault().locate("rr", ExtractRegistry.class.getPackage().getName(), false); //NON-NLS
if (rrRoot == null) { if (rrRoot == null) {
throw new IngestModuleException(Bundle.RegRipperNotFound()); throw new IngestModuleException(Bundle.RegRipperNotFound());
} }
final File rrFullRoot = installedFileLocator.locate("rr-full", ExtractRegistry.class.getPackage().getName(), false); //NON-NLS
final File rrFullRoot = InstalledFileLocator.getDefault().locate("rr-full", ExtractRegistry.class.getPackage().getName(), false); //NON-NLS
if (rrFullRoot == null) { if (rrFullRoot == null) {
throw new IngestModuleException(Bundle.RegRipperFullNotFound()); throw new IngestModuleException(Bundle.RegRipperFullNotFound());
} }
String executableToRun = RIP_EXE; String executableToRun = PlatformUtil.isWindowsOS() ? RIP_EXE : RIP_PL;
if (!PlatformUtil.isWindowsOS()) {
executableToRun = RIP_PL;
}
rrHome = rrRoot.toPath();
RR_PATH = rrHome.resolve(executableToRun).toString();
rrFullHome = rrFullRoot.toPath();
RR_FULL_PATH = rrFullHome.resolve(executableToRun).toString();
if (!(new File(RR_PATH).exists())) { rrHome = rrRoot.toPath();
String rrPath = rrHome.resolve(executableToRun).toString();
if (!(new File(rrPath).exists())) {
throw new IngestModuleException(Bundle.RegRipperNotFound()); throw new IngestModuleException(Bundle.RegRipperNotFound());
} }
if (!(new File(RR_FULL_PATH).exists())) { rrFullHome = rrFullRoot.toPath();
String rrFullPath = rrFullHome.resolve(executableToRun).toString();
if (!(new File(rrFullPath).exists())) {
throw new IngestModuleException(Bundle.RegRipperFullNotFound()); throw new IngestModuleException(Bundle.RegRipperFullNotFound());
} }
if(PlatformUtil.isWindowsOS()){ if (PlatformUtil.isWindowsOS()) {
rrCmd.add(RR_PATH); rrCmd.add(rrPath);
rrFullCmd.add(RR_FULL_PATH); rrFullCmd.add(rrFullPath);
}else{ } else {
String perl; String perl;
File usrBin = new File("/usr/bin/perl"); File usrBin = new File("/usr/bin/perl");
File usrLocalBin = new File("/usr/local/bin/perl"); File usrLocalBin = new File("/usr/local/bin/perl");
if(usrBin.canExecute() && usrBin.exists() && !usrBin.isDirectory()){ if (usrBin.canExecute() && usrBin.exists() && !usrBin.isDirectory()) {
perl = "/usr/bin/perl"; perl = "/usr/bin/perl";
}else if(usrLocalBin.canExecute() && usrLocalBin.exists() && !usrLocalBin.isDirectory()){ } else if (usrLocalBin.canExecute() && usrLocalBin.exists() && !usrLocalBin.isDirectory()) {
perl = "/usr/local/bin/perl"; perl = "/usr/local/bin/perl";
}else{ } else {
throw new IngestModuleException("perl not found in your system"); throw new IngestModuleException("perl not found in your system");
} }
rrCmd.add(perl); rrCmd.add(perl);
rrCmd.add(RR_PATH); rrCmd.add(rrPath);
rrFullCmd.add(perl); rrFullCmd.add(perl);
rrFullCmd.add(RR_FULL_PATH); rrFullCmd.add(rrFullPath);
} }
} }
@Override
protected String getModuleName() {
return NbBundle.getMessage(ExtractRegistry.class, "ExtractRegistry.moduleName.text");
}
/** /**
* Search for the registry hives on the system. * Search for the registry hives on the system.
*/ */
private List<AbstractFile> findRegistryFiles() { private List<AbstractFile> findRegistryFiles() {
List<AbstractFile> allRegistryFiles = new ArrayList<>(); List<AbstractFile> allRegistryFiles = new ArrayList<>();
org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager(); FileManager fileManager = currentCase.getServices().getFileManager();
// find the user-specific ntuser-dat files // find the user-specific ntuser-dat files
try { try {
allRegistryFiles.addAll(fileManager.findFiles(dataSource, "ntuser.dat")); //NON-NLS allRegistryFiles.addAll(fileManager.findFiles(dataSource, "ntuser.dat")); //NON-NLS
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.WARNING, "Error fetching 'ntuser.dat' file."); //NON-NLS logger.log(Level.WARNING, "Error fetching 'ntuser.dat' file.", ex); //NON-NLS
} }
// find the system hives' // find the system hives'
String[] regFileNames = new String[]{"system", "software", "security", "sam"}; //NON-NLS for (String regFileName : REG_FILE_NAMES) {
for (String regFileName : regFileNames) {
try { try {
allRegistryFiles.addAll(fileManager.findFiles(dataSource, regFileName, "/system32/config")); //NON-NLS allRegistryFiles.addAll(fileManager.findFiles(dataSource, regFileName, "/system32/config")); //NON-NLS
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
String msg = NbBundle.getMessage(this.getClass(), String msg = NbBundle.getMessage(ExtractRegistry.class,
"ExtractRegistry.findRegFiles.errMsg.errReadingFile", regFileName); "ExtractRegistry.findRegFiles.errMsg.errReadingFile", regFileName);
logger.log(Level.WARNING, msg); logger.log(Level.WARNING, msg, ex);
this.addErrorMessage(this.getName() + ": " + msg); this.addErrorMessage(this.getModuleName() + ": " + msg);
} }
} }
return allRegistryFiles; return allRegistryFiles;
@ -167,6 +208,7 @@ class ExtractRegistry extends Extract {
private void analyzeRegistryFiles() { private void analyzeRegistryFiles() {
List<AbstractFile> allRegistryFiles = findRegistryFiles(); List<AbstractFile> allRegistryFiles = findRegistryFiles();
//TODO: The handleing of the log file seems odd
// open the log file // open the log file
FileWriter logFile = null; FileWriter logFile = null;
try { try {
@ -188,14 +230,14 @@ class ExtractRegistry extends Extract {
regFile.getName(), regFileId), ex); //NON-NLS regFile.getName(), regFileId), ex); //NON-NLS
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp", NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
this.getName(), regFileName)); this.getModuleName(), regFileName));
continue; continue;
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Error writing temp registry file '%s' for registry file '%s' (id=%d).", logger.log(Level.SEVERE, String.format("Error writing temp registry file '%s' for registry file '%s' (id=%d).",
regFileNameLocal, regFile.getName(), regFileId), ex); //NON-NLS regFileNameLocal, regFile.getName(), regFileId), ex); //NON-NLS
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp", NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
this.getName(), regFileName)); this.getModuleName(), regFileName));
continue; continue;
} }
@ -211,7 +253,7 @@ class ExtractRegistry extends Extract {
logger.log(Level.SEVERE, null, ex); logger.log(Level.SEVERE, null, ex);
} }
logger.log(Level.INFO, "{0}- Now getting registry information from {1}", new Object[]{moduleName, regFileNameLocal}); //NON-NLS logger.log(Level.INFO, "{0}- Now getting registry information from {1}", new Object[]{getModuleName(), regFileNameLocal}); //NON-NLS
RegOutputFiles regOutputFiles = ripRegistryFile(regFileNameLocal, outputPathBase); RegOutputFiles regOutputFiles = ripRegistryFile(regFileNameLocal, outputPathBase);
if (context.dataSourceIngestIsCancelled()) { if (context.dataSourceIngestIsCancelled()) {
break; break;
@ -222,12 +264,12 @@ class ExtractRegistry extends Extract {
if (parseAutopsyPluginOutput(regOutputFiles.autopsyPlugins, regFile) == false) { if (parseAutopsyPluginOutput(regOutputFiles.autopsyPlugins, regFile) == false) {
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.failedParsingResults", NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.failedParsingResults",
this.getName(), regFileName)); this.getModuleName(), regFileName));
} }
} }
// create a report for the full output // create a report for the full output
if (!regOutputFiles.fullPlugins.isEmpty()) { if (regOutputFiles.fullPlugins.isEmpty() == false) {
try { try {
Report report = currentCase.addReport(regOutputFiles.fullPlugins, Report report = currentCase.addReport(regOutputFiles.fullPlugins,
NbBundle.getMessage(this.getClass(), "ExtractRegistry.parentModuleName.noSpace"), NbBundle.getMessage(this.getClass(), "ExtractRegistry.parentModuleName.noSpace"),
@ -318,7 +360,7 @@ class ExtractRegistry extends Extract {
private void executeRegRipper(List<String> regRipperPath, Path regRipperHomeDir, String hiveFilePath, String hiveFileType, String outputFile, String errFile) { private void executeRegRipper(List<String> regRipperPath, Path regRipperHomeDir, String hiveFilePath, String hiveFileType, String outputFile, String errFile) {
try { try {
List<String> commandLine = new ArrayList<>(); List<String> commandLine = new ArrayList<>();
for(String cmd: regRipperPath){ for (String cmd : regRipperPath) {
commandLine.add(cmd); commandLine.add(cmd);
} }
commandLine.add("-r"); //NON-NLS commandLine.add("-r"); //NON-NLS
@ -333,7 +375,7 @@ class ExtractRegistry extends Extract {
ExecUtil.execute(processBuilder, new DataSourceIngestModuleProcessTerminator(context)); ExecUtil.execute(processBuilder, new DataSourceIngestModuleProcessTerminator(context));
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.SEVERE, "Unable to run RegRipper", ex); //NON-NLS logger.log(Level.SEVERE, "Unable to run RegRipper", ex); //NON-NLS
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName())); this.addErrorMessage(NbBundle.getMessage(this.getClass(), "ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getModuleName()));
} }
} }
@ -341,19 +383,16 @@ class ExtractRegistry extends Extract {
/** /**
* *
* @param regFilePath Path to the output file produced by RegRipper. * @param regFilePath Path to the output file produced by RegRipper.
* @param regFile File object for registry that we are parsing (to make * @param regAbstractFile File object for registry that we are parsing (to
* blackboard artifacts with) * make blackboard artifacts with)
* *
* @return * @return
*/ */
private boolean parseAutopsyPluginOutput(String regFilePath, AbstractFile regFile) { private boolean parseAutopsyPluginOutput(String regFilePath, AbstractFile regAbstractFile) {
FileInputStream fstream = null; SleuthkitCase caseDB = currentCase.getSleuthkitCase();
try {
SleuthkitCase tempDb = currentCase.getSleuthkitCase();
// Read the file in and create a Document and elements // Read the file in and create a Document and elements
File regfile = new File(regFilePath); try (FileInputStream fstream = new FileInputStream(regFilePath);) {
fstream = new FileInputStream(regfile);
String regString = new Scanner(fstream, "UTF-8").useDelimiter("\\Z").next(); //NON-NLS String regString = new Scanner(fstream, "UTF-8").useDelimiter("\\Z").next(); //NON-NLS
String startdoc = "<?xml version=\"1.0\"?><document>"; //NON-NLS String startdoc = "<?xml version=\"1.0\"?><document>"; //NON-NLS
@ -372,6 +411,7 @@ class ExtractRegistry extends Extract {
Element oroot = doc.getDocumentElement(); Element oroot = doc.getDocumentElement();
NodeList children = oroot.getChildNodes(); NodeList children = oroot.getChildNodes();
int len = children.getLength(); int len = children.getLength();
// Add all "usb" dataType nodes to collection of BlackboardArtifacts // Add all "usb" dataType nodes to collection of BlackboardArtifacts
// that we will submit in a ModuleDataEvent for additional processing. // that we will submit in a ModuleDataEvent for additional processing.
Collection<BlackboardArtifact> usbBBartifacts = new ArrayList<>(); Collection<BlackboardArtifact> usbBBartifacts = new ArrayList<>();
@ -379,23 +419,17 @@ class ExtractRegistry extends Extract {
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
Element tempnode = (Element) children.item(i); Element tempnode = (Element) children.item(i);
String dataType = tempnode.getNodeName();
NodeList timenodes = tempnode.getElementsByTagName("mtime"); //NON-NLS NodeList timenodes = tempnode.getElementsByTagName("mtime"); //NON-NLS
Long mtime = null; Long mtime = null;
if (timenodes.getLength() > 0) { if (timenodes.getLength() > 0) {
Element timenode = (Element) timenodes.item(0); String etime = timenodes.item(0).getTextContent();
String etime = timenode.getTextContent();
try { try {
Long epochtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(etime).getTime(); Long epochtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(etime).getTime();
mtime = epochtime; mtime = epochtime / 1000;
String Tempdate = mtime.toString();
mtime = Long.valueOf(Tempdate) / 1000;
} catch (ParseException ex) { } catch (ParseException ex) {
logger.log(Level.WARNING, "Failed to parse epoch time when parsing the registry."); //NON-NLS logger.log(Level.WARNING, "Failed to parse epoch time when parsing the registry."); //NON-NLS
} }
} }
NodeList artroots = tempnode.getElementsByTagName("artifacts"); //NON-NLS NodeList artroots = tempnode.getElementsByTagName("artifacts"); //NON-NLS
if (artroots.getLength() == 0) { if (artroots.getLength() == 0) {
// If there isn't an artifact node, skip this entry // If there isn't an artifact node, skip this entry
@ -404,12 +438,293 @@ class ExtractRegistry extends Extract {
Element artroot = (Element) artroots.item(0); Element artroot = (Element) artroots.item(0);
NodeList myartlist = artroot.getChildNodes(); NodeList myartlist = artroot.getChildNodes();
String parentModuleName = NbBundle.getMessage(this.getClass(), "ExtractRegistry.parentModuleName.noSpace");
String winver = "";
String dataType = tempnode.getNodeName();
// If all artifact nodes should really go under one Blackboard artifact, need to process it differently // If all artifact nodes should really go under one Blackboard artifact, need to process it differently
switch (dataType) { switch (dataType) {
case "WinVersion": //NON-NLS case "WinVersion":
processWinVersion(myartlist, caseDB, regAbstractFile);
break;
case "Profiler":
processProfiler(myartlist, caseDB, regAbstractFile);
break;
case "CompName":
processCompName(myartlist, caseDB, regAbstractFile);
break;
default:
processOtherDataType(myartlist, dataType, regAbstractFile, usbBBartifacts, mtime);
break;
}
} // for
//TODO: why do we only send module data events for USB artifacts
if (!usbBBartifacts.isEmpty()) {
try {
blackboard.postArtifacts(usbBBartifacts, PARENT_MODULE_NAME);
} catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, "Error while trying to post usb device artifact.", ex); //NON-NLS
this.addErrorMessage(Bundle.Extractor_errPostingArtifacts(getModuleName()));
}
}
return true;
} catch (FileNotFoundException ex) {
logger.log(Level.SEVERE, "Error finding the registry file."); //NON-NLS
} catch (SAXException ex) {
logger.log(Level.SEVERE, "Error parsing the registry XML: {0}", ex); //NON-NLS
} catch (IOException ex) {
logger.log(Level.SEVERE, "Error building the document parser: {0}", ex); //NON-NLS
} catch (ParserConfigurationException ex) {
logger.log(Level.SEVERE, "Error configuring the registry parser: {0}", ex); //NON-NLS
}
return false;
}
private void processOtherDataType(NodeList myartlist, String dataType, AbstractFile regAbstractFile, Collection<BlackboardArtifact> usbBBartifacts, Long mtime) throws IllegalArgumentException, DOMException {
for (int j = 0; j < myartlist.getLength(); j++) {
Node artchild = myartlist.item(j);
// If it has attributes, then it is an Element (based off API)
if (artchild.hasAttributes()) {
Element artnode = (Element) artchild;
String value = artnode.getTextContent().trim();
switch (dataType) {
case "recentdocs": //NON-NLS
// BlackboardArtifact bbart = tempDb.getContentById(orgId).newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
// bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", dataType, mtime));
// bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity", dataType, mtimeItem));
// bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), "RecentActivity", dataType, value));
// bbart.addAttributes(bbattributes);
// @@@ BC: Why are we ignoring this...
break;
case "usb"://NON-NLS
processUSB(artnode, regAbstractFile, value, usbBBartifacts);
break;
case "uninstall"://NON-NLS
processUninstall(artnode, value, regAbstractFile);
break;
case "office"://NON-NLS
processOffice(artnode, regAbstractFile, mtime, value);
break;
case "ProcessorArchitecture": //NON-NLS
// Architecture is now included under Profiler
break;
case "ProfileList"://NON-NLS
processProfileList(value, artnode, regAbstractFile);
break;
case "NtuserNetwork"://NON-NLS
processNtuserNetwork(artnode, value, regAbstractFile);
break;
case "shellfolders": // NON-NLS
// The User Shell Folders subkey stores the paths to Windows Explorer folders for the current user of the computer
// (https://technet.microsoft.com/en-us/library/Cc962613.aspx).
// No useful information. Skip.
break;
default:
logger.log(Level.WARNING, "Unrecognized node name: {0}", dataType); //NON-NLS
break;
}
}
}
}
private void processNtuserNetwork(Element artnode, String remoteName, AbstractFile regAbstractFile) throws IllegalArgumentException {
try {
List<BlackboardAttribute> bbattributes = Arrays.asList(
new BlackboardAttribute(TSK_LOCAL_PATH, PARENT_MODULE_NAME,
artnode.getAttribute("localPath")), //NON-NLS
new BlackboardAttribute(TSK_REMOTE_PATH, PARENT_MODULE_NAME,
remoteName));
BlackboardArtifact bbart = regAbstractFile.newArtifact(TSK_REMOTE_DRIVE);
bbart.addAttributes(bbattributes);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error adding network drive artifact to blackboard."); //NON-NLS
}
}
private void processProfileList(String homeDir, Element artnode, AbstractFile regAbstractFile) throws IllegalArgumentException {
try {
List<BlackboardAttribute> bbattributes = Arrays.asList(
new BlackboardAttribute(
TSK_USER_NAME, PARENT_MODULE_NAME,
artnode.getAttribute("username")), //NON-NLS
new BlackboardAttribute(
TSK_USER_ID, PARENT_MODULE_NAME,
artnode.getAttribute("sid")),//NON-NLS
new BlackboardAttribute(
TSK_PATH, PARENT_MODULE_NAME,
homeDir));
BlackboardArtifact bbart = regAbstractFile.newArtifact(TSK_OS_ACCOUNT);
bbart.addAttributes(bbattributes);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error adding account artifact to blackboard."); //NON-NLS
}
}
private void processOffice(Element artnode, AbstractFile regAbstractFile, Long mtime, String value) throws IllegalArgumentException {
try {
List<BlackboardAttribute> bbattributes = Lists.newArrayList(
new BlackboardAttribute(TSK_NAME, PARENT_MODULE_NAME,
artnode.getAttribute("name")), //NON-NLS
new BlackboardAttribute(TSK_VALUE, PARENT_MODULE_NAME,
value),
new BlackboardAttribute(TSK_PROG_NAME, PARENT_MODULE_NAME,
artnode.getNodeName()));
// @@@ BC: Consider removing this after some more testing. It looks like an Mtime associated with the root key and not the individual item
if (mtime != null) {
bbattributes.add(new BlackboardAttribute(TSK_DATETIME_ACCESSED, PARENT_MODULE_NAME, mtime));
}
BlackboardArtifact bbart = regAbstractFile.newArtifact(TSK_RECENT_OBJECT);
bbart.addAttributes(bbattributes);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error adding recent object artifact to blackboard."); //NON-NLS
}
}
private void processUninstall(Element artnode, String progName, AbstractFile regAbstractFile) throws IllegalArgumentException {
Long itemMtime = null;
try {
Long epochtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(artnode.getAttribute("mtime")).getTime(); //NON-NLS
itemMtime = epochtime / 1000;
} catch (ParseException e) {
logger.log(Level.WARNING, "Failed to parse epoch time for installed program artifact."); //NON-NLS
}
try {
List<BlackboardAttribute> bbattributes = Lists.newArrayList(
new BlackboardAttribute(
TSK_PROG_NAME, PARENT_MODULE_NAME,
progName),
new BlackboardAttribute(
TSK_DATETIME, PARENT_MODULE_NAME,
itemMtime));
BlackboardArtifact bbart = regAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG);
bbart.addAttributes(bbattributes);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard."); //NON-NLS
}
}
private void processUSB(Element artnode, AbstractFile regAbstractFile, String deviceID, Collection<BlackboardArtifact> usbBBartifacts) throws IllegalArgumentException {
try {
String model = artnode.getAttribute("dev"); //NON-NLS
String make = "";
if (model.toLowerCase().contains("vid")) { //NON-NLS
USBInfo info = USB_MAPPER.parseAndLookup(model);
if (info.getVendor() != null) {
make = info.getVendor();
}
if (info.getProduct() != null) {
model = info.getProduct();
}
}
List<BlackboardAttribute> bbattributes = Lists.newArrayList(
new BlackboardAttribute(
TSK_DATETIME, PARENT_MODULE_NAME,
Long.parseLong(artnode.getAttribute("mtime"))),
new BlackboardAttribute(
TSK_DEVICE_MAKE, PARENT_MODULE_NAME,
make),
new BlackboardAttribute(
TSK_DEVICE_MODEL, PARENT_MODULE_NAME,
model),
new BlackboardAttribute(
TSK_DEVICE_ID, PARENT_MODULE_NAME,
deviceID));
BlackboardArtifact bbart = regAbstractFile.newArtifact(TSK_DEVICE_ATTACHED);
bbart.addAttributes(bbattributes);
usbBBartifacts.add(bbart);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error adding device attached artifact to blackboard."); //NON-NLS
}
}
private void processCompName(NodeList myartlist, SleuthkitCase caseDB, AbstractFile regAbstractFile) throws DOMException, IllegalArgumentException {
String compName = "";
String domain = "";
for (int j = 0; j < myartlist.getLength(); j++) {
Node artchild = myartlist.item(j);
// If it has attributes, then it is an Element (based off API)
if (artchild.hasAttributes()) {
Element artnode = (Element) artchild;
String value = artnode.getTextContent().trim();
String name = artnode.getAttribute("name"); //NON-NLS
if (name.equals("ComputerName")) { // NON-NLS
compName = value;
} else if (name.equals("Domain")) { // NON-NLS
domain = value;
}
}
}
try {
List<BlackboardAttribute> bbattributes = Lists.newArrayList(
new BlackboardAttribute(TSK_NAME, PARENT_MODULE_NAME, compName),
new BlackboardAttribute(TSK_DOMAIN, PARENT_MODULE_NAME, domain));
// Check if there is already an OS_INFO artifact for this file and add to that if possible
ArrayList<BlackboardArtifact> results = caseDB.getBlackboardArtifacts(TSK_OS_INFO, regAbstractFile.getId());
if (results.isEmpty()) {
BlackboardArtifact bbart = regAbstractFile.newArtifact(TSK_OS_INFO);
bbart.addAttributes(bbattributes);
} else {
results.get(0).addAttributes(bbattributes);
//TODO: does it need to get re-indexed?
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS
}
}
private void processProfiler(NodeList myartlist, SleuthkitCase caseDB, AbstractFile regAbstractFile) throws IllegalArgumentException, DOMException {
Set<String> keys = ImmutableSet.of("PROCESSOR_IDENTIFIER",// TODO: should this go into an attribute? //NON-NLS
"OS", "PROCESSOR_ARCHITECTURE", "TEMP"); //NON-NLS
Map<String, String> attributeValues = new HashMap<>();
for (int j = 0; j < myartlist.getLength(); j++) {
Node artchild = myartlist.item(j);
// If it has attributes, then it is an Element (based off API)
if (artchild.hasAttributes()) {
Element artnode = (Element) artchild;
String name = artnode.getAttribute("name"); //NON-NLS
if (keys.contains(name)) {
attributeValues.put(name, artnode.getTextContent().trim());
}
}
}
try {
List<BlackboardAttribute> bbattributes = Lists.newArrayList(
new BlackboardAttribute(
TSK_VERSION, PARENT_MODULE_NAME,
attributeValues.get("OS")), //NON-NLS
new BlackboardAttribute(
TSK_PROCESSOR_ARCHITECTURE, PARENT_MODULE_NAME,
attributeValues.get("PROCESSOR_ARCHITECTURE")), //NON-NLS
new BlackboardAttribute(
TSK_TEMP_DIR, PARENT_MODULE_NAME,
attributeValues.get("TEMP"))); //NON-NLS
// Check if there is already an OS_INFO artifact for this file and add to that if possible
ArrayList<BlackboardArtifact> results = caseDB.getBlackboardArtifacts(TSK_OS_INFO, regAbstractFile.getId());
if (results.isEmpty()) {
BlackboardArtifact bbart = regAbstractFile.newArtifact(TSK_OS_INFO);
bbart.addAttributes(bbattributes);
} else {
results.get(0).addAttributes(bbattributes);
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS
}
}
private void processWinVersion(NodeList myartlist, SleuthkitCase caseDB, AbstractFile regAbstractFile) throws NumberFormatException, IllegalArgumentException, DOMException {
String version = ""; String version = "";
String systemRoot = ""; String systemRoot = "";
String productId = ""; String productId = "";
@ -460,24 +775,33 @@ class ExtractRegistry extends Extract {
} }
} }
try { try {
Collection<BlackboardAttribute> bbattributes = new ArrayList<>(); List<BlackboardAttribute> bbattributes = Lists.newArrayList(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, version)); new BlackboardAttribute(
TSK_PROG_NAME, PARENT_MODULE_NAME,
version),
new BlackboardAttribute(
TSK_PATH, PARENT_MODULE_NAME,
systemRoot),
new BlackboardAttribute(
TSK_PRODUCT_ID, PARENT_MODULE_NAME,
productId),
new BlackboardAttribute(
TSK_OWNER, PARENT_MODULE_NAME,
regOwner),
new BlackboardAttribute(
TSK_ORGANIZATION, PARENT_MODULE_NAME,
regOrg
));
if (installtime != null) { if (installtime != null) {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, installtime)); bbattributes.add(new BlackboardAttribute(
TSK_DATETIME, PARENT_MODULE_NAME,
installtime));
} }
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, systemRoot));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PRODUCT_ID, parentModuleName, productId));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_OWNER, parentModuleName, regOwner));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ORGANIZATION, parentModuleName, regOrg));
// Check if there is already an OS_INFO artifact for this file, and add to that if possible. // Check if there is already an OS_INFO artifact for this file, and add to that if possible.
ArrayList<BlackboardArtifact> results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId()); ArrayList<BlackboardArtifact> results = caseDB.getBlackboardArtifacts(TSK_OS_INFO, regAbstractFile.getId());
if (results.isEmpty()) { if (results.isEmpty()) {
BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO); BlackboardArtifact bbart = regAbstractFile.newArtifact(TSK_OS_INFO);
bbart.addAttributes(bbattributes); bbart.addAttributes(bbattributes);
// index the artifact for keyword search
this.indexArtifact(bbart);
} else { } else {
results.get(0).addAttributes(bbattributes); results.get(0).addAttributes(bbattributes);
} }
@ -485,282 +809,6 @@ class ExtractRegistry extends Extract {
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard."); //NON-NLS logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard."); //NON-NLS
} }
break;
case "Profiler": // NON-NLS
String os = "";
String procArch = "";
String procId = "";
String tempDir = "";
for (int j = 0; j < myartlist.getLength(); j++) {
Node artchild = myartlist.item(j);
// If it has attributes, then it is an Element (based off API)
if (artchild.hasAttributes()) {
Element artnode = (Element) artchild;
String value = artnode.getTextContent().trim();
String name = artnode.getAttribute("name"); //NON-NLS
switch (name) {
case "OS": // NON-NLS
os = value;
break;
case "PROCESSOR_ARCHITECTURE": // NON-NLS
procArch = value;
break;
case "PROCESSOR_IDENTIFIER": //NON-NLS
procId = value;
break;
case "TEMP": //NON-NLS
tempDir = value;
break;
default:
break;
}
}
}
try {
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VERSION, parentModuleName, os));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE, parentModuleName, procArch));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEMP_DIR, parentModuleName, tempDir));
// Check if there is already an OS_INFO artifact for this file and add to that if possible
ArrayList<BlackboardArtifact> results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
if (results.isEmpty()) {
BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
bbart.addAttributes(bbattributes);
// index the artifact for keyword search
this.indexArtifact(bbart);
} else {
results.get(0).addAttributes(bbattributes);
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS
}
break;
case "CompName": // NON-NLS
String compName = "";
String domain = "";
for (int j = 0; j < myartlist.getLength(); j++) {
Node artchild = myartlist.item(j);
// If it has attributes, then it is an Element (based off API)
if (artchild.hasAttributes()) {
Element artnode = (Element) artchild;
String value = artnode.getTextContent().trim();
String name = artnode.getAttribute("name"); //NON-NLS
if (name.equals("ComputerName")) { // NON-NLS
compName = value;
} else if (name.equals("Domain")) { // NON-NLS
domain = value;
}
}
}
try {
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, compName));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, parentModuleName, domain));
// Check if there is already an OS_INFO artifact for this file and add to that if possible
ArrayList<BlackboardArtifact> results = tempDb.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
if (results.isEmpty()) {
BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
bbart.addAttributes(bbattributes);
// index the artifact for keyword search
this.indexArtifact(bbart);
} else {
results.get(0).addAttributes(bbattributes);
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS
}
break;
default:
for (int j = 0; j < myartlist.getLength(); j++) {
Node artchild = myartlist.item(j);
// If it has attributes, then it is an Element (based off API)
if (artchild.hasAttributes()) {
Element artnode = (Element) artchild;
String value = artnode.getTextContent().trim();
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
switch (dataType) {
case "recentdocs": //NON-NLS
// BlackboardArtifact bbart = tempDb.getContentById(orgId).newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
// bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", dataType, mtime));
// bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity", dataType, mtimeItem));
// bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), "RecentActivity", dataType, value));
// bbart.addAttributes(bbattributes);
// @@@ BC: Why are we ignoring this...
break;
case "usb": //NON-NLS
try {
Long usbMtime = Long.parseLong(artnode.getAttribute("mtime")); //NON-NLS
usbMtime = Long.valueOf(usbMtime.toString());
BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime));
String dev = artnode.getAttribute("dev"); //NON-NLS
String make = "";
String model = dev;
if (dev.toLowerCase().contains("vid")) { //NON-NLS
USBInfo info = USB_MAPPER.parseAndLookup(dev);
if (info.getVendor() != null) {
make = info.getVendor();
}
if (info.getProduct() != null) {
model = info.getProduct();
}
}
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value));
bbart.addAttributes(bbattributes);
// index the artifact for keyword search
this.indexArtifact(bbart);
// add to collection for ModuleDataEvent
usbBBartifacts.add(bbart);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error adding device attached artifact to blackboard."); //NON-NLS
}
break;
case "uninstall": //NON-NLS
Long itemMtime = null;
try {
Long epochtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(artnode.getAttribute("mtime")).getTime(); //NON-NLS
itemMtime = epochtime;
itemMtime = itemMtime / 1000;
} catch (ParseException e) {
logger.log(Level.WARNING, "Failed to parse epoch time for installed program artifact."); //NON-NLS
}
try {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, value));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, itemMtime));
BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG);
bbart.addAttributes(bbattributes);
// index the artifact for keyword search
this.indexArtifact(bbart);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard."); //NON-NLS
}
break;
case "office": //NON-NLS
String officeName = artnode.getAttribute("name"); //NON-NLS
try {
BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
// @@@ BC: Consider removing this after some more testing. It looks like an Mtime associated with the root key and not the individual item
if (mtime != null) {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, parentModuleName, mtime));
}
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, officeName));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, parentModuleName, value));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, artnode.getNodeName()));
bbart.addAttributes(bbattributes);
// index the artifact for keyword search
this.indexArtifact(bbart);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error adding recent object artifact to blackboard."); //NON-NLS
}
break;
case "ProcessorArchitecture": //NON-NLS
// Architecture is now included under Profiler
//try {
// String processorArchitecture = value;
// if (processorArchitecture.equals("AMD64"))
// processorArchitecture = "x86-64";
// BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
// bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE.getTypeID(), parentModuleName, processorArchitecture));
// bbart.addAttributes(bbattributes);
//} catch (TskCoreException ex) {
// logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS
//}
break;
case "ProfileList": //NON-NLS
try {
String homeDir = value;
String sid = artnode.getAttribute("sid"); //NON-NLS
String username = artnode.getAttribute("username"); //NON-NLS
BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
parentModuleName, username));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID,
parentModuleName, sid));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
parentModuleName, homeDir));
bbart.addAttributes(bbattributes);
// index the artifact for keyword search
this.indexArtifact(bbart);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error adding account artifact to blackboard."); //NON-NLS
}
break;
case "NtuserNetwork": // NON-NLS
try {
String localPath = artnode.getAttribute("localPath"); //NON-NLS
String remoteName = value;
BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_REMOTE_DRIVE);
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH,
parentModuleName, localPath));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH,
parentModuleName, remoteName));
bbart.addAttributes(bbattributes);
// index the artifact for keyword search
this.indexArtifact(bbart);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error adding network artifact to blackboard."); //NON-NLS
}
break;
case "shellfolders": // NON-NLS
// The User Shell Folders subkey stores the paths to Windows Explorer folders for the current user of the computer
// (https://technet.microsoft.com/en-us/library/Cc962613.aspx).
// No useful information. Skip.
break;
default:
logger.log(Level.WARNING, "Unrecognized node name: {0}", dataType); //NON-NLS
break;
}
}
}
break;
}
} // for
if (!usbBBartifacts.isEmpty()) {
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED, usbBBartifacts));
}
return true;
} catch (FileNotFoundException ex) {
logger.log(Level.SEVERE, "Error finding the registry file."); //NON-NLS
} catch (SAXException ex) {
logger.log(Level.SEVERE, "Error parsing the registry XML: {0}", ex); //NON-NLS
} catch (IOException ex) {
logger.log(Level.SEVERE, "Error building the document parser: {0}", ex); //NON-NLS
} catch (ParserConfigurationException ex) {
logger.log(Level.SEVERE, "Error configuring the registry parser: {0}", ex); //NON-NLS
} finally {
try {
if (fstream != null) {
fstream.close();
}
} catch (IOException ex) {
}
}
return false;
} }
@Override @Override

View File

@ -1,4 +1,4 @@
/* /*
* *
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
@ -22,28 +22,42 @@
*/ */
package org.sleuthkit.autopsy.recentactivity; package org.sleuthkit.autopsy.recentactivity;
import com.google.common.collect.Lists;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.logging.Level; import java.util.logging.Level;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.services.FileManager;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.ingest.IngestJobContext; 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.AbstractFile;
import org.sleuthkit.datamodel.Blackboard;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_REFERRER;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException; import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
@ -51,21 +65,25 @@ import org.sleuthkit.datamodel.TskCoreException;
/** /**
* Firefox recent activity extraction * Firefox recent activity extraction
*/ */
class Firefox extends Extract { final class FirefoxExtractor extends Extract {
private static final Logger logger = Logger.getLogger(FirefoxExtractor.class.getName());
private static final String PARENT_MODULE_NAME = NbBundle.getMessage(FirefoxExtractor.class,
"Firefox.parentModuleName.noSpace");
private static final Logger logger = Logger.getLogger(Firefox.class.getName());
private static final String HISTORY_QUERY = "SELECT moz_historyvisits.id,url,title,visit_count,(visit_date/1000000) AS visit_date,from_visit,(SELECT url FROM moz_places WHERE id=moz_historyvisits.from_visit) as ref FROM moz_places, moz_historyvisits WHERE moz_places.id = moz_historyvisits.place_id AND hidden = 0"; //NON-NLS private static final String HISTORY_QUERY = "SELECT moz_historyvisits.id,url,title,visit_count,(visit_date/1000000) AS visit_date,from_visit,(SELECT url FROM moz_places WHERE id=moz_historyvisits.from_visit) as ref FROM moz_places, moz_historyvisits WHERE moz_places.id = moz_historyvisits.place_id AND hidden = 0"; //NON-NLS
private static final String COOKIE_QUERY = "SELECT name,value,host,expiry,(lastAccessed/1000000) AS lastAccessed,(creationTime/1000000) AS creationTime FROM moz_cookies"; //NON-NLS private static final String COOKIE_QUERY = "SELECT name,value,host,expiry,(lastAccessed/1000000) AS lastAccessed,(creationTime/1000000) AS creationTime FROM moz_cookies"; //NON-NLS
private static final String COOKIE_QUERY_V3 = "SELECT name,value,host,expiry,(lastAccessed/1000000) AS lastAccessed FROM moz_cookies"; //NON-NLS private static final String COOKIE_QUERY_V3 = "SELECT name,value,host,expiry,(lastAccessed/1000000) AS lastAccessed FROM moz_cookies"; //NON-NLS
private static final String BOOKMARK_QUERY = "SELECT fk, moz_bookmarks.title, url, (moz_bookmarks.dateAdded/1000000) AS dateAdded FROM moz_bookmarks INNER JOIN moz_places ON moz_bookmarks.fk=moz_places.id"; //NON-NLS private static final String BOOKMARK_QUERY = "SELECT fk, moz_bookmarks.title, url, (moz_bookmarks.dateAdded/1000000) AS dateAdded FROM moz_bookmarks INNER JOIN moz_places ON moz_bookmarks.fk=moz_places.id"; //NON-NLS
private static final String DOWNLOAD_QUERY = "SELECT target, source,(startTime/1000000) AS startTime, maxBytes FROM moz_downloads"; //NON-NLS private static final String DOWNLOAD_QUERY = "SELECT target, source,(startTime/1000000) AS startTime, maxBytes FROM moz_downloads"; //NON-NLS
private static final String DOWNLOAD_QUERY_V24 = "SELECT url, content AS target, (lastModified/1000000) AS lastModified FROM moz_places, moz_annos WHERE moz_places.id = moz_annos.place_id AND moz_annos.anno_attribute_id = 3"; //NON-NLS private static final String DOWNLOAD_QUERY_V24 = "SELECT url, content AS target, (lastModified/1000000) AS lastModified FROM moz_places, moz_annos WHERE moz_places.id = moz_annos.place_id AND moz_annos.anno_attribute_id = 3"; //NON-NLS
private final IngestServices services = IngestServices.getInstance();
private Content dataSource; private Content dataSource;
private IngestJobContext context; private IngestJobContext context;
Firefox() { @Override
moduleName = NbBundle.getMessage(Firefox.class, "Firefox.moduleName"); protected String getModuleName() {
return NbBundle.getMessage(FirefoxExtractor.class, "Firefox.moduleName");
} }
@Override @Override
@ -75,19 +93,19 @@ class Firefox extends Extract {
dataFound = false; dataFound = false;
this.getHistory(); this.getHistory();
this.getBookmark(); this.getBookmark();
this.getDownload(); getDownloadPreVersion24();
getDownloadVersion24();
this.getCookie(); this.getCookie();
} }
private void getHistory() { private void getHistory() {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> historyFiles; List<AbstractFile> historyFiles;
try { try {
historyFiles = fileManager.findFiles(dataSource, "places.sqlite", "Firefox"); //NON-NLS historyFiles = fileManager.findFiles(dataSource, "places.sqlite", "Firefox"); //NON-NLS
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
String msg = NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errFetchingFiles"); String msg = NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errFetchingFiles");
logger.log(Level.WARNING, msg); logger.log(Level.WARNING, msg);
this.addErrorMessage(this.getName() + ": " + msg); this.addErrorMessage(this.getModuleName() + ": " + msg);
return; return;
} }
@ -99,28 +117,28 @@ class Firefox extends Extract {
dataFound = true; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>(); Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0; int index = 0;
for (AbstractFile historyFile : historyFiles) { for (AbstractFile historyFile : historyFiles) {
if (historyFile.getSize() == 0) { if (historyFile.getSize() == 0) {
continue; continue;
} }
String fileName = historyFile.getName(); String fileName = historyFile.getName();
String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + j + ".db"; //NON-NLS String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + index + ".db"; //NON-NLS
try { try {
ContentUtils.writeToFile(historyFile, new File(temps), context::dataSourceIngestIsCancelled); ContentUtils.writeToFile(historyFile, new File(temps), context::dataSourceIngestIsCancelled);
} catch (ReadContentInputStreamException ex) { } catch (ReadContentInputStreamException ex) {
logger.log(Level.WARNING, String.format("Error reading Firefox web history artifacts file '%s' (id=%d).", logger.log(Level.WARNING, String.format("Error reading Firefox web history artifacts file '%s' (id=%d).",
fileName, historyFile.getId()), ex); //NON-NLS fileName, historyFile.getId()), ex); //NON-NLS
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(), NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getModuleName(),
fileName)); fileName));
continue; continue;
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox web history artifacts file '%s' (id=%d).", logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox web history artifacts file '%s' (id=%d).",
temps, fileName, historyFile.getId()), ex); //NON-NLS temps, fileName, historyFile.getId()), ex); //NON-NLS
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(), NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getModuleName(),
fileName)); fileName));
continue; continue;
} }
@ -130,61 +148,61 @@ class Firefox extends Extract {
break; break;
} }
List<HashMap<String, Object>> tempList = this.dbConnect(temps, HISTORY_QUERY); List<HashMap<String, Object>> tempList = this.dbConnect(temps, HISTORY_QUERY);
logger.log(Level.INFO, "{0} - Now getting history from {1} with {2} artifacts identified.", new Object[]{moduleName, temps, tempList.size()}); //NON-NLS logger.log(Level.INFO, "{0} - Now getting history from {1} with {2} artifacts identified.", new Object[]{getModuleName(), temps, tempList.size()}); //NON-NLS
for (HashMap<String, Object> result : tempList) { for (HashMap<String, Object> result : tempList) {
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"),
((result.get("url").toString() != null) ? result.get("url").toString() : ""))); //NON-NLS
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("url").toString() != null) ? EscapeUtil.decodeURL(result.get("url").toString()) : "")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"),
(Long.valueOf(result.get("visit_date").toString())))); //NON-NLS
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER,
NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"),
((result.get("ref").toString() != null) ? result.get("ref").toString() : ""))); //NON-NLS
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"),
((result.get("title").toString() != null) ? result.get("title").toString() : ""))); //NON-NLS
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"),
NbBundle.getMessage(this.getClass(), "Firefox.moduleName")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"), (Util.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : "")))); //NON-NLS
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, historyFile, bbattributes); Collection<BlackboardAttribute> bbattributes = Arrays.asList(
if (bbart != null) { new BlackboardAttribute(
TSK_URL, PARENT_MODULE_NAME,
Objects.toString(result.get("url"), "")),//NON-NLS
new BlackboardAttribute(
TSK_DATETIME_ACCESSED, PARENT_MODULE_NAME,
Long.valueOf(result.get("visit_date").toString())), //NON-NLS
new BlackboardAttribute(
TSK_REFERRER, PARENT_MODULE_NAME,
Objects.toString(result.get("ref"), "")), //NON-NLS
new BlackboardAttribute(
TSK_TITLE, PARENT_MODULE_NAME,
Objects.toString(result.get("title"), "")), //NON-NLS
new BlackboardAttribute(
TSK_PROG_NAME, PARENT_MODULE_NAME,
getModuleName()),
new BlackboardAttribute(
TSK_DOMAIN, PARENT_MODULE_NAME,
Util.extractDomain(Objects.toString(result.get("url"), "")))); //NON-NLS
try {
BlackboardArtifact bbart = historyFile.newArtifact(TSK_WEB_HISTORY);
bbart.addAttributes(bbattributes);
bbartifacts.add(bbart); bbartifacts.add(bbart);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error while trying to create Firefox history artifact.", ex); //NON-NLS
this.addErrorMessage(
NbBundle.getMessage(Chrome.class, "Firefox.getHistory.errMsg.errAnalyzeFile=", //NON-NLS
this.getModuleName(), historyFile.getName()));
} }
} }
++j; index++;
dbFile.delete(); dbFile.delete();
} }
try {
services.fireModuleDataEvent(new ModuleDataEvent( blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), } catch (Blackboard.BlackboardException ex) {
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, bbartifacts)); logger.log(Level.SEVERE, "Error while trying to post Firefox history artifact.", ex); //NON-NLS
this.addErrorMessage(Bundle.Extractor_errPostingArtifacts(getModuleName()));
}
} }
/** /**
* Queries for bookmark files and adds artifacts * Queries for bookmark files and adds artifacts
*/ */
private void getBookmark() { private void getBookmark() {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> bookmarkFiles; List<AbstractFile> bookmarkFiles;
try { try {
bookmarkFiles = fileManager.findFiles(dataSource, "places.sqlite", "Firefox"); //NON-NLS bookmarkFiles = fileManager.findFiles(dataSource, "places.sqlite", "Firefox"); //NON-NLS
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
String msg = NbBundle.getMessage(this.getClass(), "Firefox.getBookmark.errMsg.errFetchFiles"); String msg = NbBundle.getMessage(this.getClass(), "Firefox.getBookmark.errMsg.errFetchFiles");
logger.log(Level.WARNING, msg); logger.log(Level.WARNING, msg);
this.addErrorMessage(this.getName() + ": " + msg); this.addErrorMessage(this.getModuleName() + ": " + msg);
return; return;
} }
@ -195,27 +213,27 @@ class Firefox extends Extract {
dataFound = true; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>(); Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0; int index = 0;
for (AbstractFile bookmarkFile : bookmarkFiles) { for (AbstractFile bookmarkFile : bookmarkFiles) {
if (bookmarkFile.getSize() == 0) { if (bookmarkFile.getSize() == 0) {
continue; continue;
} }
String fileName = bookmarkFile.getName(); String fileName = bookmarkFile.getName();
String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + j + ".db"; //NON-NLS String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + index + ".db"; //NON-NLS
try { try {
ContentUtils.writeToFile(bookmarkFile, new File(temps), context::dataSourceIngestIsCancelled); ContentUtils.writeToFile(bookmarkFile, new File(temps), context::dataSourceIngestIsCancelled);
} catch (ReadContentInputStreamException ex) { } catch (ReadContentInputStreamException ex) {
logger.log(Level.WARNING, String.format("Error reading Firefox bookmark artifacts file '%s' (id=%d).", logger.log(Level.WARNING, String.format("Error reading Firefox bookmark artifacts file '%s' (id=%d).",
fileName, bookmarkFile.getId()), ex); //NON-NLS fileName, bookmarkFile.getId()), ex); //NON-NLS
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(), NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getModuleName(),
fileName)); fileName));
continue; continue;
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox bookmark artifacts file '%s' (id=%d).", logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox bookmark artifacts file '%s' (id=%d).",
temps, fileName, bookmarkFile.getId()), ex); //NON-NLS temps, fileName, bookmarkFile.getId()), ex); //NON-NLS
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getBookmark.errMsg.errAnalyzeFile", this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getBookmark.errMsg.errAnalyzeFile",
this.getName(), fileName)); this.getModuleName(), fileName));
continue; continue;
} }
File dbFile = new File(temps); File dbFile = new File(temps);
@ -224,59 +242,61 @@ class Firefox extends Extract {
break; break;
} }
List<HashMap<String, Object>> tempList = this.dbConnect(temps, BOOKMARK_QUERY); List<HashMap<String, Object>> tempList = this.dbConnect(temps, BOOKMARK_QUERY);
logger.log(Level.INFO, "{0} - Now getting bookmarks from {1} with {2} artifacts identified.", new Object[]{moduleName, temps, tempList.size()}); //NON-NLS logger.log(Level.INFO, "{0} - Now getting bookmarks from {1} with {2} artifacts identified.", new Object[]{getModuleName(), temps, tempList.size()}); //NON-NLS
for (HashMap<String, Object> result : tempList) { for (HashMap<String, Object> result : tempList) {
Collection<BlackboardAttribute> bbattributes = new ArrayList<>(); Collection<BlackboardAttribute> bbattributes = Lists.newArrayList(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL, new BlackboardAttribute(
NbBundle.getMessage(this.getClass(), TSK_URL, PARENT_MODULE_NAME,
"Firefox.parentModuleName.noSpace"), Objects.toString(result.get("url"), "")), //NON-NLS
((result.get("url").toString() != null) ? result.get("url").toString() : ""))); //NON-NLS new BlackboardAttribute(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE, TSK_TITLE, PARENT_MODULE_NAME,
NbBundle.getMessage(this.getClass(), Objects.toString(result.get("title"), "")), //NON-NLS
"Firefox.parentModuleName.noSpace"), new BlackboardAttribute(
((result.get("title").toString() != null) ? result.get("title").toString() : ""))); //NON-NLS TSK_PROG_NAME, PARENT_MODULE_NAME,
if (Long.valueOf(result.get("dateAdded").toString()) > 0) { //NON-NLS getModuleName()),
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED, new BlackboardAttribute(
NbBundle.getMessage(this.getClass(), TSK_DOMAIN, PARENT_MODULE_NAME,
"Firefox.parentModuleName.noSpace"), Util.extractDomain(Objects.toString(result.get("url"), "")))); //NON-NLS
(Long.valueOf(result.get("dateAdded").toString())))); //NON-NLS Long createdTime = Long.valueOf(result.get("dateAdded").toString());
if (createdTime > 0) { //NON-NLS
bbattributes.add(new BlackboardAttribute(
TSK_DATETIME_CREATED, PARENT_MODULE_NAME,
createdTime)); //NON-NLS
} }
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, try {
NbBundle.getMessage(this.getClass(), BlackboardArtifact bbart = bookmarkFile.newArtifact(TSK_WEB_BOOKMARK);
"Firefox.parentModuleName.noSpace"), bbart.addAttributes(bbattributes);
NbBundle.getMessage(this.getClass(), "Firefox.moduleName")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"),
(Util.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : "")))); //NON-NLS
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bookmarkFile, bbattributes);
if (bbart != null) {
bbartifacts.add(bbart); bbartifacts.add(bbart);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error while trying to create Firefox bookmark artifact.", ex); //NON-NLS
this.addErrorMessage(
NbBundle.getMessage(Chrome.class, "Firefox.getBookmark.errMsg.errAnalyzeFile=", //NON-NLS
this.getModuleName(), bookmarkFile.getName()));
} }
} }
++j; index++;
dbFile.delete(); dbFile.delete();
} }
try {
services.fireModuleDataEvent(new ModuleDataEvent( blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), } catch (Blackboard.BlackboardException ex) {
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bbartifacts)); logger.log(Level.SEVERE, "Error while trying to post Firefox bookmark artifact.", ex); //NON-NLS
this.addErrorMessage(Bundle.Extractor_errPostingArtifacts(getModuleName()));
}
} }
/** /**
* Queries for cookies file and adds artifacts * Queries for cookies file and adds artifacts
*/ */
private void getCookie() { private void getCookie() {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> cookiesFiles; List<AbstractFile> cookiesFiles;
try { try {
cookiesFiles = fileManager.findFiles(dataSource, "cookies.sqlite", "Firefox"); //NON-NLS cookiesFiles = fileManager.findFiles(dataSource, "cookies.sqlite", "Firefox"); //NON-NLS
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
String msg = NbBundle.getMessage(this.getClass(), "Firefox.getCookie.errMsg.errFetchFile"); String msg = NbBundle.getMessage(this.getClass(), "Firefox.getCookie.errMsg.errFetchFile");
logger.log(Level.WARNING, msg); logger.log(Level.WARNING, msg);
this.addErrorMessage(this.getName() + ": " + msg); this.addErrorMessage(this.getModuleName() + ": " + msg);
return; return;
} }
@ -287,27 +307,27 @@ class Firefox extends Extract {
dataFound = true; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>(); Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0; int index = 0;
for (AbstractFile cookiesFile : cookiesFiles) { for (AbstractFile cookiesFile : cookiesFiles) {
if (cookiesFile.getSize() == 0) { if (cookiesFile.getSize() == 0) {
continue; continue;
} }
String fileName = cookiesFile.getName(); String fileName = cookiesFile.getName();
String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + j + ".db"; //NON-NLS String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + index + ".db"; //NON-NLS
try { try {
ContentUtils.writeToFile(cookiesFile, new File(temps), context::dataSourceIngestIsCancelled); ContentUtils.writeToFile(cookiesFile, new File(temps), context::dataSourceIngestIsCancelled);
} catch (ReadContentInputStreamException ex) { } catch (ReadContentInputStreamException ex) {
logger.log(Level.WARNING, String.format("Error reading Firefox cookie artifacts file '%s' (id=%d).", logger.log(Level.WARNING, String.format("Error reading Firefox cookie artifacts file '%s' (id=%d).",
fileName, cookiesFile.getId()), ex); //NON-NLS fileName, cookiesFile.getId()), ex); //NON-NLS
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(), NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getModuleName(),
fileName)); fileName));
continue; continue;
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox cookie artifacts file '%s' (id=%d).", logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox cookie artifacts file '%s' (id=%d).",
temps, fileName, cookiesFile.getId()), ex); //NON-NLS temps, fileName, cookiesFile.getId()), ex); //NON-NLS
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "Firefox.getCookie.errMsg.errAnalyzeFile", this.getName(), NbBundle.getMessage(this.getClass(), "Firefox.getCookie.errMsg.errAnalyzeFile", this.getModuleName(),
fileName)); fileName));
continue; continue;
} }
@ -317,71 +337,57 @@ class Firefox extends Extract {
break; break;
} }
boolean checkColumn = Util.checkColumn("creationTime", "moz_cookies", temps); //NON-NLS boolean checkColumn = Util.checkColumn("creationTime", "moz_cookies", temps); //NON-NLS
String query; String query = checkColumn ? COOKIE_QUERY : COOKIE_QUERY_V3;
if (checkColumn) {
query = COOKIE_QUERY;
} else {
query = COOKIE_QUERY_V3;
}
List<HashMap<String, Object>> tempList = this.dbConnect(temps, query); List<HashMap<String, Object>> tempList = this.dbConnect(temps, query);
logger.log(Level.INFO, "{0} - Now getting cookies from {1} with {2} artifacts identified.", new Object[]{moduleName, temps, tempList.size()}); //NON-NLS logger.log(Level.INFO, "{0} - Now getting cookies from {1} with {2} artifacts identified.", new Object[]{getModuleName(), temps, tempList.size()}); //NON-NLS
for (HashMap<String, Object> result : tempList) { for (HashMap<String, Object> result : tempList) {
Collection<BlackboardAttribute> bbattributes = new ArrayList<>(); Collection<BlackboardAttribute> bbattributes = Lists.newArrayList(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL, new BlackboardAttribute(
NbBundle.getMessage(this.getClass(), TSK_URL, PARENT_MODULE_NAME,
"Firefox.parentModuleName.noSpace"), Objects.toString(result.get("host"), "")), //NON-NLS
((result.get("host").toString() != null) ? result.get("host").toString() : ""))); //NON-NLS new BlackboardAttribute(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, TSK_DATETIME, PARENT_MODULE_NAME,
NbBundle.getMessage(this.getClass(), Long.valueOf(result.get("lastAccessed").toString())), //NON-NLS
"Firefox.parentModuleName.noSpace"), new BlackboardAttribute(
(Long.valueOf(result.get("lastAccessed").toString())))); //NON-NLS TSK_NAME, PARENT_MODULE_NAME,
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, Objects.toString(result.get("name"), "")), //NON-NLS
NbBundle.getMessage(this.getClass(), new BlackboardAttribute(
"Firefox.parentModuleName.noSpace"), TSK_VALUE, PARENT_MODULE_NAME,
((result.get("name").toString() != null) ? result.get("name").toString() : ""))); //NON-NLS Objects.toString(result.get("value"), "")), //NON-NLS
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, new BlackboardAttribute(
NbBundle.getMessage(this.getClass(), TSK_PROG_NAME, PARENT_MODULE_NAME,
"Firefox.parentModuleName.noSpace"), getModuleName()),
((result.get("value").toString() != null) ? result.get("value").toString() : ""))); //NON-NLS new BlackboardAttribute(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, TSK_DOMAIN, PARENT_MODULE_NAME,
NbBundle.getMessage(this.getClass(), Util.extractDomain(result.get("host").toString()).replaceFirst("^\\.+(?!$)", ""))); //NON-NLS
"Firefox.parentModuleName.noSpace"), if (checkColumn) {
NbBundle.getMessage(this.getClass(), "Firefox.moduleName"))); bbattributes.add(new BlackboardAttribute(
TSK_DATETIME_CREATED, PARENT_MODULE_NAME,
if (checkColumn == true) {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"),
(Long.valueOf(result.get("creationTime").toString())))); //NON-NLS (Long.valueOf(result.get("creationTime").toString())))); //NON-NLS
} }
String domain = Util.extractDomain(result.get("host").toString()); //NON-NLS try {
domain = domain.replaceFirst("^\\.+(?!$)", ""); BlackboardArtifact bbart = cookiesFile.newArtifact(TSK_WEB_COOKIE);
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, bbart.addAttributes(bbattributes);
NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"), domain));
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
if (bbart != null) {
bbartifacts.add(bbart); bbartifacts.add(bbart);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error while trying to create Firefox cookie artifact.", ex); //NON-NLS
this.addErrorMessage(
NbBundle.getMessage(Chrome.class, "Firefox.getCookie.errMsg.errAnalyzeFile=", //NON-NLS
this.getModuleName(), cookiesFile.getName()));
} }
} }
++j; ++index;
dbFile.delete(); dbFile.delete();
} }
services.fireModuleDataEvent(new ModuleDataEvent( try {
NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE, bbartifacts)); } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, "Error while trying to post Firefox cookie artifact.", ex); //NON-NLS
this.addErrorMessage(Bundle.Extractor_errPostingArtifacts(getModuleName()));
} }
/**
* Queries for downloads files and adds artifacts
*/
private void getDownload() {
getDownloadPreVersion24();
getDownloadVersion24();
} }
/** /**
@ -391,14 +397,13 @@ class Firefox extends Extract {
*/ */
private void getDownloadPreVersion24() { private void getDownloadPreVersion24() {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> downloadsFiles; List<AbstractFile> downloadsFiles;
try { try {
downloadsFiles = fileManager.findFiles(dataSource, "downloads.sqlite", "Firefox"); //NON-NLS downloadsFiles = fileManager.findFiles(dataSource, "downloads.sqlite", "Firefox"); //NON-NLS
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
String msg = NbBundle.getMessage(this.getClass(), "Firefox.getDlPre24.errMsg.errFetchFiles"); String msg = NbBundle.getMessage(this.getClass(), "Firefox.getDlPre24.errMsg.errFetchFiles");
logger.log(Level.WARNING, msg); logger.log(Level.WARNING, msg);
this.addErrorMessage(this.getName() + ": " + msg); this.addErrorMessage(this.getModuleName() + ": " + msg);
return; return;
} }
@ -409,13 +414,13 @@ class Firefox extends Extract {
dataFound = true; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>(); Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0; int index = 0;
for (AbstractFile downloadsFile : downloadsFiles) { for (AbstractFile downloadsFile : downloadsFiles) {
if (downloadsFile.getSize() == 0) { if (downloadsFile.getSize() == 0) {
continue; continue;
} }
String fileName = downloadsFile.getName(); String fileName = downloadsFile.getName();
String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + j + ".db"; //NON-NLS String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + index + ".db"; //NON-NLS
int errors = 0; int errors = 0;
try { try {
ContentUtils.writeToFile(downloadsFile, new File(temps), context::dataSourceIngestIsCancelled); ContentUtils.writeToFile(downloadsFile, new File(temps), context::dataSourceIngestIsCancelled);
@ -423,14 +428,14 @@ class Firefox extends Extract {
logger.log(Level.WARNING, String.format("Error reading Firefox download artifacts file '%s' (id=%d).", logger.log(Level.WARNING, String.format("Error reading Firefox download artifacts file '%s' (id=%d).",
fileName, downloadsFile.getId()), ex); //NON-NLS fileName, downloadsFile.getId()), ex); //NON-NLS
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(), NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getModuleName(),
fileName)); fileName));
continue; continue;
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox download artifacts file '%s' (id=%d).", logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox download artifacts file '%s' (id=%d).",
temps, fileName, downloadsFile.getId()), ex); //NON-NLS temps, fileName, downloadsFile.getId()), ex); //NON-NLS
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getDlPre24.errMsg.errAnalyzeFiles", this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getDlPre24.errMsg.errAnalyzeFiles",
this.getName(), fileName)); this.getModuleName(), fileName));
continue; continue;
} }
File dbFile = new File(temps); File dbFile = new File(temps);
@ -440,70 +445,63 @@ class Firefox extends Extract {
} }
List<HashMap<String, Object>> tempList = this.dbConnect(temps, DOWNLOAD_QUERY); List<HashMap<String, Object>> tempList = this.dbConnect(temps, DOWNLOAD_QUERY);
logger.log(Level.INFO, "{0}- Now getting downloads from {1} with {2} artifacts identified.", new Object[]{moduleName, temps, tempList.size()}); //NON-NLS logger.log(Level.INFO, "{0}- Now getting downloads from {1} with {2} artifacts identified.", new Object[]{getModuleName(), temps, tempList.size()}); //NON-NLS
for (HashMap<String, Object> result : tempList) { for (HashMap<String, Object> result : tempList) {
Collection<BlackboardAttribute> bbattributes = new ArrayList<>(); Collection<BlackboardAttribute> bbattributes = Lists.newArrayList(
new BlackboardAttribute(TSK_URL, PARENT_MODULE_NAME,
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL, Objects.toString(result.get("source"), "")), //NON-NLS
NbBundle.getMessage(this.getClass(), new BlackboardAttribute(TSK_DATETIME_ACCESSED, PARENT_MODULE_NAME,
"Firefox.parentModuleName.noSpace"), Long.valueOf(result.get("startTime").toString())), //NON-NLS
((result.get("source").toString() != null) ? result.get("source").toString() : ""))); //NON-NLS new BlackboardAttribute(TSK_PROG_NAME, PARENT_MODULE_NAME,
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("source").toString() != null) ? EscapeUtil.decodeURL(result.get("source").toString()) : ""))); getModuleName()),
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, new BlackboardAttribute(TSK_DOMAIN, PARENT_MODULE_NAME,
NbBundle.getMessage(this.getClass(), Util.extractDomain(Objects.toString(result.get("source"), "")))); //NON-NLS
"Firefox.parentModuleName.noSpace"),
(Long.valueOf(result.get("startTime").toString())))); //NON-NLS
String target = result.get("target").toString(); //NON-NLS String target = result.get("target").toString(); //NON-NLS
if (target != null) {
try { try {
String decodedTarget = URLDecoder.decode(target.replaceAll("file:///", ""), "UTF-8"); //NON-NLS String decodedTarget = URLDecoder.decode(target.replaceAll("file:///", ""), "UTF-8"); //NON-NLS
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, bbattributes.add(new BlackboardAttribute(
NbBundle.getMessage(this.getClass(), TSK_PATH, PARENT_MODULE_NAME,
"Firefox.parentModuleName.noSpace"),
decodedTarget)); decodedTarget));
long pathID = Util.findID(dataSource, decodedTarget); long pathID = Util.findID(dataSource, decodedTarget);
if (pathID != -1) { if (pathID != -1) {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID, bbattributes.add(new BlackboardAttribute(
NbBundle.getMessage(this.getClass(), TSK_PATH_ID, PARENT_MODULE_NAME,
"Firefox.parentModuleName.noSpace"),
pathID)); pathID));
} }
} catch (UnsupportedEncodingException ex) { } catch (UnsupportedEncodingException ex) {
logger.log(Level.SEVERE, "Error decoding Firefox download URL in " + temps, ex); //NON-NLS logger.log(Level.SEVERE, "Error decoding Firefox download URL in " + temps, ex); //NON-NLS
errors++; errors++;
} }
} try {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, BlackboardArtifact bbart = downloadsFile.newArtifact(TSK_WEB_DOWNLOAD);
NbBundle.getMessage(this.getClass(), bbart.addAttributes(bbattributes);
"Firefox.parentModuleName.noSpace"),
NbBundle.getMessage(this.getClass(), "Firefox.moduleName")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"),
(Util.extractDomain((result.get("source").toString() != null) ? result.get("source").toString() : "")))); //NON-NLS
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
if (bbart != null) {
bbartifacts.add(bbart); bbartifacts.add(bbart);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error while trying to create Firefox download artifact.", ex); //NON-NLS
this.addErrorMessage(
NbBundle.getMessage(Chrome.class, "Firefox.getDlPre24.errMsg.errAnalyzeFiles", //NON-NLS
this.getModuleName(), downloadsFile.getName()));
} }
} }
if (errors > 0) { if (errors > 0) {
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "Firefox.getDlPre24.errMsg.errParsingArtifacts", NbBundle.getMessage(this.getClass(), "Firefox.getDlPre24.errMsg.errParsingArtifacts",
this.getName(), errors)); this.getModuleName(), errors));
} }
j++; index++;
dbFile.delete(); dbFile.delete();
break;
} }
services.fireModuleDataEvent(new ModuleDataEvent( try {
NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, bbartifacts)); } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, "Error while trying to post Firefox download artifact.", ex); //NON-NLS
this.addErrorMessage(Bundle.Extractor_errPostingArtifacts(getModuleName()));
}
} }
/** /**
@ -512,14 +510,13 @@ class Firefox extends Extract {
* Downloads are stored in the places database. * Downloads are stored in the places database.
*/ */
private void getDownloadVersion24() { private void getDownloadVersion24() {
FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> downloadsFiles; List<AbstractFile> downloadsFiles;
try { try {
downloadsFiles = fileManager.findFiles(dataSource, "places.sqlite", "Firefox"); //NON-NLS downloadsFiles = fileManager.findFiles(dataSource, "places.sqlite", "Firefox"); //NON-NLS
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
String msg = NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errFetchFiles"); String msg = NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errFetchFiles");
logger.log(Level.WARNING, msg); logger.log(Level.WARNING, msg);
this.addErrorMessage(this.getName() + ": " + msg); this.addErrorMessage(this.getModuleName() + ": " + msg);
return; return;
} }
@ -530,13 +527,13 @@ class Firefox extends Extract {
dataFound = true; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>(); Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
int j = 0; int index = 0;
for (AbstractFile downloadsFile : downloadsFiles) { for (AbstractFile downloadsFile : downloadsFiles) {
if (downloadsFile.getSize() == 0) { if (downloadsFile.getSize() == 0) {
continue; continue;
} }
String fileName = downloadsFile.getName(); String fileName = downloadsFile.getName();
String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + "-downloads" + j + ".db"; //NON-NLS String temps = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + "-downloads" + index + ".db"; //NON-NLS
int errors = 0; int errors = 0;
try { try {
ContentUtils.writeToFile(downloadsFile, new File(temps), context::dataSourceIngestIsCancelled); ContentUtils.writeToFile(downloadsFile, new File(temps), context::dataSourceIngestIsCancelled);
@ -544,14 +541,14 @@ class Firefox extends Extract {
logger.log(Level.WARNING, String.format("Error reading Firefox download artifacts file '%s' (id=%d).", logger.log(Level.WARNING, String.format("Error reading Firefox download artifacts file '%s' (id=%d).",
fileName, downloadsFile.getId()), ex); //NON-NLS fileName, downloadsFile.getId()), ex); //NON-NLS
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(), NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getModuleName(),
fileName)); fileName));
continue; continue;
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox download artifacts file '%s' (id=%d).", logger.log(Level.SEVERE, String.format("Error writing temp sqlite db file '%s' for Firefox download artifacts file '%s' (id=%d).",
temps, fileName, downloadsFile.getId()), ex); //NON-NLS temps, fileName, downloadsFile.getId()), ex); //NON-NLS
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errAnalyzeFile", this.getName(), NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errAnalyzeFile", this.getModuleName(),
fileName)); fileName));
continue; continue;
} }
@ -563,68 +560,66 @@ class Firefox extends Extract {
List<HashMap<String, Object>> tempList = this.dbConnect(temps, DOWNLOAD_QUERY_V24); List<HashMap<String, Object>> tempList = this.dbConnect(temps, DOWNLOAD_QUERY_V24);
logger.log(Level.INFO, "{0} - Now getting downloads from {1} with {2} artifacts identified.", new Object[]{moduleName, temps, tempList.size()}); //NON-NLS logger.log(Level.INFO, "{0} - Now getting downloads from {1} with {2} artifacts identified.", new Object[]{getModuleName(), temps, tempList.size()}); //NON-NLS
for (HashMap<String, Object> result : tempList) { for (HashMap<String, Object> result : tempList) {
Collection<BlackboardAttribute> bbattributes = new ArrayList<>(); Collection<BlackboardAttribute> bbattributes = Lists.newArrayList(
new BlackboardAttribute(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL, TSK_URL, PARENT_MODULE_NAME,
NbBundle.getMessage(this.getClass(), result.get("url").toString()), //NON-NLS
"Firefox.parentModuleName.noSpace"), new BlackboardAttribute(
((result.get("url").toString() != null) ? result.get("url").toString() : ""))); //NON-NLS TSK_DATETIME_ACCESSED, PARENT_MODULE_NAME,
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("source").toString() != null) ? EscapeUtil.decodeURL(result.get("source").toString()) : ""))); Long.valueOf(result.get("lastModified").toString())), //NON-NLS
//TODO Revisit usage of deprecated constructor as per TSK-583 new BlackboardAttribute(
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", "Last Visited", (Long.valueOf(result.get("startTime").toString())))); TSK_PROG_NAME, PARENT_MODULE_NAME,
getModuleName()),
new BlackboardAttribute(
TSK_DOMAIN, PARENT_MODULE_NAME,
Util.extractDomain(result.get("url").toString()))); //NON-NLS
String target = result.get("target").toString(); //NON-NLS String target = result.get("target").toString(); //NON-NLS
if (target != null) {
try { try {
String decodedTarget = URLDecoder.decode(target.replaceAll("file:///", ""), "UTF-8"); //NON-NLS String decodedTarget = URLDecoder.decode(target.replaceAll("file:///", ""), "UTF-8"); //NON-NLS
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, bbattributes.add(new BlackboardAttribute(
NbBundle.getMessage(this.getClass(), TSK_PATH, PARENT_MODULE_NAME,
"Firefox.parentModuleName.noSpace"),
decodedTarget)); decodedTarget));
long pathID = Util.findID(dataSource, decodedTarget); long pathID = Util.findID(dataSource, decodedTarget);
if (pathID != -1) { if (pathID != -1) {
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID, bbattributes.add(new BlackboardAttribute(
NbBundle.getMessage(this.getClass(), TSK_PATH_ID, PARENT_MODULE_NAME,
"Firefox.parentModuleName.noSpace"),
pathID)); pathID));
} }
} catch (UnsupportedEncodingException ex) { } catch (UnsupportedEncodingException ex) {
logger.log(Level.SEVERE, "Error decoding Firefox download URL in " + temps, ex); //NON-NLS logger.log(Level.SEVERE, "Error decoding Firefox download URL in " + temps, ex); //NON-NLS
errors++; errors++;
} }
}
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"),
Long.valueOf(result.get("lastModified").toString()))); //NON-NLS
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"),
NbBundle.getMessage(this.getClass(), "Firefox.moduleName")));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(),
"Firefox.parentModuleName.noSpace"),
(Util.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : "")))); //NON-NLS
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes); try {
if (bbart != null) { BlackboardArtifact bbart = downloadsFile.newArtifact(TSK_WEB_DOWNLOAD);
bbart.addAttributes(bbattributes);
bbartifacts.add(bbart); bbartifacts.add(bbart);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error while trying to create Firefox download artifact.", ex); //NON-NLS
this.addErrorMessage(
NbBundle.getMessage(Chrome.class, "Firefox.getDlV24.errMsg.errAnalyzeFile", //NON-NLS
this.getModuleName(), downloadsFile.getName()));
} }
} }
if (errors > 0) { if (errors > 0) {
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errParsingArtifacts", this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errParsingArtifacts",
this.getName(), errors)); this.getModuleName(), errors));
} }
j++; index++;
dbFile.delete(); dbFile.delete();
break;
} }
services.fireModuleDataEvent(new ModuleDataEvent( try {
NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, bbartifacts)); } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, "Error while trying to post Firefox download artifact.", ex); //NON-NLS
this.addErrorMessage(Bundle.Extractor_errPostingArtifacts(getModuleName()));
}
} }
} }

View File

@ -1,4 +1,4 @@
/* /*
* *
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
@ -23,7 +23,6 @@
package org.sleuthkit.autopsy.recentactivity; package org.sleuthkit.autopsy.recentactivity;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
@ -33,12 +32,12 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.DataSourceIngestModule; import org.sleuthkit.autopsy.ingest.DataSourceIngestModule;
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress; import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress;
import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestMessage; import org.sleuthkit.autopsy.ingest.IngestMessage;
import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType; import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.autopsy.ingest.IngestModule.ProcessResult; import org.sleuthkit.autopsy.ingest.IngestModule.ProcessResult;
import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.datamodel.Content;
/** /**
* Recent activity image ingest module * Recent activity image ingest module
@ -48,12 +47,8 @@ public final class RAImageIngestModule implements DataSourceIngestModule {
private static final Logger logger = Logger.getLogger(RAImageIngestModule.class.getName()); private static final Logger logger = Logger.getLogger(RAImageIngestModule.class.getName());
private final List<Extract> extracters = new ArrayList<>(); private final List<Extract> extracters = new ArrayList<>();
private final List<Extract> browserExtracters = new ArrayList<>(); private final List<Extract> browserExtracters = new ArrayList<>();
private IngestServices services = IngestServices.getInstance(); private final IngestServices services = IngestServices.getInstance();
private IngestJobContext context; private IngestJobContext context;
private StringBuilder subCompleted = new StringBuilder();
RAImageIngestModule() {
}
@Override @Override
public void startUp(IngestJobContext context) throws IngestModuleException { public void startUp(IngestJobContext context) throws IngestModuleException {
@ -67,10 +62,10 @@ public final class RAImageIngestModule implements DataSourceIngestModule {
} }
Extract registry = new ExtractRegistry(); Extract registry = new ExtractRegistry();
Extract recentDocuments = new RecentDocumentsByLnk(); Extract recentDocuments = new RecentDocumentsLnkExtractor();
Extract chrome = new Chrome(); Extract chrome = new Chrome();
Extract firefox = new Firefox(); Extract firefox = new FirefoxExtractor();
Extract SEUQA = new SearchEngineURLQueryAnalyzer(); Extract SEUQA = new SearchEngineURLQueryExtractor();
extracters.add(chrome); extracters.add(chrome);
extracters.add(firefox); extracters.add(firefox);
@ -102,18 +97,16 @@ public final class RAImageIngestModule implements DataSourceIngestModule {
for (int i = 0; i < extracters.size(); i++) { for (int i = 0; i < extracters.size(); i++) {
Extract extracter = extracters.get(i); Extract extracter = extracters.get(i);
if (context.dataSourceIngestIsCancelled()) { if (context.dataSourceIngestIsCancelled()) {
logger.log(Level.INFO, "Recent Activity has been canceled, quitting before {0}", extracter.getName()); //NON-NLS logger.log(Level.INFO, "Recent Activity has been canceled, quitting before {0}", extracter.getModuleName()); //NON-NLS
break; break;
} }
progressBar.progress(extracter.getName(), i); progressBar.progress(extracter.getModuleName(), i);
try { try {
extracter.process(dataSource, context); extracter.process(dataSource, context);
} catch (Exception ex) { } catch (Exception ex) {
logger.log(Level.SEVERE, "Exception occurred in " + extracter.getName(), ex); //NON-NLS logger.log(Level.SEVERE, "Exception occurred in " + extracter.getModuleName(), ex); //NON-NLS
subCompleted.append(NbBundle.getMessage(this.getClass(), "RAImageIngestModule.process.errModFailed",
extracter.getName()));
errors.add( errors.add(
NbBundle.getMessage(this.getClass(), "RAImageIngestModule.process.errModErrs", RecentActivityExtracterModuleFactory.getModuleName())); NbBundle.getMessage(this.getClass(), "RAImageIngestModule.process.errModErrs", RecentActivityExtracterModuleFactory.getModuleName()));
} }
@ -155,7 +148,7 @@ public final class RAImageIngestModule implements DataSourceIngestModule {
historyMsg.append( historyMsg.append(
NbBundle.getMessage(this.getClass(), "RAImageIngestModule.process.histMsg.title", dataSource.getName())); NbBundle.getMessage(this.getClass(), "RAImageIngestModule.process.histMsg.title", dataSource.getName()));
for (Extract module : browserExtracters) { for (Extract module : browserExtracters) {
historyMsg.append("<li>").append(module.getName()); //NON-NLS historyMsg.append("<li>").append(module.getModuleName()); //NON-NLS
historyMsg.append(": ").append((module.foundData()) ? NbBundle historyMsg.append(": ").append((module.foundData()) ? NbBundle
.getMessage(this.getClass(), "RAImageIngestModule.process.histMsg.found") : NbBundle .getMessage(this.getClass(), "RAImageIngestModule.process.histMsg.found") : NbBundle
.getMessage(this.getClass(), "RAImageIngestModule.process.histMsg.notFnd")); .getMessage(this.getClass(), "RAImageIngestModule.process.histMsg.notFnd"));
@ -173,17 +166,6 @@ public final class RAImageIngestModule implements DataSourceIngestModule {
return ProcessResult.OK; return ProcessResult.OK;
} }
for (int i = 0; i < extracters.size(); i++) {
Extract extracter = extracters.get(i);
try {
extracter.complete();
} catch (Exception ex) {
logger.log(Level.SEVERE, "Exception occurred when completing " + extracter.getName(), ex); //NON-NLS
subCompleted.append(NbBundle.getMessage(this.getClass(), "RAImageIngestModule.complete.errMsg.failed",
extracter.getName()));
}
}
return ProcessResult.OK; return ProcessResult.OK;
} }

View File

@ -1,8 +1,8 @@
/* /*
* *
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2012-2014 Basis Technology Corp. * Copyright 2012-2018 Basis Technology Corp.
* *
* Copyright 2012 42six Solutions. * Copyright 2012 42six Solutions.
* Contact: aebadirad <at> 42six <dot> com * Contact: aebadirad <at> 42six <dot> com
@ -23,37 +23,55 @@
package org.sleuthkit.autopsy.recentactivity; package org.sleuthkit.autopsy.recentactivity;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import java.util.Collection;
import org.sleuthkit.autopsy.coreutils.JLNK; import org.sleuthkit.autopsy.coreutils.JLNK;
import org.sleuthkit.autopsy.coreutils.JLnkParser; import org.sleuthkit.autopsy.coreutils.JLnkParser;
import org.sleuthkit.autopsy.coreutils.JLnkParserException; import org.sleuthkit.autopsy.coreutils.JLnkParserException;
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.datamodel.Blackboard;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.*; import org.sleuthkit.datamodel.ReadContentInputStream;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
/** /**
* Recent documents class that will extract recent documents in the form of .lnk * Recent documents class that will extract recent documents in the form of .lnk
* files * files
*/ */
class RecentDocumentsByLnk extends Extract { class RecentDocumentsLnkExtractor extends Extract {
private static final Logger logger = Logger.getLogger(RecentDocumentsByLnk.class.getName()); private static final Logger logger = Logger.getLogger(RecentDocumentsLnkExtractor.class.getName());
private IngestServices services = IngestServices.getInstance();
private static final String PARENT_MODULE_NAME = NbBundle.getMessage(RecentDocumentsLnkExtractor.class,
"RecentDocumentsByLnk.parentModuleName.noSpace");
private Content dataSource; private Content dataSource;
private IngestJobContext context; private IngestJobContext context;
@Override
protected String getModuleName() {
return "lnk files";
}
@Override
public void process(Content dataSource, IngestJobContext context) {
this.dataSource = dataSource;
this.context = context;
dataFound = false;
this.getRecentDocuments();
}
/** /**
* Find the documents that Windows stores about recent documents and make * Find the documents that Windows stores about recent documents and make
* artifacts. * artifacts.
@ -62,8 +80,6 @@ class RecentDocumentsByLnk extends Extract {
* @param controller * @param controller
*/ */
private void getRecentDocuments() { private void getRecentDocuments() {
org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
List<AbstractFile> recentFiles; List<AbstractFile> recentFiles;
try { try {
recentFiles = fileManager.findFiles(dataSource, "%.lnk", "Recent"); //NON-NLS recentFiles = fileManager.findFiles(dataSource, "%.lnk", "Recent"); //NON-NLS
@ -71,7 +87,7 @@ class RecentDocumentsByLnk extends Extract {
logger.log(Level.WARNING, "Error searching for .lnk files."); //NON-NLS logger.log(Level.WARNING, "Error searching for .lnk files."); //NON-NLS
this.addErrorMessage( this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "RecentDocumentsByLnk.getRecDoc.errMsg.errGetLnkFiles", NbBundle.getMessage(this.getClass(), "RecentDocumentsByLnk.getRecDoc.errMsg.errGetLnkFiles",
this.getName())); this.getModuleName()));
return; return;
} }
@ -81,6 +97,8 @@ class RecentDocumentsByLnk extends Extract {
} }
dataFound = true; dataFound = true;
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
for (AbstractFile recentFile : recentFiles) { for (AbstractFile recentFile : recentFiles) {
if (context.dataSourceIngestIsCancelled()) { if (context.dataSourceIngestIsCancelled()) {
break; break;
@ -102,33 +120,36 @@ class RecentDocumentsByLnk extends Extract {
} }
continue; continue;
} }
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
String path = lnk.getBestPath(); String path = lnk.getBestPath();
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, Collection<BlackboardAttribute> bbattributes = Arrays.asList(
NbBundle.getMessage(this.getClass(), new BlackboardAttribute(
"RecentDocumentsByLnk.parentModuleName.noSpace"), TSK_PATH, PARENT_MODULE_NAME,
path)); path),
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID, new BlackboardAttribute(
NbBundle.getMessage(this.getClass(), TSK_PATH_ID, PARENT_MODULE_NAME,
"RecentDocumentsByLnk.parentModuleName.noSpace"), Util.findID(dataSource, path)),
Util.findID(dataSource, path))); new BlackboardAttribute(
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, TSK_DATETIME, PARENT_MODULE_NAME,
NbBundle.getMessage(this.getClass(),
"RecentDocumentsByLnk.parentModuleName.noSpace"),
recentFile.getCrtime())); recentFile.getCrtime()));
this.addArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT, recentFile, bbattributes); try {
BlackboardArtifact bbart = recentFile.newArtifact(TSK_RECENT_OBJECT);
bbart.addAttributes(bbattributes);
bbartifacts.add(bbart);
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Error creating recent document artifact.", ex); //NON-NLS
this.addErrorMessage(
NbBundle.getMessage(this.getClass(), "RecentDocumentsByLnk.getRecDoc.errMsg.errCreatingArtifact",
this.getModuleName()));
} }
services.fireModuleDataEvent(new ModuleDataEvent(
NbBundle.getMessage(this.getClass(), "RecentDocumentsByLnk.parentModuleName"),
BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT));
} }
@Override //TODO: why weren't these getting indexed before?
public void process(Content dataSource, IngestJobContext context) { try {
this.dataSource = dataSource; blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
this.context = context; } catch (Blackboard.BlackboardException ex) {
dataFound = false; logger.log(Level.SEVERE, "Error while trying to post recent document artifact.", ex); //NON-NLS
this.getRecentDocuments(); this.addErrorMessage(Bundle.Extractor_errPostingArtifacts(getModuleName()));
} }
}
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2012-2014 Basis Technology Corp. * Copyright 2012-2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -23,10 +23,10 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
@ -35,13 +35,17 @@ import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.coreutils.XMLUtil; import org.sleuthkit.autopsy.coreutils.XMLUtil;
import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException; import org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException;
import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Blackboard;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT;
import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.w3c.dom.Document; import org.w3c.dom.Document;
@ -64,18 +68,22 @@ import org.xml.sax.SAXException;
"cannotParseXml=Unable to parse XML file: ", "cannotParseXml=Unable to parse XML file: ",
"# {0} - file name", "SearchEngineURLQueryAnalyzer.init.exception.msg=Unable to find {0}." "# {0} - file name", "SearchEngineURLQueryAnalyzer.init.exception.msg=Unable to find {0}."
}) })
class SearchEngineURLQueryAnalyzer extends Extract { final class SearchEngineURLQueryExtractor extends Extract {
private static final Logger logger = Logger.getLogger(SearchEngineURLQueryExtractor.class.getName());
private static final String PARENT_MODULE_NAME = NbBundle.getMessage(SearchEngineURLQueryExtractor.class,
"SearchEngineURLQueryAnalyzer.parentModuleName");
private static final Logger logger = Logger.getLogger(SearchEngineURLQueryAnalyzer.class.getName());
private static final String XMLFILE = "SEUQAMappings.xml"; //NON-NLS private static final String XMLFILE = "SEUQAMappings.xml"; //NON-NLS
private static final String XSDFILE = "SearchEngineSchema.xsd"; //NON-NLS private static final String XSDFILE = "SearchEngineSchema.xsd"; //NON-NLS
private static SearchEngineURLQueryAnalyzer.SearchEngine[] engines; private static SearchEngine[] engines;
private Content dataSource; private Content dataSource;
private IngestJobContext context; private IngestJobContext context;
SearchEngineURLQueryAnalyzer() { @Override
moduleName = NbBundle.getMessage(ExtractIE.class, "SearchEngineURLQueryAnalyzer.moduleName.text"); protected String getModuleName() {
return NbBundle.getMessage(ExtractIE.class, "SearchEngineURLQueryAnalyzer.moduleName.text");
} }
/** /**
@ -156,13 +164,11 @@ class SearchEngineURLQueryAnalyzer extends Extract {
Document xmlinput; Document xmlinput;
try { try {
String path = PlatformUtil.getUserConfigDirectory() + File.separator + XMLFILE; String path = PlatformUtil.getUserConfigDirectory() + File.separator + XMLFILE;
File f = new File(path); File configFile = new File(path);
logger.log(Level.INFO, "Load successful"); //NON-NLS logger.log(Level.INFO, "Load successful"); //NON-NLS
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); xmlinput = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(configFile);
DocumentBuilder db = dbf.newDocumentBuilder();
xmlinput = db.parse(f);
if (!XMLUtil.xmlIsValid(xmlinput, SearchEngineURLQueryAnalyzer.class, XSDFILE)) { if (!XMLUtil.xmlIsValid(xmlinput, SearchEngineURLQueryExtractor.class, XSDFILE)) {
logger.log(Level.WARNING, "Error loading Search Engines: could not validate against [" + XSDFILE + "], results may not be accurate."); //NON-NLS logger.log(Level.WARNING, "Error loading Search Engines: could not validate against [" + XSDFILE + "], results may not be accurate."); //NON-NLS
} }
@ -175,7 +181,7 @@ class SearchEngineURLQueryAnalyzer extends Extract {
} }
NodeList nlist = xmlinput.getElementsByTagName("SearchEngine"); //NON-NLS NodeList nlist = xmlinput.getElementsByTagName("SearchEngine"); //NON-NLS
SearchEngineURLQueryAnalyzer.SearchEngine[] listEngines = new SearchEngineURLQueryAnalyzer.SearchEngine[nlist.getLength()]; SearchEngine[] listEngines = new SearchEngine[nlist.getLength()];
for (int i = 0; i < nlist.getLength(); i++) { for (int i = 0; i < nlist.getLength(); i++) {
NamedNodeMap nnm = nlist.item(i).getAttributes(); NamedNodeMap nnm = nlist.item(i).getAttributes();
@ -190,8 +196,8 @@ class SearchEngineURLQueryAnalyzer extends Extract {
} }
} }
SearchEngineURLQueryAnalyzer.SearchEngine Se = new SearchEngineURLQueryAnalyzer.SearchEngine(EngineName, EnginedomainSubstring, keys); SearchEngine searchEngine = new SearchEngine(EngineName, EnginedomainSubstring, keys);
listEngines[i] = Se; listEngines[i] = searchEngine;
} }
engines = listEngines; engines = listEngines;
} }
@ -206,7 +212,7 @@ class SearchEngineURLQueryAnalyzer extends Extract {
* is found * is found
* *
*/ */
private static SearchEngineURLQueryAnalyzer.SearchEngine getSearchEngineFromUrl(String domain) { private static SearchEngine getSearchEngineFromUrl(String domain) {
if (engines == null) { if (engines == null) {
return null; return null;
} }
@ -225,32 +231,31 @@ class SearchEngineURLQueryAnalyzer extends Extract {
* *
* @return The extracted search query. * @return The extracted search query.
*/ */
private String extractSearchEngineQuery(SearchEngineURLQueryAnalyzer.SearchEngine eng, String url) { private String extractSearchEngineQuery(SearchEngine eng, String url) {
String x = ""; //NON-NLS String value = ""; //NON-NLS
for (KeyPair kp : eng.getKeys()) { for (KeyPair kp : eng.getKeys()) {
if (url.contains(kp.getKey())) { if (url.contains(kp.getKey())) {
x = getValue(url, kp.getKeyRegExp()); value = getValue(url, kp.getKeyRegExp());
break; break;
} }
} }
try { //try to decode the url try { //try to decode the url
String decoded = URLDecoder.decode(x, "UTF-8"); //NON-NLS return URLDecoder.decode(value, "UTF-8"); //NON-NLS
return decoded;
} catch (UnsupportedEncodingException exception) { //if it fails, return the encoded string } catch (UnsupportedEncodingException exception) { //if it fails, return the encoded string
logger.log(Level.FINE, "Error during URL decoding, returning undecoded value:" logger.log(Level.FINE, "Error during URL decoding, returning undecoded value:"
+ "\n\tURL: " + url + "\n\tURL: " + url
+ "\n\tUndecoded value: " + x + "\n\tUndecoded value: " + value
+ "\n\tEngine name: " + eng.getEngineName() + "\n\tEngine name: " + eng.getEngineName()
+ "\n\tEngine domain: " + eng.getDomainSubstring(), exception); //NON-NLS + "\n\tEngine domain: " + eng.getDomainSubstring(), exception); //NON-NLS
return x; return value;
} catch (IllegalArgumentException exception) { //if it fails, return the encoded string } catch (IllegalArgumentException exception) { //if it fails, return the encoded string
logger.log(Level.SEVERE, "Illegal argument passed to URL decoding, returning undecoded value:" logger.log(Level.SEVERE, "Illegal argument passed to URL decoding, returning undecoded value:"
+ "\n\tURL: " + url + "\n\tURL: " + url
+ "\n\tUndecoded value: " + x + "\n\tUndecoded value: " + value
+ "\n\tEngine name: " + eng.getEngineName() + "\n\tEngine name: " + eng.getEngineName()
+ "\n\tEngine domain: " + eng.getDomainSubstring(), exception); //NON-NLS) + "\n\tEngine domain: " + eng.getDomainSubstring(), exception); //NON-NLS)
return x; return value;
} }
} }
@ -273,126 +278,106 @@ class SearchEngineURLQueryAnalyzer extends Extract {
* at more formal approaches of splitting on the "?" and then on "&" * at more formal approaches of splitting on the "?" and then on "&"
* resulting in missing things. * resulting in missing things.
*/ */
//TODO: What does this old comment mean? : Want to determine if string contains a string based on splitkey, but we want to split the string on splitKeyConverted due to regex
String value = ""; //NON-NLS String value = ""; //NON-NLS
String v = regExpKey;
//Want to determine if string contains a string based on splitkey, but we want to split the string on splitKeyConverted due to regex String[] tokens = url.split(regExpKey.replace("\\?", "?"));
if (regExpKey.contains("\\?")) { if (tokens.length >= 2) {
v = regExpKey.replace("\\?", "?"); if (tokens[tokens.length - 1].contains("&")) {
} value = tokens[tokens.length - 1].split("&")[0];
String[] sp = url.split(v);
if (sp.length >= 2) {
if (sp[sp.length - 1].contains("&")) {
value = sp[sp.length - 1].split("&")[0];
} else { } else {
value = sp[sp.length - 1]; value = tokens[tokens.length - 1];
} }
} }
return value; return value;
} }
private void findSearchQueries() { private void findSearchQueries() {
int totalQueries = 0;
try {
//from blackboard_artifacts
Collection<BlackboardArtifact> listArtifacts = currentCase.getSleuthkitCase().getMatchingArtifacts("WHERE (blackboard_artifacts.artifact_type_id = '" + ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID() //NON-NLS
+ "' OR blackboard_artifacts.artifact_type_id = '" + ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID() + "') "); //List of every 'web_history' and 'bookmark' artifact NON-NLS
logger.log(Level.INFO, "Processing {0} blackboard artifacts.", listArtifacts.size()); //NON-NLS
for (BlackboardArtifact artifact : listArtifacts) { Collection<BlackboardArtifact> sourceArtifacts = new ArrayList<>();
try {
//List of every 'web_history' and 'bookmark'
sourceArtifacts.addAll(tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_WEB_BOOKMARK));
sourceArtifacts.addAll(tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_WEB_HISTORY));
} catch (TskCoreException tskCoreException) {
logger.log(Level.SEVERE, "Error getting TSK_WEB_BOOKMARK or TSK_WEB_HISTORY artifacts", tskCoreException); //NON-NLS
}
logger.log(Level.INFO, "Processing {0} blackboard artifacts.", sourceArtifacts.size()); //NON-NLS
Collection<BlackboardArtifact> queryArtifacts = new ArrayList<>();
for (BlackboardArtifact sourceArtifact : sourceArtifacts) {
if (context.dataSourceIngestIsCancelled()) { if (context.dataSourceIngestIsCancelled()) {
break; //User cancelled the process. break; //User cancelled the process.
} }
long fileId = sourceArtifact.getObjectID();
//initializing default attributes try {
String query = ""; if (false == tskCase.isFileFromSource(dataSource, fileId)) {
String searchEngineDomain = ""; continue; //File was from a different dataSource. Skipping.
String browser = ""; }
long last_accessed = -1; } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Encountered error determining if file " + fileId + "is from datasource " + dataSource.getId(), ex); //NON-NLS
long fileId = artifact.getObjectID();
boolean isFromSource = tskCase.isFileFromSource(dataSource, fileId);
if (!isFromSource) {
//File was from a different dataSource. Skipping.
continue; continue;
} }
AbstractFile file = tskCase.getAbstractFileById(fileId); AbstractFile file;
try {
file = tskCase.getAbstractFileById(fileId);
if (file == null) { if (file == null) {
logger.log(Level.WARNING, "There was no file for id {0}", fileId); //NON-NLS
continue;
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting file for id " + fileId, ex); //NON-NLS
continue; continue;
} }
SearchEngineURLQueryAnalyzer.SearchEngine se = null; try {
//from blackboard_attributes final String urlString = sourceArtifact.getAttribute(new BlackboardAttribute.Type(TSK_URL)).getValueString();
Collection<BlackboardAttribute> listAttributes = currentCase.getSleuthkitCase().getMatchingAttributes("WHERE artifact_id = " + artifact.getArtifactID()); //NON-NLS SearchEngine searchEngine = getSearchEngineFromUrl(urlString);
if (searchEngine == null) { //TODO: should we log this?
for (BlackboardAttribute attribute : listAttributes) { continue;
if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL.getTypeID()) {
final String urlString = attribute.getValueString();
se = getSearchEngineFromUrl(urlString);
if (se == null) {
break;
} }
query = extractSearchEngineQuery(se, attribute.getValueString()); String query = extractSearchEngineQuery(searchEngine, urlString);
if (query.equals("")) //False positive match, artifact was not a query. NON-NLS if (query.isEmpty()) { //False positive match, artifact was not a query.
{ continue;
break;
} }
} else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()) { String browser = sourceArtifact.getAttribute(new BlackboardAttribute.Type(TSK_PROG_NAME)).getValueString();
browser = attribute.getValueString(); String searchEngineDomain = sourceArtifact.getAttribute(new BlackboardAttribute.Type(TSK_DOMAIN)).getValueString();
} else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID()) { long last_accessed = sourceArtifact.getAttribute(new BlackboardAttribute.Type(TSK_DATETIME_ACCESSED)).getValueLong();
searchEngineDomain = attribute.getValueString();
} else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()) { Collection<BlackboardAttribute> bbattributes = Arrays.asList(
last_accessed = attribute.getValueLong(); new BlackboardAttribute(
TSK_DOMAIN, PARENT_MODULE_NAME,
searchEngineDomain),
new BlackboardAttribute(
TSK_TEXT, PARENT_MODULE_NAME,
query),
new BlackboardAttribute(
TSK_PROG_NAME, PARENT_MODULE_NAME,
browser),
new BlackboardAttribute(
TSK_DATETIME_ACCESSED, PARENT_MODULE_NAME,
last_accessed));
BlackboardArtifact bbart = file.newArtifact(TSK_WEB_SEARCH_QUERY);
bbart.addAttributes(bbattributes);
queryArtifacts.add(bbart);
searchEngine.increment();
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Encountered error creating search query artifacts.", ex); //NON-NLS
} }
} }
if (se != null && !query.equals("")) { //NON-NLS try {
// If date doesn't exist, change to 0 (instead of 1969) blackboard.postArtifacts(queryArtifacts, PARENT_MODULE_NAME);
if (last_accessed == -1) { } catch (Blackboard.BlackboardException ex) {
last_accessed = 0; logger.log(Level.SEVERE, "Encountered error posting search query artifacts.", ex); //NON-NLS
}
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
NbBundle.getMessage(this.getClass(),
"SearchEngineURLQueryAnalyzer.parentModuleName"), searchEngineDomain));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEXT,
NbBundle.getMessage(this.getClass(),
"SearchEngineURLQueryAnalyzer.parentModuleName"), query));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME,
NbBundle.getMessage(this.getClass(),
"SearchEngineURLQueryAnalyzer.parentModuleName"), browser));
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
NbBundle.getMessage(this.getClass(),
"SearchEngineURLQueryAnalyzer.parentModuleName"), last_accessed));
this.addArtifact(ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY, file, bbattributes);
se.increment();
++totalQueries;
}
}
} catch (TskCoreException e) {
logger.log(Level.SEVERE, "Encountered error retrieving artifacts for search engine queries", e); //NON-NLS
} finally {
if (context.dataSourceIngestIsCancelled()) {
logger.info("Operation terminated by user."); //NON-NLS
}
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(
NbBundle.getMessage(this.getClass(), "SearchEngineURLQueryAnalyzer.parentModuleName.noSpace"),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_SEARCH_QUERY));
logger.log(Level.INFO, "Extracted {0} queries from the blackboard", totalQueries); //NON-NLS
}
} }
private String getTotals() { logger.log(Level.INFO, "Extracted {0} queries from the blackboard", queryArtifacts.size()); //NON-NLS
String total = "";
if (engines == null) {
return total;
}
for (SearchEngineURLQueryAnalyzer.SearchEngine se : engines) {
total += se.getEngineName() + " : " + se.getTotal() + "\n";
}
return total;
} }
@Override @Override
@ -400,13 +385,20 @@ class SearchEngineURLQueryAnalyzer extends Extract {
this.dataSource = dataSource; this.dataSource = dataSource;
this.context = context; this.context = context;
this.findSearchQueries(); this.findSearchQueries();
logger.log(Level.INFO, "Search Engine stats: \n{0}", getTotals()); //NON-NLS
String totals = "";
for (SearchEngine se : engines) {
totals += se.getEngineName() + " : " + se.getTotal() + "\n";
}
logger.log(Level.INFO, "Search Engine stats: \n{0}", totals); //NON-NLS
} }
@Override @Override
void configExtractor() throws IngestModuleException { void configExtractor() throws IngestModuleException {
try { try {
PlatformUtil.extractResourceToUserConfigDir(SearchEngineURLQueryAnalyzer.class, XMLFILE, true); PlatformUtil.extractResourceToUserConfigDir(SearchEngineURLQueryExtractor.class,
XMLFILE, true);
} catch (IOException e) { } catch (IOException e) {
String message = Bundle.SearchEngineURLQueryAnalyzer_init_exception_msg(XMLFILE); String message = Bundle.SearchEngineURLQueryAnalyzer_init_exception_msg(XMLFILE);
logger.log(Level.SEVERE, message, e); logger.log(Level.SEVERE, message, e);

View File

@ -1,4 +1,4 @@
/* /*
* *
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
@ -22,7 +22,6 @@
*/ */
package org.sleuthkit.autopsy.recentactivity; package org.sleuthkit.autopsy.recentactivity;
import org.sleuthkit.autopsy.coreutils.SQLiteDBConnect;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
@ -35,14 +34,16 @@ import java.sql.ResultSet;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.casemodule.services.FileManager;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.SQLiteDBConnect;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
@ -71,32 +72,24 @@ class Util {
} }
public static String readFile(String path) throws IOException { public static String readFile(String path) throws IOException {
FileInputStream stream = new FileInputStream(new File(path)); try (FileInputStream stream = new FileInputStream(new File(path))) {
try {
FileChannel fc = stream.getChannel(); FileChannel fc = stream.getChannel();
MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
/* /*
* Instead of using default, pass in a decoder. * Instead of using default, pass in a decoder.
*/ */
return Charset.defaultCharset().decode(bb).toString(); return Charset.defaultCharset().decode(bb).toString();
} finally {
stream.close();
} }
} }
public static String getBaseDomain(String url) { public static String getBaseDomain(String url) {
String host = null; //TODO: There is no utility in apache or guave to do this for us?
//strip protocol //strip protocol
String cleanUrl = url.replaceFirst(".*:\\/\\/", ""); String cleanUrl = url.replaceFirst(".*:\\/\\/", "");
//strip after slashes //strip after slashes
String dirToks[] = cleanUrl.split("\\/"); String dirToks[] = cleanUrl.split("\\/");
if (dirToks.length > 0) { String host = (dirToks.length > 0) ? dirToks[0] : cleanUrl;
host = dirToks[0];
} else {
host = cleanUrl;
}
//get the domain part from host (last 2) //get the domain part from host (last 2)
StringTokenizer tok = new StringTokenizer(host, "."); StringTokenizer tok = new StringTokenizer(host, ".");
@ -118,6 +111,8 @@ class Util {
} }
public static String extractDomain(String value) { public static String extractDomain(String value) {
//TODO: There is no utility in apache or guave to do this for us?
if (value == null) { if (value == null) {
return ""; return "";
@ -207,31 +202,17 @@ class Util {
public static boolean checkColumn(String column, String tablename, String connection) { public static boolean checkColumn(String column, String tablename, String connection) {
String query = "PRAGMA table_info(" + tablename + ")"; //NON-NLS String query = "PRAGMA table_info(" + tablename + ")"; //NON-NLS
boolean found = false;
ResultSet temprs; try (SQLiteDBConnect tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", "jdbc:sqlite:" + connection); //NON-NLS
try { ResultSet temprs = tempdbconnect.executeQry(query);) {
SQLiteDBConnect tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", "jdbc:sqlite:" + connection); //NON-NLS
temprs = tempdbconnect.executeQry(query);
while (temprs.next()) { while (temprs.next()) {
if (temprs.getString("name") == null ? column == null : temprs.getString("name").equals(column)) { //NON-NLS if (Objects.equals(temprs.getString("name"), column)) { //NON-NLS
found = true; return true;
} }
} }
} catch (Exception ex) { } catch (Exception ex) {
logger.log(Level.WARNING, "Error while trying to get columns from sqlite db." + connection, ex); //NON-NLS logger.log(Level.WARNING, "Error while trying to get columns from sqlite db." + connection, ex); //NON-NLS
} }
return found; return false;
}
public static ResultSet runQuery(String query, String connection) {
ResultSet results = null;
try {
SQLiteDBConnect tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", "jdbc:sqlite:" + connection); //NON-NLS
results = tempdbconnect.executeQry(query);
tempdbconnect.closeConnection();
} catch (Exception ex) {
logger.log(Level.WARNING, "Error while trying to run sql query: " + query + " : " + connection, ex); //NON-NLS
}
return results;
} }
} }