mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 18:17:43 +00:00
Merge branch 'postArtifacts_recent_activity' into postArtifacts_fallout_2
This commit is contained in:
commit
740e1b0e9a
@ -30,7 +30,7 @@ import java.sql.Statement;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* Database connection class & utilities *
|
||||
* Database connection class & utilities.
|
||||
*/
|
||||
public class SQLiteDBConnect implements AutoCloseable {
|
||||
|
||||
@ -127,6 +127,7 @@ public class SQLiteDBConnect implements AutoCloseable {
|
||||
} catch (SQLException 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
|
||||
|
@ -34,13 +34,10 @@ import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
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.IngestModule;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.FsContent;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.DataSourceIngestModule;
|
||||
|
@ -80,8 +80,8 @@ public class PlasoIngestModule implements DataSourceIngestModule {
|
||||
@NbBundle.Messages({
|
||||
"PlasoIngestModule_error_running=Error running Plaso, see log file.",
|
||||
"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
|
||||
public void startUp(IngestJobContext context) throws IngestModuleException {
|
||||
this.context = context;
|
||||
@ -111,8 +111,8 @@ public class PlasoIngestModule implements DataSourceIngestModule {
|
||||
"PlasoIngestModule_running_log2timeline=Running Log2timeline",
|
||||
"PlasoIngestModule_running_psort=Running Psort",
|
||||
"PlasoIngestModule_completed=Plaso Processing Completed",
|
||||
"PlasoIngestModule_has_run=Plaso Plugin has been run.",})
|
||||
|
||||
"PlasoIngestModule_has_run=Plaso Plugin has been run."
|
||||
})
|
||||
@Override
|
||||
public ProcessResult process(Content dataSource, DataSourceIngestModuleProgress statusHelper) {
|
||||
statusHelper.switchToIndeterminate();
|
||||
|
@ -63,6 +63,15 @@
|
||||
<specification-version>10.12</specification-version>
|
||||
</run-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>
|
||||
<public-packages>
|
||||
<package>org.sleuthkit.autopsy.recentactivity</package>
|
||||
|
@ -83,6 +83,7 @@ RAImageIngestModule.complete.errMsg.failed={0} failed to complete - see log for
|
||||
RAImageIngestModule.getName=Recent Activity
|
||||
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.errCreatingArtifact={0}\: Error creating Recent Document artifact.
|
||||
RecentDocumentsByLnk.getRecDoc.errParsingFile={0}\: Error parsing Recent File {1}
|
||||
RecentDocumentsByLnk.parentModuleName.noSpace=RecentActivity
|
||||
RecentDocumentsByLnk.parentModuleName=Recent Activity
|
||||
|
@ -22,30 +22,43 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.recentactivity;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonIOException;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
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.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
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.datamodel.ContentUtils;
|
||||
import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
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 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_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.ReadContentInputStream.ReadContentInputStreamException;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
@ -54,20 +67,25 @@ import org.sleuthkit.datamodel.TskData;
|
||||
/**
|
||||
* 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
|
||||
+ "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 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 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 IngestJobContext context;
|
||||
|
||||
Chrome() {
|
||||
moduleName = NbBundle.getMessage(Chrome.class, "Chrome.moduleName");
|
||||
@Override
|
||||
protected String getModuleName() {
|
||||
return NbBundle.getMessage(Chrome.class, "Chrome.moduleName");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -85,15 +103,17 @@ class Chrome extends Extract {
|
||||
/**
|
||||
* 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() {
|
||||
FileManager fileManager = currentCase.getServices().getFileManager();
|
||||
|
||||
List<AbstractFile> historyFiles;
|
||||
try {
|
||||
historyFiles = fileManager.findFiles(dataSource, "History", "Chrome"); //NON-NLS
|
||||
} 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);
|
||||
this.addErrorMessage(this.getName() + ": " + msg);
|
||||
this.addErrorMessage(this.getModuleName() + ": " + msg);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -107,11 +127,12 @@ class Chrome extends Extract {
|
||||
|
||||
// log a message if we don't have any allocated history files
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO why are we using historyFiles instead of allocatedHistoryfiles here?
|
||||
dataFound = true;
|
||||
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
|
||||
int j = 0;
|
||||
@ -126,14 +147,14 @@ class Chrome extends Extract {
|
||||
} catch (ReadContentInputStreamException ex) {
|
||||
logger.log(Level.WARNING, String.format("Error reading Chrome web history artifacts file '%s' (id=%d).",
|
||||
historyFile.getName(), historyFile.getId()), ex); //NON-NLS
|
||||
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getHistory.errMsg.errAnalyzingFile",
|
||||
this.getName(), historyFile.getName()));
|
||||
this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getHistory.errMsg.errAnalyzingFile",
|
||||
this.getModuleName(), historyFile.getName()));
|
||||
continue;
|
||||
} 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).",
|
||||
temps, historyFile.getName(), historyFile.getId()), ex); //NON-NLS
|
||||
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getHistory.errMsg.errAnalyzingFile",
|
||||
this.getName(), historyFile.getName()));
|
||||
this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getHistory.errMsg.errAnalyzingFile",
|
||||
this.getModuleName(), historyFile.getName()));
|
||||
continue;
|
||||
}
|
||||
File dbFile = new File(temps);
|
||||
@ -143,53 +164,57 @@ class Chrome extends Extract {
|
||||
}
|
||||
List<HashMap<String, Object>> tempList;
|
||||
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) {
|
||||
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
|
||||
((result.get("url").toString() != null) ? result.get("url").toString() : ""))); //NON-NLS
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
|
||||
(Long.valueOf(result.get("last_visit_time").toString()) / 1000000) - Long.valueOf("11644473600"))); //NON-NLS
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER,
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
|
||||
((result.get("from_visit").toString() != null) ? result.get("from_visit").toString() : ""))); //NON-NLS
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
|
||||
((result.get("title").toString() != null) ? result.get("title").toString() : ""))); //NON-NLS
|
||||
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"),
|
||||
(Util.extractDomain((result.get("url").toString() != null) ? result.get("url").toString() : "")))); //NON-NLS
|
||||
|
||||
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, historyFile, bbattributes);
|
||||
if (bbart != null) {
|
||||
Collection<BlackboardAttribute> bbattributes = Arrays.asList(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("last_visit_time").toString()) / 1000000) - SECONDS_SINCE_JAN_1_1601),
|
||||
new BlackboardAttribute(
|
||||
TSK_REFERRER, PARENT_MODULE_NAME,
|
||||
Objects.toString(result.get("from_visit"), "")), //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(ARTIFACT_TYPE.TSK_WEB_HISTORY);
|
||||
bbart.addAttributes(bbattributes);
|
||||
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();
|
||||
}
|
||||
|
||||
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, bbartifacts));
|
||||
try {
|
||||
blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
|
||||
} catch (Blackboard.BlackboardException ex) {
|
||||
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.
|
||||
*/
|
||||
private void getBookmark() {
|
||||
FileManager fileManager = currentCase.getServices().getFileManager();
|
||||
List<AbstractFile> bookmarkFiles;
|
||||
try {
|
||||
bookmarkFiles = fileManager.findFiles(dataSource, "Bookmarks", "Chrome"); //NON-NLS
|
||||
} 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);
|
||||
this.addErrorMessage(this.getName() + ": " + msg);
|
||||
this.addErrorMessage(this.getModuleName() + ": " + msg);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -200,31 +225,30 @@ class Chrome extends Extract {
|
||||
|
||||
dataFound = true;
|
||||
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
|
||||
int j = 0;
|
||||
|
||||
while (j < bookmarkFiles.size()) {
|
||||
AbstractFile bookmarkFile = bookmarkFiles.get(j++);
|
||||
int index = 0;
|
||||
while (index < bookmarkFiles.size()) {
|
||||
AbstractFile bookmarkFile = bookmarkFiles.get(index++);
|
||||
if (bookmarkFile.getSize() == 0) {
|
||||
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 {
|
||||
ContentUtils.writeToFile(bookmarkFile, new File(temps), context::dataSourceIngestIsCancelled);
|
||||
} catch (ReadContentInputStreamException ex) {
|
||||
logger.log(Level.WARNING, String.format("Error reading Chrome bookmark artifacts file '%s' (id=%d).",
|
||||
bookmarkFile.getName(), bookmarkFile.getId()), ex); //NON-NLS
|
||||
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getBookmark.errMsg.errAnalyzingFile",
|
||||
this.getName(), bookmarkFile.getName()));
|
||||
this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getBookmark.errMsg.errAnalyzingFile",
|
||||
this.getModuleName(), bookmarkFile.getName()));
|
||||
continue;
|
||||
} catch (IOException ex) {
|
||||
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
|
||||
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getBookmark.errMsg.errAnalyzingFile",
|
||||
this.getName(), bookmarkFile.getName()));
|
||||
this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getBookmark.errMsg.errAnalyzingFile",
|
||||
this.getModuleName(), bookmarkFile.getName()));
|
||||
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);
|
||||
if (context.dataSourceIngestIsCancelled()) {
|
||||
dbFile.delete();
|
||||
@ -236,8 +260,7 @@ class Chrome extends Extract {
|
||||
tempReader = new FileReader(temps);
|
||||
} catch (FileNotFoundException ex) {
|
||||
logger.log(Level.SEVERE, "Error while trying to read into the Bookmarks for Chrome.", ex); //NON-NLS
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.getBookmark.errMsg.errAnalyzeFile", this.getName(),
|
||||
this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getBookmark.errMsg.errAnalyzeFile", this.getModuleName(),
|
||||
bookmarkFile.getName()));
|
||||
continue;
|
||||
}
|
||||
@ -255,8 +278,8 @@ class Chrome extends Extract {
|
||||
jBookmarkArray = jBookmark.getAsJsonArray("children"); //NON-NLS
|
||||
} catch (JsonIOException | JsonSyntaxException | IllegalStateException ex) {
|
||||
logger.log(Level.WARNING, "Error parsing Json from Chrome Bookmark.", ex); //NON-NLS
|
||||
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getBookmark.errMsg.errAnalyzingFile3",
|
||||
this.getName(), bookmarkFile.getName()));
|
||||
this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getBookmark.errMsg.errAnalyzingFile3",
|
||||
this.getModuleName(), bookmarkFile.getName()));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -288,58 +311,52 @@ class Chrome extends Extract {
|
||||
}
|
||||
String domain = Util.extractDomain(url);
|
||||
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);
|
||||
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);
|
||||
|
||||
// index the artifact for keyword search
|
||||
this.indexArtifact(bbart);
|
||||
bbartifacts.add(bbart);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error while trying to insert Chrome bookmark artifact{0}", ex); //NON-NLS
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.getBookmark.errMsg.errAnalyzingFile4",
|
||||
this.getName(), bookmarkFile.getName()));
|
||||
logger.log(Level.SEVERE, "Error while trying to insert Chrome bookmark artifact.", ex); //NON-NLS
|
||||
this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getBookmark.errMsg.errAnalyzingFile4",
|
||||
this.getModuleName(), bookmarkFile.getName()));
|
||||
}
|
||||
}
|
||||
dbFile.delete();
|
||||
}
|
||||
|
||||
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bbartifacts));
|
||||
try {
|
||||
blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
|
||||
} catch (Blackboard.BlackboardException ex) {
|
||||
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
|
||||
*/
|
||||
private void getCookie() {
|
||||
|
||||
FileManager fileManager = currentCase.getServices().getFileManager();
|
||||
List<AbstractFile> cookiesFiles;
|
||||
try {
|
||||
cookiesFiles = fileManager.findFiles(dataSource, "Cookies", "Chrome"); //NON-NLS
|
||||
} 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);
|
||||
this.addErrorMessage(this.getName() + ": " + msg);
|
||||
this.addErrorMessage(this.getModuleName() + ": " + msg);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -350,26 +367,26 @@ class Chrome extends Extract {
|
||||
|
||||
dataFound = true;
|
||||
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
|
||||
int j = 0;
|
||||
while (j < cookiesFiles.size()) {
|
||||
AbstractFile cookiesFile = cookiesFiles.get(j++);
|
||||
int index = 0;
|
||||
while (index < cookiesFiles.size()) {
|
||||
AbstractFile cookiesFile = cookiesFiles.get(index++);
|
||||
if (cookiesFile.getSize() == 0) {
|
||||
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 {
|
||||
ContentUtils.writeToFile(cookiesFile, new File(temps), context::dataSourceIngestIsCancelled);
|
||||
} catch (ReadContentInputStreamException ex) {
|
||||
logger.log(Level.WARNING, String.format("Error reading Chrome cookie artifacts file '%s' (id=%d).",
|
||||
cookiesFile.getName(), cookiesFile.getId()), ex); //NON-NLS
|
||||
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getCookie.errMsg.errAnalyzeFile",
|
||||
this.getName(), cookiesFile.getName()));
|
||||
this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getCookie.errMsg.errAnalyzeFile",
|
||||
this.getModuleName(), cookiesFile.getName()));
|
||||
continue;
|
||||
} catch (IOException ex) {
|
||||
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
|
||||
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getCookie.errMsg.errAnalyzeFile",
|
||||
this.getName(), cookiesFile.getName()));
|
||||
this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getCookie.errMsg.errAnalyzeFile",
|
||||
this.getModuleName(), cookiesFile.getName()));
|
||||
continue;
|
||||
}
|
||||
File dbFile = new File(temps);
|
||||
@ -379,56 +396,60 @@ class Chrome extends Extract {
|
||||
}
|
||||
|
||||
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) {
|
||||
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
|
||||
domain = domain.replaceFirst("^\\.+(?!$)", "");
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), domain));
|
||||
|
||||
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
|
||||
if (bbart != null) {
|
||||
Collection<BlackboardAttribute> bbattributes = Arrays.asList(new BlackboardAttribute(
|
||||
TSK_DOMAIN, PARENT_MODULE_NAME,
|
||||
domain),
|
||||
new BlackboardAttribute(
|
||||
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);
|
||||
} 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();
|
||||
}
|
||||
|
||||
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE, bbartifacts));
|
||||
try {
|
||||
blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
|
||||
} catch (Blackboard.BlackboardException ex) {
|
||||
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
|
||||
*/
|
||||
private void getDownload() {
|
||||
FileManager fileManager = currentCase.getServices().getFileManager();
|
||||
List<AbstractFile> downloadFiles;
|
||||
try {
|
||||
downloadFiles = fileManager.findFiles(dataSource, "History", "Chrome"); //NON-NLS
|
||||
} 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);
|
||||
this.addErrorMessage(this.getName() + ": " + msg);
|
||||
this.addErrorMessage(this.getModuleName() + ": " + msg);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -439,26 +460,26 @@ class Chrome extends Extract {
|
||||
|
||||
dataFound = true;
|
||||
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
|
||||
int j = 0;
|
||||
while (j < downloadFiles.size()) {
|
||||
AbstractFile downloadFile = downloadFiles.get(j++);
|
||||
int index = 0;
|
||||
while (index < downloadFiles.size()) {
|
||||
AbstractFile downloadFile = downloadFiles.get(index++);
|
||||
if (downloadFile.getSize() == 0) {
|
||||
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 {
|
||||
ContentUtils.writeToFile(downloadFile, new File(temps), context::dataSourceIngestIsCancelled);
|
||||
} catch (ReadContentInputStreamException ex) {
|
||||
logger.log(Level.WARNING, String.format("Error reading Chrome download artifacts file '%s' (id=%d).",
|
||||
downloadFile.getName(), downloadFile.getId()), ex); //NON-NLS
|
||||
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getDownload.errMsg.errAnalyzeFiles1",
|
||||
this.getName(), downloadFile.getName()));
|
||||
this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getDownload.errMsg.errAnalyzeFiles1",
|
||||
this.getModuleName(), downloadFile.getName()));
|
||||
continue;
|
||||
} catch (IOException ex) {
|
||||
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
|
||||
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getDownload.errMsg.errAnalyzeFiles1",
|
||||
this.getName(), downloadFile.getName()));
|
||||
this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getDownload.errMsg.errAnalyzeFiles1",
|
||||
this.getModuleName(), downloadFile.getName()));
|
||||
continue;
|
||||
}
|
||||
File dbFile = new File(temps);
|
||||
@ -467,68 +488,65 @@ class Chrome extends Extract {
|
||||
break;
|
||||
}
|
||||
|
||||
List<HashMap<String, Object>> tempList;
|
||||
List<HashMap<String, Object>> tempList = this.dbConnect(temps,
|
||||
(isChromePreVersion30(temps)) ? DOWNLOAD_QUERY : DOWNLOAD_QUERY_V30);
|
||||
|
||||
if (isChromePreVersion30(temps)) {
|
||||
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
|
||||
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) {
|
||||
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"), (result.get("full_path").toString()))); //NON-NLS
|
||||
|
||||
Collection<BlackboardAttribute> bbattributes = Lists.newArrayList(new BlackboardAttribute(
|
||||
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
|
||||
if (pathID != -1) {
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"Chrome.parentModuleName"), pathID));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID, PARENT_MODULE_NAME, pathID));
|
||||
}
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
|
||||
((result.get("url").toString() != null) ? result.get("url").toString() : ""))); //NON-NLS
|
||||
//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) {
|
||||
try {
|
||||
BlackboardArtifact bbart = downloadFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD);
|
||||
bbart.addAttributes(bbattributes);
|
||||
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();
|
||||
}
|
||||
|
||||
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, bbartifacts));
|
||||
try {
|
||||
blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
|
||||
} catch (Blackboard.BlackboardException ex) {
|
||||
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
|
||||
*/
|
||||
private void getLogin() {
|
||||
FileManager fileManager = currentCase.getServices().getFileManager();
|
||||
List<AbstractFile> signonFiles;
|
||||
try {
|
||||
signonFiles = fileManager.findFiles(dataSource, "signons.sqlite", "Chrome"); //NON-NLS
|
||||
} 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);
|
||||
this.addErrorMessage(this.getName() + ": " + msg);
|
||||
this.addErrorMessage(this.getModuleName() + ": " + msg);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -539,26 +557,26 @@ class Chrome extends Extract {
|
||||
|
||||
dataFound = true;
|
||||
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
|
||||
int j = 0;
|
||||
while (j < signonFiles.size()) {
|
||||
AbstractFile signonFile = signonFiles.get(j++);
|
||||
int index = 0;
|
||||
while (index < signonFiles.size()) {
|
||||
AbstractFile signonFile = signonFiles.get(index++);
|
||||
if (signonFile.getSize() == 0) {
|
||||
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 {
|
||||
ContentUtils.writeToFile(signonFile, new File(temps), context::dataSourceIngestIsCancelled);
|
||||
} catch (ReadContentInputStreamException ex) {
|
||||
logger.log(Level.WARNING, String.format("Error reading Chrome login artifacts file '%s' (id=%d).",
|
||||
signonFile.getName(), signonFile.getId()), ex); //NON-NLS
|
||||
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getLogin.errMsg.errAnalyzingFiles",
|
||||
this.getName(), signonFile.getName()));
|
||||
this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getLogin.errMsg.errAnalyzingFiles",
|
||||
this.getModuleName(), signonFile.getName()));
|
||||
continue;
|
||||
} catch (IOException ex) {
|
||||
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
|
||||
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Chrome.getLogin.errMsg.errAnalyzingFiles",
|
||||
this.getName(), signonFile.getName()));
|
||||
this.addErrorMessage(NbBundle.getMessage(Chrome.class, "Chrome.getLogin.errMsg.errAnalyzingFiles",
|
||||
this.getModuleName(), signonFile.getName()));
|
||||
continue;
|
||||
}
|
||||
File dbFile = new File(temps);
|
||||
@ -567,67 +585,78 @@ class Chrome extends Extract {
|
||||
break;
|
||||
}
|
||||
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) {
|
||||
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
|
||||
((result.get("origin_url").toString() != null) ? result.get("origin_url").toString() : ""))); //NON-NLS
|
||||
//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()) : "")));
|
||||
//TODO Revisit usage of deprecated constructor as per TSK-583
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID(), "Recent Activity", "Last Visited", ((Long.valueOf(result.get("last_visit_time").toString())) / 1000000)));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
|
||||
(Long.valueOf(result.get("last_visit_time").toString()) / 1000000) - Long.valueOf("11644473600"))); //NON-NLS
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER,
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
|
||||
((result.get("from_visit").toString() != null) ? result.get("from_visit").toString() : ""))); //NON-NLS
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
|
||||
((result.get("title").toString() != null) ? result.get("title").toString() : ""))); //NON-NLS
|
||||
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_URL_DECODED,
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
|
||||
(Util.extractDomain((result.get("origin_url").toString() != null) ? result.get("url").toString() : "")))); //NON-NLS
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
|
||||
((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
|
||||
Collection<BlackboardAttribute> bbattributes = Arrays.asList(new BlackboardAttribute(
|
||||
TSK_URL, PARENT_MODULE_NAME,
|
||||
Objects.toString(result.get("origin_url"), "")), //NON-NLS
|
||||
new BlackboardAttribute(
|
||||
TSK_DATETIME_ACCESSED, PARENT_MODULE_NAME,
|
||||
(Long.valueOf(result.get("last_visit_time").toString()) / 1000000) - SECONDS_SINCE_JAN_1_1601), //NON-NLS
|
||||
new BlackboardAttribute(
|
||||
TSK_REFERRER, PARENT_MODULE_NAME,
|
||||
Objects.toString(result.get("from_visit"), "")), //NON-NLS
|
||||
new BlackboardAttribute(
|
||||
TSK_NAME, PARENT_MODULE_NAME,
|
||||
Objects.toString(result.get("title").toString(), "")), //NON-NLS
|
||||
new BlackboardAttribute(
|
||||
TSK_PROG_NAME, PARENT_MODULE_NAME,
|
||||
getModuleName()),
|
||||
new BlackboardAttribute(
|
||||
TSK_URL_DECODED, PARENT_MODULE_NAME,
|
||||
Util.extractDomain(Objects.toString(result.get("origin_url"), ""))), //NON-NLS
|
||||
new BlackboardAttribute(
|
||||
TSK_USER_NAME, PARENT_MODULE_NAME,
|
||||
Objects.toString(result.get("username_value"), "").replaceAll("'", "''")), //NON-NLS
|
||||
new BlackboardAttribute(
|
||||
TSK_DOMAIN, PARENT_MODULE_NAME,
|
||||
Objects.toString(result.get("signon_realm"), ""))); //NON-NLS
|
||||
|
||||
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY, signonFile, bbattributes);
|
||||
if (bbart != null) {
|
||||
try {
|
||||
BlackboardArtifact bbart = signonFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY);
|
||||
bbart.addAttributes(bbattributes);
|
||||
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
|
||||
Collection<BlackboardAttribute> osAcctAttributes = new ArrayList<>();
|
||||
osAcctAttributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
|
||||
((result.get("username_value").toString() != null) ? result.get("username_value").toString().replaceAll("'", "''") : ""))); //NON-NLS
|
||||
this.addArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT, signonFile, osAcctAttributes);
|
||||
//TODO: Why not? Because it has a different artifact type? We can just post it seperately?
|
||||
try {
|
||||
BlackboardAttribute osAcctAttribute = new BlackboardAttribute(TSK_USER_NAME, PARENT_MODULE_NAME,
|
||||
Objects.toString(result.get("username_value"), "").replaceAll("'", "''")); //NON-NLS
|
||||
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();
|
||||
}
|
||||
|
||||
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(
|
||||
NbBundle.getMessage(this.getClass(), "Chrome.parentModuleName"),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, bbartifacts));
|
||||
try {
|
||||
blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
|
||||
} 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) {
|
||||
String query = "PRAGMA table_info(downloads)"; //NON-NLS
|
||||
List<HashMap<String, Object>> columns = this.dbConnect(temps, query);
|
||||
for (HashMap<String, Object> col : columns) {
|
||||
if (col.get("name").equals("url")) { //NON-NLS
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return columns.stream()
|
||||
.anyMatch(col -> "url".equals(col.get("name")));
|
||||
}
|
||||
}
|
||||
|
@ -31,8 +31,8 @@ import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.casemodule.services.FileManager;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.SQLiteDBConnect;
|
||||
import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException;
|
||||
@ -40,21 +40,33 @@ import org.sleuthkit.datamodel.*;
|
||||
|
||||
abstract class Extract {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(Extract.class.getName());
|
||||
|
||||
protected Case currentCase;
|
||||
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<>();
|
||||
String moduleName = "";
|
||||
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 {
|
||||
try {
|
||||
currentCase = Case.getCurrentCaseThrows();
|
||||
tskCase = currentCase.getSleuthkitCase();
|
||||
blackboard = tskCase.getBlackboard();
|
||||
fileManager = currentCase.getServices().getFileManager();
|
||||
} catch (NoCurrentCaseException ex) {
|
||||
//TODO: fix this error message
|
||||
throw new IngestModuleException(Bundle.Extract_indexError_message(), ex);
|
||||
}
|
||||
configExtractor();
|
||||
@ -91,54 +103,25 @@ abstract class Extract {
|
||||
errorMessages.add(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic method for adding a blackboard artifact to the blackboard and
|
||||
* indexing it
|
||||
*
|
||||
* @param type is a blackboard.artifact_type enum to determine which
|
||||
* type the artifact should be
|
||||
* @param content is the AbstractFile object that needs to have the
|
||||
* artifact added for it
|
||||
* @param bbattributes is the collection of blackboard attributes that need
|
||||
* to be added to the artifact after the artifact has
|
||||
* been created
|
||||
*
|
||||
* @return The newly-created artifact, or null on error
|
||||
*/
|
||||
protected BlackboardArtifact addArtifact(BlackboardArtifact.ARTIFACT_TYPE type, AbstractFile content, Collection<BlackboardAttribute> bbattributes) {
|
||||
try {
|
||||
BlackboardArtifact bbart = content.newArtifact(type);
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// /**
|
||||
// * Method to index a blackboard artifact for keyword search
|
||||
// *
|
||||
// * @param bbart Blackboard artifact to be indexed
|
||||
// */
|
||||
//
|
||||
// void postArtifacts(Collections<BlackboardArtifact> bbarts) throws Blackboard.BlackboardException {
|
||||
//
|
||||
// // index the artifact for keyword search
|
||||
// blackboard.postArtifact(bbarts, getModuleName());
|
||||
//// } 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
|
||||
* query sqlite databases storing user recent activity data, such as in
|
||||
@ -151,20 +134,16 @@ abstract class Extract {
|
||||
* it that the query obtained
|
||||
*/
|
||||
protected List<HashMap<String, Object>> dbConnect(String path, String query) {
|
||||
ResultSet temprs;
|
||||
List<HashMap<String, Object>> list;
|
||||
|
||||
String connectionString = "jdbc:sqlite:" + path; //NON-NLS
|
||||
try {
|
||||
SQLiteDBConnect tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", connectionString); //NON-NLS
|
||||
temprs = tempdbconnect.executeQry(query);
|
||||
list = this.resultSetToArrayList(temprs);
|
||||
tempdbconnect.closeConnection();
|
||||
try (SQLiteDBConnect tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", connectionString); //NON-NLS
|
||||
ResultSet temprs = tempdbconnect.executeQry(query);) {
|
||||
return this.resultSetToArrayList(temprs);
|
||||
} catch (SQLException ex) {
|
||||
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 list;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -193,15 +172,6 @@ abstract class Extract {
|
||||
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() {
|
||||
return dataFound;
|
||||
}
|
||||
|
@ -22,10 +22,9 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.recentactivity;
|
||||
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Sets;
|
||||
import java.io.BufferedReader;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.ExecUtil;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
@ -34,29 +33,46 @@ import java.io.InputStreamReader;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
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.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
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.casemodule.services.FileManager;
|
||||
import org.sleuthkit.autopsy.coreutils.ExecUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProcessTerminator;
|
||||
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
|
||||
@ -65,18 +81,23 @@ import org.sleuthkit.datamodel.*;
|
||||
class ExtractIE extends Extract {
|
||||
|
||||
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 String PASCO_LIB_PATH;
|
||||
private final String JAVA_PATH;
|
||||
private static final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
|
||||
private final String JAVA_PATH = PlatformUtil.getJavaPath();
|
||||
|
||||
private Content dataSource;
|
||||
private IngestJobContext context;
|
||||
|
||||
ExtractIE() throws NoCurrentCaseException {
|
||||
moduleName = NbBundle.getMessage(ExtractIE.class, "ExtractIE.moduleName.text");
|
||||
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
|
||||
@ -93,7 +114,6 @@ class ExtractIE extends Extract {
|
||||
* Finds the files storing bookmarks and creates artifacts
|
||||
*/
|
||||
private void getBookmark() {
|
||||
org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
|
||||
List<AbstractFile> favoritesFiles;
|
||||
try {
|
||||
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
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.getBookmark.errMsg.errGettingBookmarks",
|
||||
this.getName()));
|
||||
this.getModuleName()));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -121,89 +141,73 @@ class ExtractIE extends Extract {
|
||||
break;
|
||||
}
|
||||
|
||||
String url = getURLFromIEBookmarkFile(fav);
|
||||
|
||||
String name = fav.getName();
|
||||
Long datetime = fav.getCrtime();
|
||||
String Tempdate = datetime.toString();
|
||||
datetime = Long.valueOf(Tempdate);
|
||||
String domain = Util.extractDomain(url);
|
||||
|
||||
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"ExtractIE.parentModuleName.noSpace"), url));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TITLE,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"ExtractIE.parentModuleName.noSpace"), name));
|
||||
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) {
|
||||
Collection<BlackboardAttribute> bbattributes = Arrays.asList(
|
||||
new BlackboardAttribute(
|
||||
TSK_URL, PARENT_MODULE_NAME, getURLFromIEBookmarkFile(fav)),
|
||||
new BlackboardAttribute(
|
||||
TSK_TITLE, PARENT_MODULE_NAME, fav.getName()),
|
||||
new BlackboardAttribute(
|
||||
TSK_DATETIME_CREATED, PARENT_MODULE_NAME, fav.getCrtime()),
|
||||
new BlackboardAttribute(
|
||||
TSK_PROG_NAME, PARENT_MODULE_NAME,
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.moduleName.text")),
|
||||
new BlackboardAttribute(
|
||||
TSK_DOMAIN, PARENT_MODULE_NAME, Util.extractDomain(getURLFromIEBookmarkFile(fav))));
|
||||
try {
|
||||
BlackboardArtifact bbart = fav.newArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK);
|
||||
bbart.addAttributes(bbattributes);
|
||||
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(
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName"),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bbartifacts));
|
||||
try {
|
||||
blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
|
||||
} 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) {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(new ReadContentInputStream(fav)));
|
||||
String line, url = "";
|
||||
try {
|
||||
line = reader.readLine();
|
||||
while (null != line) {
|
||||
String line;
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new ReadContentInputStream(fav)));) {
|
||||
while (null != (line = reader.readLine())) {
|
||||
// The actual shortcut line we are interested in is of the
|
||||
// form URL=http://path/to/website
|
||||
if (line.startsWith("URL")) { //NON-NLS
|
||||
url = line.substring(line.indexOf("=") + 1);
|
||||
break;
|
||||
return StringUtils.substringAfter(line, "="); //NON-NLS
|
||||
}
|
||||
line = reader.readLine();
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, "Failed to read from content: " + fav.getName(), ex); //NON-NLS
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.getURLFromIEBmkFile.errMsg", this.getName(),
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.getURLFromIEBmkFile.errMsg", this.getModuleName(),
|
||||
fav.getName()));
|
||||
} 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
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.getURLFromIEBmkFile.errMsg2", this.getName(),
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.getURLFromIEBmkFile.errMsg2", this.getModuleName(),
|
||||
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.
|
||||
*/
|
||||
private void getCookie() {
|
||||
org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
|
||||
List<AbstractFile> cookiesFiles;
|
||||
try {
|
||||
cookiesFiles = fileManager.findFiles(dataSource, "%.txt", "Cookies"); //NON-NLS
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error getting cookie files for IE"); //NON-NLS
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.getCookie.errMsg.errGettingFile", this.getName()));
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.getCookie.errMsg.errGettingFile", this.getModuleName()));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -222,54 +226,56 @@ class ExtractIE extends Extract {
|
||||
continue;
|
||||
}
|
||||
|
||||
byte[] t = new byte[(int) cookiesFile.getSize()];
|
||||
byte[] cookiesBuffer = new byte[(int) cookiesFile.getSize()];
|
||||
try {
|
||||
final int bytesRead = cookiesFile.read(t, 0, cookiesFile.getSize());
|
||||
cookiesFile.read(cookiesBuffer, 0, cookiesFile.getSize());
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Error reading bytes of Internet Explorer cookie.", ex); //NON-NLS
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.getCookie.errMsg.errReadingIECookie",
|
||||
this.getName(), cookiesFile.getName()));
|
||||
this.getModuleName(), cookiesFile.getName()));
|
||||
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<>();
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"ExtractIE.parentModuleName.noSpace"), url));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"ExtractIE.parentModuleName.noSpace"), datetime));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"ExtractIE.parentModuleName.noSpace"), (name != null) ? name : ""));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"ExtractIE.parentModuleName.noSpace"), value));
|
||||
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_COOKIE, cookiesFile, bbattributes);
|
||||
if (bbart != null) {
|
||||
String[] values = new String(cookiesBuffer).split("\n");
|
||||
String URL = values.length > 2 ? values[2] : "";
|
||||
|
||||
Collection<BlackboardAttribute> bbattributes = Arrays.asList(
|
||||
new BlackboardAttribute(
|
||||
TSK_DATETIME, PARENT_MODULE_NAME,
|
||||
cookiesFile.getCrtime()),
|
||||
new BlackboardAttribute(
|
||||
TSK_NAME, PARENT_MODULE_NAME,
|
||||
values.length > 0 ? values[0] : ""),
|
||||
new BlackboardAttribute(
|
||||
TSK_VALUE, PARENT_MODULE_NAME,
|
||||
values.length > 1 ? values[1] : ""),
|
||||
new BlackboardAttribute(
|
||||
TSK_URL, PARENT_MODULE_NAME,
|
||||
URL),
|
||||
new BlackboardAttribute(
|
||||
TSK_PROG_NAME, PARENT_MODULE_NAME,
|
||||
getModuleName()),
|
||||
new BlackboardAttribute(
|
||||
TSK_DOMAIN, PARENT_MODULE_NAME,
|
||||
Util.extractDomain(URL)));
|
||||
try {
|
||||
BlackboardArtifact bbart = cookiesFile.newArtifact(TSK_WEB_COOKIE);
|
||||
bbart.addAttributes(bbattributes);
|
||||
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(
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName"),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE, bbartifacts));
|
||||
try {
|
||||
blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
|
||||
} 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() {
|
||||
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
|
||||
if (pascoRoot == null) {
|
||||
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
|
||||
return;
|
||||
}
|
||||
@ -290,20 +296,20 @@ class ExtractIE extends Extract {
|
||||
final String pascoHome = pascoRoot.getAbsolutePath();
|
||||
logger.log(Level.INFO, "Pasco2 home: {0}", pascoHome); //NON-NLS
|
||||
|
||||
PASCO_LIB_PATH = pascoHome + File.separator + "pasco2.jar" + File.pathSeparator //NON-NLS
|
||||
+ pascoHome + File.separator + "*";
|
||||
String pascoLibPath = pascoHome + File.separator + "pasco2.jar" + File.pathSeparator //NON-NLS
|
||||
+ pascoHome + File.separator + "*";
|
||||
|
||||
File resultsDir = new File(moduleTempResultsDir);
|
||||
resultsDir.mkdirs();
|
||||
|
||||
// get index.dat files
|
||||
org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
|
||||
FileManager fileManager = currentCase.getServices().getFileManager();
|
||||
List<AbstractFile> indexFiles;
|
||||
try {
|
||||
indexFiles = fileManager.findFiles(dataSource, "index.dat"); //NON-NLS
|
||||
} catch (TskCoreException ex) {
|
||||
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
|
||||
return;
|
||||
}
|
||||
@ -315,18 +321,21 @@ class ExtractIE extends Extract {
|
||||
}
|
||||
|
||||
dataFound = true;
|
||||
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
|
||||
String temps;
|
||||
String indexFileName;
|
||||
boolean foundHistory = false;
|
||||
Collection<BlackboardArtifact> historyArtifacts = new ArrayList<>();
|
||||
Collection<BlackboardArtifact> accountArtifacts = new ArrayList<>();
|
||||
|
||||
for (AbstractFile indexFile : indexFiles) {
|
||||
// Since each result represent an index.dat file,
|
||||
// just create these files with the following notation:
|
||||
// index<Number>.dat (i.e. index0.dat, index1.dat,..., indexN.dat)
|
||||
// Write each index.dat file to a temp directory.
|
||||
//BlackboardArtifact bbart = fsc.newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY);
|
||||
indexFileName = "index" + Integer.toString((int) indexFile.getId()) + ".dat"; //NON-NLS
|
||||
//indexFileName = "index" + Long.toString(bbart.getArtifactID()) + ".dat";
|
||||
temps = RAImageIngestModule.getRATempPath(currentCase, "IE") + File.separator + indexFileName; //NON-NLS
|
||||
/* Since each result represent an index.dat file, just create these
|
||||
* files with the following notation: index<Number>.dat (i.e.
|
||||
* index0.dat, index1.dat,..., indexN.dat) Write each index.dat file
|
||||
* to a temp directory.
|
||||
*
|
||||
* TODO: this comment is not accurate. It implies we use an
|
||||
* sequential id number but actualy we use the file id from the db.
|
||||
*/
|
||||
String indexFileName = "index" + indexFile.getId() + ".dat"; //NON-NLS
|
||||
String temps = RAImageIngestModule.getRATempPath(currentCase, "IE") + File.separator + indexFileName; //NON-NLS
|
||||
File datFile = new File(temps);
|
||||
if (context.dataSourceIngestIsCancelled()) {
|
||||
break;
|
||||
@ -336,39 +345,48 @@ class ExtractIE extends Extract {
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.WARNING, "Error while trying to write index.dat file " + datFile.getAbsolutePath(), e); //NON-NLS
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.errWriteFile", this.getName(),
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.errWriteFile", this.getModuleName(),
|
||||
datFile.getAbsolutePath()));
|
||||
continue;
|
||||
}
|
||||
|
||||
String filename = "pasco2Result." + indexFile.getId() + ".txt"; //NON-NLS
|
||||
boolean bPascProcSuccess = executePasco(temps, filename);
|
||||
boolean bPascProcSuccess = executePasco(pascoLibPath, temps, filename);
|
||||
if (context.dataSourceIngestIsCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//At this point pasco2 proccessed the index files.
|
||||
//Now fetch the results, parse them and the delete the files.
|
||||
//At this point pasco2 proccessed the index file.
|
||||
//Now fetch the results, parse them and the delete the file.
|
||||
if (bPascProcSuccess) {
|
||||
// Don't add TSK_OS_ACCOUNT artifacts to the ModuleDataEvent
|
||||
bbartifacts.addAll(parsePascoOutput(indexFile, filename).stream()
|
||||
.filter(bbart -> bbart.getArtifactTypeID() == ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID())
|
||||
.collect(Collectors.toList()));
|
||||
HashMultimap<ARTIFACT_TYPE, BlackboardArtifact> artifacts = parsePascoOutput(indexFile, filename);
|
||||
historyArtifacts.addAll(artifacts.get(TSK_WEB_HISTORY));
|
||||
accountArtifacts.addAll(artifacts.get(TSK_OS_ACCOUNT));
|
||||
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();
|
||||
} 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(
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.errProcHist", this.getName()));
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.getHistory.errMsg.errProcHist", this.getModuleName()));
|
||||
}
|
||||
}
|
||||
|
||||
if (foundHistory) {
|
||||
services.fireModuleDataEvent(new ModuleDataEvent(
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.parentModuleName"),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, bbartifacts));
|
||||
try {
|
||||
blackboard.postArtifacts(historyArtifacts, PARENT_MODULE_NAME);
|
||||
} 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 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;
|
||||
try {
|
||||
final String outputFileFullPath = moduleTempResultsDir + File.separator + outputFileName;
|
||||
final String errFileFullPath = moduleTempResultsDir + File.separator + outputFileName + ".err"; //NON-NLS
|
||||
logger.log(Level.INFO, "Writing pasco results to: {0}", outputFileFullPath); //NON-NLS
|
||||
List<String> commandLine = new ArrayList<>();
|
||||
commandLine.add(JAVA_PATH);
|
||||
commandLine.add("-cp"); //NON-NLS
|
||||
commandLine.add(PASCO_LIB_PATH);
|
||||
commandLine.add("isi.pasco2.Main"); //NON-NLS
|
||||
commandLine.add("-T"); //NON-NLS
|
||||
commandLine.add("history"); //NON-NLS
|
||||
commandLine.add(indexFilePath);
|
||||
List<String> commandLine = Arrays.asList(
|
||||
JAVA_PATH,
|
||||
"-cp",//NON-NLS
|
||||
pascoLibraryPath,
|
||||
"isi.pasco2.Main", //NON-NLS
|
||||
"-T", //NON-NLS
|
||||
"history", //NON-NLS
|
||||
indexFilePath);
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
|
||||
processBuilder.redirectOutput(new File(outputFileFullPath));
|
||||
processBuilder.redirectError(new File(errFileFullPath));
|
||||
@ -424,15 +442,15 @@ class ExtractIE extends Extract {
|
||||
*
|
||||
* @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;
|
||||
|
||||
File file = new File(fnAbs);
|
||||
if (file.exists() == false) {
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.notFound", this.getName(),
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.notFound", this.getModuleName(),
|
||||
file.getName()));
|
||||
logger.log(Level.WARNING, "Pasco Output not found: {0}", file.getPath()); //NON-NLS
|
||||
return bbartifacts;
|
||||
@ -443,123 +461,118 @@ class ExtractIE extends Extract {
|
||||
if (file.length() == 0) {
|
||||
return bbartifacts;
|
||||
}
|
||||
try (Scanner fileScanner = new Scanner(new FileInputStream(file.toString()));) {
|
||||
|
||||
Scanner fileScanner;
|
||||
try {
|
||||
fileScanner = new Scanner(new FileInputStream(file.toString()));
|
||||
// Keep a list of reported user accounts to avoid repeats.
|
||||
// Initialize it with the empty string to represent an unknown user.
|
||||
Set<String> reportedUserAccounts = Sets.newHashSet("");
|
||||
while (fileScanner.hasNext()) {
|
||||
String line = fileScanner.nextLine();
|
||||
if (!line.startsWith("URL")) { //NON-NLS
|
||||
continue;
|
||||
}
|
||||
|
||||
String[] lineBuff = line.split("\\t"); //NON-NLS
|
||||
|
||||
if (lineBuff.length < 4) {
|
||||
logger.log(Level.INFO, "Found unrecognized IE history format."); //NON-NLS
|
||||
continue;
|
||||
}
|
||||
|
||||
String actime = lineBuff[3];
|
||||
Long ftime = (long) 0;
|
||||
String user;
|
||||
String realurl;
|
||||
String domain;
|
||||
|
||||
/*
|
||||
* We've seen two types of lines: URL http://XYZ.com .... URL
|
||||
* Visited: Joe@http://XYZ.com ....
|
||||
*/
|
||||
if (lineBuff[1].contains("@")) {
|
||||
String url[] = lineBuff[1].split("@", 2);
|
||||
user = url[0];
|
||||
user = user.replace("Visited:", ""); //NON-NLS
|
||||
user = user.replace(":Host:", ""); //NON-NLS
|
||||
user = user.replaceAll(":(.*?):", "");
|
||||
user = user.trim();
|
||||
realurl = url[1];
|
||||
realurl = realurl.replace("Visited:", ""); //NON-NLS
|
||||
realurl = realurl.replaceAll(":(.*?):", "");
|
||||
realurl = realurl.replace(":Host:", ""); //NON-NLS
|
||||
realurl = realurl.trim();
|
||||
} else {
|
||||
user = "";
|
||||
realurl = lineBuff[1].trim();
|
||||
}
|
||||
|
||||
domain = Util.extractDomain(realurl);
|
||||
|
||||
if (!actime.isEmpty()) {
|
||||
try {
|
||||
Long epochtime = new SimpleDateFormat(PASCO_DATE_FORMAT).parse(actime).getTime();
|
||||
ftime = epochtime / 1000;
|
||||
} catch (ParseException e) {
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.errParsingEntry",
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
BlackboardArtifact bbart = origFile.newArtifact(TSK_WEB_HISTORY);
|
||||
bbart.addAttributes(bbattributes);
|
||||
bbartifacts.put(TSK_WEB_HISTORY, bbart);
|
||||
} catch (TskCoreException ex) {
|
||||
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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return bbartifacts;
|
||||
} catch (FileNotFoundException ex) {
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.errParsing", this.getName(),
|
||||
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;
|
||||
}
|
||||
|
||||
// Keep a list of reported user accounts to avoid repeats
|
||||
Set<String> reportedUserAccounts = new HashSet<>();
|
||||
|
||||
while (fileScanner.hasNext()) {
|
||||
String line = fileScanner.nextLine();
|
||||
if (!line.startsWith("URL")) { //NON-NLS
|
||||
continue;
|
||||
}
|
||||
|
||||
String[] lineBuff = line.split("\\t"); //NON-NLS
|
||||
|
||||
if (lineBuff.length < 4) {
|
||||
logger.log(Level.INFO, "Found unrecognized IE history format."); //NON-NLS
|
||||
continue;
|
||||
}
|
||||
|
||||
String actime = lineBuff[3];
|
||||
Long ftime = (long) 0;
|
||||
String user;
|
||||
String realurl;
|
||||
String domain;
|
||||
|
||||
/*
|
||||
* We've seen two types of lines: URL http://XYZ.com .... URL
|
||||
* Visited: Joe@http://XYZ.com ....
|
||||
*/
|
||||
if (lineBuff[1].contains("@")) {
|
||||
String url[] = lineBuff[1].split("@", 2);
|
||||
user = url[0];
|
||||
user = user.replace("Visited:", ""); //NON-NLS
|
||||
user = user.replace(":Host:", ""); //NON-NLS
|
||||
user = user.replaceAll("(:)(.*?)(:)", "");
|
||||
user = user.trim();
|
||||
realurl = url[1];
|
||||
realurl = realurl.replace("Visited:", ""); //NON-NLS
|
||||
realurl = realurl.replaceAll(":(.*?):", "");
|
||||
realurl = realurl.replace(":Host:", ""); //NON-NLS
|
||||
realurl = realurl.trim();
|
||||
} else {
|
||||
user = "";
|
||||
realurl = lineBuff[1].trim();
|
||||
}
|
||||
|
||||
domain = Util.extractDomain(realurl);
|
||||
|
||||
if (!actime.isEmpty()) {
|
||||
try {
|
||||
Long epochtime = dateFormatter.parse(actime).getTime();
|
||||
ftime = epochtime / 1000;
|
||||
} catch (ParseException e) {
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "ExtractIE.parsePascoOutput.errMsg.errParsingEntry",
|
||||
this.getName()));
|
||||
logger.log(Level.WARNING, String.format("Error parsing Pasco results, may have partial processing of corrupt file (id=%d)", origFile.getId()), e); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
BlackboardArtifact bbart = origFile.newArtifact(ARTIFACT_TYPE.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);
|
||||
|
||||
// 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) {
|
||||
logger.log(Level.SEVERE, "Error writing Internet Explorer web history artifact to the blackboard.", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
fileScanner.close();
|
||||
return bbartifacts;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
@ -22,28 +22,42 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.recentactivity;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.services.FileManager;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.datamodel.ContentUtils;
|
||||
import org.sleuthkit.autopsy.ingest.IngestJobContext;
|
||||
import org.sleuthkit.autopsy.ingest.IngestServices;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.Blackboard;
|
||||
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.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.ReadContentInputStream.ReadContentInputStreamException;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
@ -51,21 +65,25 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
/**
|
||||
* 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 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 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_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 IngestJobContext context;
|
||||
|
||||
Firefox() {
|
||||
moduleName = NbBundle.getMessage(Firefox.class, "Firefox.moduleName");
|
||||
@Override
|
||||
protected String getModuleName() {
|
||||
return NbBundle.getMessage(FirefoxExtractor.class, "Firefox.moduleName");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -75,19 +93,19 @@ class Firefox extends Extract {
|
||||
dataFound = false;
|
||||
this.getHistory();
|
||||
this.getBookmark();
|
||||
this.getDownload();
|
||||
getDownloadPreVersion24();
|
||||
getDownloadVersion24();
|
||||
this.getCookie();
|
||||
}
|
||||
|
||||
private void getHistory() {
|
||||
FileManager fileManager = currentCase.getServices().getFileManager();
|
||||
List<AbstractFile> historyFiles;
|
||||
try {
|
||||
historyFiles = fileManager.findFiles(dataSource, "places.sqlite", "Firefox"); //NON-NLS
|
||||
} catch (TskCoreException ex) {
|
||||
String msg = NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errFetchingFiles");
|
||||
logger.log(Level.WARNING, msg);
|
||||
this.addErrorMessage(this.getName() + ": " + msg);
|
||||
this.addErrorMessage(this.getModuleName() + ": " + msg);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -99,28 +117,28 @@ class Firefox extends Extract {
|
||||
|
||||
dataFound = true;
|
||||
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
|
||||
int j = 0;
|
||||
int index = 0;
|
||||
for (AbstractFile historyFile : historyFiles) {
|
||||
if (historyFile.getSize() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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 {
|
||||
ContentUtils.writeToFile(historyFile, new File(temps), context::dataSourceIngestIsCancelled);
|
||||
} catch (ReadContentInputStreamException ex) {
|
||||
logger.log(Level.WARNING, String.format("Error reading Firefox web history artifacts file '%s' (id=%d).",
|
||||
fileName, historyFile.getId()), ex); //NON-NLS
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getModuleName(),
|
||||
fileName));
|
||||
continue;
|
||||
} 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).",
|
||||
temps, fileName, historyFile.getId()), ex); //NON-NLS
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getModuleName(),
|
||||
fileName));
|
||||
continue;
|
||||
}
|
||||
@ -130,61 +148,61 @@ class Firefox extends Extract {
|
||||
break;
|
||||
}
|
||||
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) {
|
||||
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);
|
||||
if (bbart != null) {
|
||||
Collection<BlackboardAttribute> bbattributes = Arrays.asList(
|
||||
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);
|
||||
} 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();
|
||||
}
|
||||
|
||||
services.fireModuleDataEvent(new ModuleDataEvent(
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, bbartifacts));
|
||||
try {
|
||||
blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
|
||||
} catch (Blackboard.BlackboardException ex) {
|
||||
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
|
||||
*/
|
||||
private void getBookmark() {
|
||||
|
||||
FileManager fileManager = currentCase.getServices().getFileManager();
|
||||
List<AbstractFile> bookmarkFiles;
|
||||
try {
|
||||
bookmarkFiles = fileManager.findFiles(dataSource, "places.sqlite", "Firefox"); //NON-NLS
|
||||
} catch (TskCoreException ex) {
|
||||
String msg = NbBundle.getMessage(this.getClass(), "Firefox.getBookmark.errMsg.errFetchFiles");
|
||||
logger.log(Level.WARNING, msg);
|
||||
this.addErrorMessage(this.getName() + ": " + msg);
|
||||
this.addErrorMessage(this.getModuleName() + ": " + msg);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -195,27 +213,27 @@ class Firefox extends Extract {
|
||||
|
||||
dataFound = true;
|
||||
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
|
||||
int j = 0;
|
||||
int index = 0;
|
||||
for (AbstractFile bookmarkFile : bookmarkFiles) {
|
||||
if (bookmarkFile.getSize() == 0) {
|
||||
continue;
|
||||
}
|
||||
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 {
|
||||
ContentUtils.writeToFile(bookmarkFile, new File(temps), context::dataSourceIngestIsCancelled);
|
||||
} catch (ReadContentInputStreamException ex) {
|
||||
logger.log(Level.WARNING, String.format("Error reading Firefox bookmark artifacts file '%s' (id=%d).",
|
||||
fileName, bookmarkFile.getId()), ex); //NON-NLS
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getModuleName(),
|
||||
fileName));
|
||||
continue;
|
||||
} catch (IOException ex) {
|
||||
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
|
||||
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getBookmark.errMsg.errAnalyzeFile",
|
||||
this.getName(), fileName));
|
||||
this.getModuleName(), fileName));
|
||||
continue;
|
||||
}
|
||||
File dbFile = new File(temps);
|
||||
@ -224,59 +242,61 @@ class Firefox extends Extract {
|
||||
break;
|
||||
}
|
||||
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) {
|
||||
|
||||
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_TITLE,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"Firefox.parentModuleName.noSpace"),
|
||||
((result.get("title").toString() != null) ? result.get("title").toString() : ""))); //NON-NLS
|
||||
if (Long.valueOf(result.get("dateAdded").toString()) > 0) { //NON-NLS
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"Firefox.parentModuleName.noSpace"),
|
||||
(Long.valueOf(result.get("dateAdded").toString())))); //NON-NLS
|
||||
Collection<BlackboardAttribute> bbattributes = Lists.newArrayList(
|
||||
new BlackboardAttribute(
|
||||
TSK_URL, PARENT_MODULE_NAME,
|
||||
Objects.toString(result.get("url"), "")), //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
|
||||
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,
|
||||
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_BOOKMARK, bookmarkFile, bbattributes);
|
||||
if (bbart != null) {
|
||||
try {
|
||||
BlackboardArtifact bbart = bookmarkFile.newArtifact(TSK_WEB_BOOKMARK);
|
||||
bbart.addAttributes(bbattributes);
|
||||
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();
|
||||
}
|
||||
|
||||
services.fireModuleDataEvent(new ModuleDataEvent(
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bbartifacts));
|
||||
try {
|
||||
blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
|
||||
} catch (Blackboard.BlackboardException ex) {
|
||||
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
|
||||
*/
|
||||
private void getCookie() {
|
||||
FileManager fileManager = currentCase.getServices().getFileManager();
|
||||
List<AbstractFile> cookiesFiles;
|
||||
try {
|
||||
cookiesFiles = fileManager.findFiles(dataSource, "cookies.sqlite", "Firefox"); //NON-NLS
|
||||
} catch (TskCoreException ex) {
|
||||
String msg = NbBundle.getMessage(this.getClass(), "Firefox.getCookie.errMsg.errFetchFile");
|
||||
logger.log(Level.WARNING, msg);
|
||||
this.addErrorMessage(this.getName() + ": " + msg);
|
||||
this.addErrorMessage(this.getModuleName() + ": " + msg);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -287,27 +307,27 @@ class Firefox extends Extract {
|
||||
|
||||
dataFound = true;
|
||||
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
|
||||
int j = 0;
|
||||
int index = 0;
|
||||
for (AbstractFile cookiesFile : cookiesFiles) {
|
||||
if (cookiesFile.getSize() == 0) {
|
||||
continue;
|
||||
}
|
||||
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 {
|
||||
ContentUtils.writeToFile(cookiesFile, new File(temps), context::dataSourceIngestIsCancelled);
|
||||
} catch (ReadContentInputStreamException ex) {
|
||||
logger.log(Level.WARNING, String.format("Error reading Firefox cookie artifacts file '%s' (id=%d).",
|
||||
fileName, cookiesFile.getId()), ex); //NON-NLS
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getModuleName(),
|
||||
fileName));
|
||||
continue;
|
||||
} catch (IOException ex) {
|
||||
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
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.getCookie.errMsg.errAnalyzeFile", this.getName(),
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.getCookie.errMsg.errAnalyzeFile", this.getModuleName(),
|
||||
fileName));
|
||||
continue;
|
||||
}
|
||||
@ -317,71 +337,57 @@ class Firefox extends Extract {
|
||||
break;
|
||||
}
|
||||
boolean checkColumn = Util.checkColumn("creationTime", "moz_cookies", temps); //NON-NLS
|
||||
String query;
|
||||
if (checkColumn) {
|
||||
query = COOKIE_QUERY;
|
||||
} else {
|
||||
query = COOKIE_QUERY_V3;
|
||||
}
|
||||
String query = checkColumn ? COOKIE_QUERY : COOKIE_QUERY_V3;
|
||||
|
||||
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) {
|
||||
|
||||
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"Firefox.parentModuleName.noSpace"),
|
||||
((result.get("host").toString() != null) ? result.get("host").toString() : ""))); //NON-NLS
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"Firefox.parentModuleName.noSpace"),
|
||||
(Long.valueOf(result.get("lastAccessed").toString())))); //NON-NLS
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"Firefox.parentModuleName.noSpace"),
|
||||
((result.get("name").toString() != null) ? result.get("name").toString() : ""))); //NON-NLS
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"Firefox.parentModuleName.noSpace"),
|
||||
((result.get("value").toString() != null) ? result.get("value").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")));
|
||||
|
||||
if (checkColumn == true) {
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"Firefox.parentModuleName.noSpace"),
|
||||
Collection<BlackboardAttribute> bbattributes = Lists.newArrayList(
|
||||
new BlackboardAttribute(
|
||||
TSK_URL, PARENT_MODULE_NAME,
|
||||
Objects.toString(result.get("host"), "")), //NON-NLS
|
||||
new BlackboardAttribute(
|
||||
TSK_DATETIME, PARENT_MODULE_NAME,
|
||||
Long.valueOf(result.get("lastAccessed").toString())), //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()),
|
||||
new BlackboardAttribute(
|
||||
TSK_DOMAIN, PARENT_MODULE_NAME,
|
||||
Util.extractDomain(result.get("host").toString()).replaceFirst("^\\.+(?!$)", ""))); //NON-NLS
|
||||
if (checkColumn) {
|
||||
bbattributes.add(new BlackboardAttribute(
|
||||
TSK_DATETIME_CREATED, PARENT_MODULE_NAME,
|
||||
(Long.valueOf(result.get("creationTime").toString())))); //NON-NLS
|
||||
}
|
||||
String domain = Util.extractDomain(result.get("host").toString()); //NON-NLS
|
||||
domain = domain.replaceFirst("^\\.+(?!$)", "");
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"Firefox.parentModuleName.noSpace"), domain));
|
||||
|
||||
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_COOKIE, cookiesFile, bbattributes);
|
||||
if (bbart != null) {
|
||||
try {
|
||||
BlackboardArtifact bbart = cookiesFile.newArtifact(TSK_WEB_COOKIE);
|
||||
bbart.addAttributes(bbattributes);
|
||||
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();
|
||||
}
|
||||
|
||||
services.fireModuleDataEvent(new ModuleDataEvent(
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE, bbartifacts));
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries for downloads files and adds artifacts
|
||||
*/
|
||||
private void getDownload() {
|
||||
getDownloadPreVersion24();
|
||||
getDownloadVersion24();
|
||||
try {
|
||||
blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
|
||||
} 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()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -391,14 +397,13 @@ class Firefox extends Extract {
|
||||
*/
|
||||
private void getDownloadPreVersion24() {
|
||||
|
||||
FileManager fileManager = currentCase.getServices().getFileManager();
|
||||
List<AbstractFile> downloadsFiles;
|
||||
try {
|
||||
downloadsFiles = fileManager.findFiles(dataSource, "downloads.sqlite", "Firefox"); //NON-NLS
|
||||
} catch (TskCoreException ex) {
|
||||
String msg = NbBundle.getMessage(this.getClass(), "Firefox.getDlPre24.errMsg.errFetchFiles");
|
||||
logger.log(Level.WARNING, msg);
|
||||
this.addErrorMessage(this.getName() + ": " + msg);
|
||||
this.addErrorMessage(this.getModuleName() + ": " + msg);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -409,13 +414,13 @@ class Firefox extends Extract {
|
||||
|
||||
dataFound = true;
|
||||
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
|
||||
int j = 0;
|
||||
int index = 0;
|
||||
for (AbstractFile downloadsFile : downloadsFiles) {
|
||||
if (downloadsFile.getSize() == 0) {
|
||||
continue;
|
||||
}
|
||||
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;
|
||||
try {
|
||||
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).",
|
||||
fileName, downloadsFile.getId()), ex); //NON-NLS
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getModuleName(),
|
||||
fileName));
|
||||
continue;
|
||||
} catch (IOException ex) {
|
||||
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
|
||||
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getDlPre24.errMsg.errAnalyzeFiles",
|
||||
this.getName(), fileName));
|
||||
this.getModuleName(), fileName));
|
||||
continue;
|
||||
}
|
||||
File dbFile = new File(temps);
|
||||
@ -440,70 +445,63 @@ class Firefox extends Extract {
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
|
||||
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"Firefox.parentModuleName.noSpace"),
|
||||
((result.get("source").toString() != null) ? result.get("source").toString() : ""))); //NON-NLS
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL_DECODED.getTypeID(), "RecentActivity", ((result.get("source").toString() != null) ? EscapeUtil.decodeURL(result.get("source").toString()) : "")));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"Firefox.parentModuleName.noSpace"),
|
||||
(Long.valueOf(result.get("startTime").toString())))); //NON-NLS
|
||||
Collection<BlackboardAttribute> bbattributes = Lists.newArrayList(
|
||||
new BlackboardAttribute(TSK_URL, PARENT_MODULE_NAME,
|
||||
Objects.toString(result.get("source"), "")), //NON-NLS
|
||||
new BlackboardAttribute(TSK_DATETIME_ACCESSED, PARENT_MODULE_NAME,
|
||||
Long.valueOf(result.get("startTime").toString())), //NON-NLS
|
||||
new BlackboardAttribute(TSK_PROG_NAME, PARENT_MODULE_NAME,
|
||||
getModuleName()),
|
||||
new BlackboardAttribute(TSK_DOMAIN, PARENT_MODULE_NAME,
|
||||
Util.extractDomain(Objects.toString(result.get("source"), "")))); //NON-NLS
|
||||
|
||||
String target = result.get("target").toString(); //NON-NLS
|
||||
|
||||
if (target != null) {
|
||||
try {
|
||||
String decodedTarget = URLDecoder.decode(target.replaceAll("file:///", ""), "UTF-8"); //NON-NLS
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"Firefox.parentModuleName.noSpace"),
|
||||
decodedTarget));
|
||||
long pathID = Util.findID(dataSource, decodedTarget);
|
||||
if (pathID != -1) {
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"Firefox.parentModuleName.noSpace"),
|
||||
pathID));
|
||||
}
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
logger.log(Level.SEVERE, "Error decoding Firefox download URL in " + temps, ex); //NON-NLS
|
||||
errors++;
|
||||
try {
|
||||
String decodedTarget = URLDecoder.decode(target.replaceAll("file:///", ""), "UTF-8"); //NON-NLS
|
||||
bbattributes.add(new BlackboardAttribute(
|
||||
TSK_PATH, PARENT_MODULE_NAME,
|
||||
decodedTarget));
|
||||
long pathID = Util.findID(dataSource, decodedTarget);
|
||||
if (pathID != -1) {
|
||||
bbattributes.add(new BlackboardAttribute(
|
||||
TSK_PATH_ID, PARENT_MODULE_NAME,
|
||||
pathID));
|
||||
}
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
logger.log(Level.SEVERE, "Error decoding Firefox download URL in " + temps, ex); //NON-NLS
|
||||
errors++;
|
||||
}
|
||||
try {
|
||||
|
||||
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("source").toString() != null) ? result.get("source").toString() : "")))); //NON-NLS
|
||||
|
||||
BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, downloadsFile, bbattributes);
|
||||
if (bbart != null) {
|
||||
BlackboardArtifact bbart = downloadsFile.newArtifact(TSK_WEB_DOWNLOAD);
|
||||
bbart.addAttributes(bbattributes);
|
||||
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) {
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.getDlPre24.errMsg.errParsingArtifacts",
|
||||
this.getName(), errors));
|
||||
this.getModuleName(), errors));
|
||||
}
|
||||
j++;
|
||||
index++;
|
||||
dbFile.delete();
|
||||
break;
|
||||
}
|
||||
|
||||
services.fireModuleDataEvent(new ModuleDataEvent(
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, bbartifacts));
|
||||
try {
|
||||
blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
|
||||
} 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.
|
||||
*/
|
||||
private void getDownloadVersion24() {
|
||||
FileManager fileManager = currentCase.getServices().getFileManager();
|
||||
List<AbstractFile> downloadsFiles;
|
||||
try {
|
||||
downloadsFiles = fileManager.findFiles(dataSource, "places.sqlite", "Firefox"); //NON-NLS
|
||||
} catch (TskCoreException ex) {
|
||||
String msg = NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errFetchFiles");
|
||||
logger.log(Level.WARNING, msg);
|
||||
this.addErrorMessage(this.getName() + ": " + msg);
|
||||
this.addErrorMessage(this.getModuleName() + ": " + msg);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -530,13 +527,13 @@ class Firefox extends Extract {
|
||||
|
||||
dataFound = true;
|
||||
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
|
||||
int j = 0;
|
||||
int index = 0;
|
||||
for (AbstractFile downloadsFile : downloadsFiles) {
|
||||
if (downloadsFile.getSize() == 0) {
|
||||
continue;
|
||||
}
|
||||
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;
|
||||
try {
|
||||
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).",
|
||||
fileName, downloadsFile.getId()), ex); //NON-NLS
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getName(),
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.getHistory.errMsg.errAnalyzeFile", this.getModuleName(),
|
||||
fileName));
|
||||
continue;
|
||||
} catch (IOException ex) {
|
||||
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
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errAnalyzeFile", this.getName(),
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errAnalyzeFile", this.getModuleName(),
|
||||
fileName));
|
||||
continue;
|
||||
}
|
||||
@ -563,68 +560,66 @@ class Firefox extends Extract {
|
||||
|
||||
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) {
|
||||
|
||||
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("source").toString() != null) ? EscapeUtil.decodeURL(result.get("source").toString()) : "")));
|
||||
//TODO Revisit usage of deprecated constructor as per TSK-583
|
||||
//bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", "Last Visited", (Long.valueOf(result.get("startTime").toString()))));
|
||||
Collection<BlackboardAttribute> bbattributes = Lists.newArrayList(
|
||||
new BlackboardAttribute(
|
||||
TSK_URL, PARENT_MODULE_NAME,
|
||||
result.get("url").toString()), //NON-NLS
|
||||
new BlackboardAttribute(
|
||||
TSK_DATETIME_ACCESSED, PARENT_MODULE_NAME,
|
||||
Long.valueOf(result.get("lastModified").toString())), //NON-NLS
|
||||
new BlackboardAttribute(
|
||||
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
|
||||
if (target != null) {
|
||||
try {
|
||||
String decodedTarget = URLDecoder.decode(target.replaceAll("file:///", ""), "UTF-8"); //NON-NLS
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"Firefox.parentModuleName.noSpace"),
|
||||
decodedTarget));
|
||||
long pathID = Util.findID(dataSource, decodedTarget);
|
||||
if (pathID != -1) {
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"Firefox.parentModuleName.noSpace"),
|
||||
pathID));
|
||||
}
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
logger.log(Level.SEVERE, "Error decoding Firefox download URL in " + temps, ex); //NON-NLS
|
||||
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);
|
||||
if (bbart != null) {
|
||||
try {
|
||||
String decodedTarget = URLDecoder.decode(target.replaceAll("file:///", ""), "UTF-8"); //NON-NLS
|
||||
bbattributes.add(new BlackboardAttribute(
|
||||
TSK_PATH, PARENT_MODULE_NAME,
|
||||
decodedTarget));
|
||||
long pathID = Util.findID(dataSource, decodedTarget);
|
||||
if (pathID != -1) {
|
||||
bbattributes.add(new BlackboardAttribute(
|
||||
TSK_PATH_ID, PARENT_MODULE_NAME,
|
||||
pathID));
|
||||
}
|
||||
} catch (UnsupportedEncodingException ex) {
|
||||
logger.log(Level.SEVERE, "Error decoding Firefox download URL in " + temps, ex); //NON-NLS
|
||||
errors++;
|
||||
}
|
||||
|
||||
try {
|
||||
BlackboardArtifact bbart = downloadsFile.newArtifact(TSK_WEB_DOWNLOAD);
|
||||
bbart.addAttributes(bbattributes);
|
||||
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) {
|
||||
this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getDlV24.errMsg.errParsingArtifacts",
|
||||
this.getName(), errors));
|
||||
this.getModuleName(), errors));
|
||||
}
|
||||
j++;
|
||||
index++;
|
||||
dbFile.delete();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
services.fireModuleDataEvent(new ModuleDataEvent(
|
||||
NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, bbartifacts));
|
||||
try {
|
||||
blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
|
||||
} 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()));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
@ -23,7 +23,6 @@
|
||||
package org.sleuthkit.autopsy.recentactivity;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
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.ingest.DataSourceIngestModule;
|
||||
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.MessageType;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
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
|
||||
@ -48,12 +47,8 @@ public final class RAImageIngestModule implements DataSourceIngestModule {
|
||||
private static final Logger logger = Logger.getLogger(RAImageIngestModule.class.getName());
|
||||
private final List<Extract> extracters = new ArrayList<>();
|
||||
private final List<Extract> browserExtracters = new ArrayList<>();
|
||||
private IngestServices services = IngestServices.getInstance();
|
||||
private final IngestServices services = IngestServices.getInstance();
|
||||
private IngestJobContext context;
|
||||
private StringBuilder subCompleted = new StringBuilder();
|
||||
|
||||
RAImageIngestModule() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startUp(IngestJobContext context) throws IngestModuleException {
|
||||
@ -67,10 +62,10 @@ public final class RAImageIngestModule implements DataSourceIngestModule {
|
||||
}
|
||||
|
||||
Extract registry = new ExtractRegistry();
|
||||
Extract recentDocuments = new RecentDocumentsByLnk();
|
||||
Extract recentDocuments = new RecentDocumentsLnkExtractor();
|
||||
Extract chrome = new Chrome();
|
||||
Extract firefox = new Firefox();
|
||||
Extract SEUQA = new SearchEngineURLQueryAnalyzer();
|
||||
Extract firefox = new FirefoxExtractor();
|
||||
Extract SEUQA = new SearchEngineURLQueryExtractor();
|
||||
|
||||
extracters.add(chrome);
|
||||
extracters.add(firefox);
|
||||
@ -102,18 +97,16 @@ public final class RAImageIngestModule implements DataSourceIngestModule {
|
||||
for (int i = 0; i < extracters.size(); i++) {
|
||||
Extract extracter = extracters.get(i);
|
||||
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;
|
||||
}
|
||||
|
||||
progressBar.progress(extracter.getName(), i);
|
||||
progressBar.progress(extracter.getModuleName(), i);
|
||||
|
||||
try {
|
||||
extracter.process(dataSource, context);
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.SEVERE, "Exception occurred in " + extracter.getName(), ex); //NON-NLS
|
||||
subCompleted.append(NbBundle.getMessage(this.getClass(), "RAImageIngestModule.process.errModFailed",
|
||||
extracter.getName()));
|
||||
logger.log(Level.SEVERE, "Exception occurred in " + extracter.getModuleName(), ex); //NON-NLS
|
||||
errors.add(
|
||||
NbBundle.getMessage(this.getClass(), "RAImageIngestModule.process.errModErrs", RecentActivityExtracterModuleFactory.getModuleName()));
|
||||
}
|
||||
@ -155,7 +148,7 @@ public final class RAImageIngestModule implements DataSourceIngestModule {
|
||||
historyMsg.append(
|
||||
NbBundle.getMessage(this.getClass(), "RAImageIngestModule.process.histMsg.title", dataSource.getName()));
|
||||
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
|
||||
.getMessage(this.getClass(), "RAImageIngestModule.process.histMsg.found") : NbBundle
|
||||
.getMessage(this.getClass(), "RAImageIngestModule.process.histMsg.notFnd"));
|
||||
@ -173,17 +166,6 @@ public final class RAImageIngestModule implements DataSourceIngestModule {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2012-2014 Basis Technology Corp.
|
||||
* Copyright 2012-2018 Basis Technology Corp.
|
||||
*
|
||||
* Copyright 2012 42six Solutions.
|
||||
* Contact: aebadirad <at> 42six <dot> com
|
||||
@ -23,37 +23,55 @@
|
||||
package org.sleuthkit.autopsy.recentactivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
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.JLnkParser;
|
||||
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.IngestServices;
|
||||
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
|
||||
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_RECENT_OBJECT;
|
||||
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.*;
|
||||
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
|
||||
* files
|
||||
*/
|
||||
class RecentDocumentsByLnk extends Extract {
|
||||
class RecentDocumentsLnkExtractor extends Extract {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(RecentDocumentsByLnk.class.getName());
|
||||
private IngestServices services = IngestServices.getInstance();
|
||||
private static final Logger logger = Logger.getLogger(RecentDocumentsLnkExtractor.class.getName());
|
||||
|
||||
private static final String PARENT_MODULE_NAME = NbBundle.getMessage(RecentDocumentsLnkExtractor.class,
|
||||
"RecentDocumentsByLnk.parentModuleName.noSpace");
|
||||
private Content dataSource;
|
||||
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
|
||||
* artifacts.
|
||||
@ -62,8 +80,6 @@ class RecentDocumentsByLnk extends Extract {
|
||||
* @param controller
|
||||
*/
|
||||
private void getRecentDocuments() {
|
||||
|
||||
org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
|
||||
List<AbstractFile> recentFiles;
|
||||
try {
|
||||
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
|
||||
this.addErrorMessage(
|
||||
NbBundle.getMessage(this.getClass(), "RecentDocumentsByLnk.getRecDoc.errMsg.errGetLnkFiles",
|
||||
this.getName()));
|
||||
this.getModuleName()));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -81,6 +97,8 @@ class RecentDocumentsByLnk extends Extract {
|
||||
}
|
||||
|
||||
dataFound = true;
|
||||
|
||||
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
|
||||
for (AbstractFile recentFile : recentFiles) {
|
||||
if (context.dataSourceIngestIsCancelled()) {
|
||||
break;
|
||||
@ -96,39 +114,42 @@ class RecentDocumentsByLnk extends Extract {
|
||||
} catch (JLnkParserException e) {
|
||||
//TODO should throw a specific checked exception
|
||||
boolean unalloc = recentFile.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.UNALLOC)
|
||||
|| recentFile.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC);
|
||||
|| recentFile.isDirNameFlagSet(TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC);
|
||||
if (unalloc == false) {
|
||||
logger.log(Level.WARNING, "Error lnk parsing the file to get recent files {0}", recentFile); //NON-NLS
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
|
||||
String path = lnk.getBestPath();
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"RecentDocumentsByLnk.parentModuleName.noSpace"),
|
||||
path));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH_ID,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"RecentDocumentsByLnk.parentModuleName.noSpace"),
|
||||
Util.findID(dataSource, path)));
|
||||
bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"RecentDocumentsByLnk.parentModuleName.noSpace"),
|
||||
recentFile.getCrtime()));
|
||||
this.addArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT, recentFile, bbattributes);
|
||||
Collection<BlackboardAttribute> bbattributes = Arrays.asList(
|
||||
new BlackboardAttribute(
|
||||
TSK_PATH, PARENT_MODULE_NAME,
|
||||
path),
|
||||
new BlackboardAttribute(
|
||||
TSK_PATH_ID, PARENT_MODULE_NAME,
|
||||
Util.findID(dataSource, path)),
|
||||
new BlackboardAttribute(
|
||||
TSK_DATETIME, PARENT_MODULE_NAME,
|
||||
recentFile.getCrtime()));
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: why weren't these getting indexed before?
|
||||
try {
|
||||
blackboard.postArtifacts(bbartifacts, PARENT_MODULE_NAME);
|
||||
} catch (Blackboard.BlackboardException ex) {
|
||||
logger.log(Level.SEVERE, "Error while trying to post recent document artifact.", ex); //NON-NLS
|
||||
this.addErrorMessage(Bundle.Extractor_errPostingArtifacts(getModuleName()));
|
||||
}
|
||||
services.fireModuleDataEvent(new ModuleDataEvent(
|
||||
NbBundle.getMessage(this.getClass(), "RecentDocumentsByLnk.parentModuleName"),
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void process(Content dataSource, IngestJobContext context) {
|
||||
this.dataSource = dataSource;
|
||||
this.context = context;
|
||||
dataFound = false;
|
||||
this.getRecentDocuments();
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2012-2014 Basis Technology Corp.
|
||||
* Copyright 2012-2018 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -23,10 +23,10 @@ import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
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.ingest.IngestJobContext;
|
||||
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.Blackboard;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
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.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.TskCoreException;
|
||||
import org.w3c.dom.Document;
|
||||
@ -64,18 +68,22 @@ import org.xml.sax.SAXException;
|
||||
"cannotParseXml=Unable to parse XML file: ",
|
||||
"# {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 XSDFILE = "SearchEngineSchema.xsd"; //NON-NLS
|
||||
private static SearchEngineURLQueryAnalyzer.SearchEngine[] engines;
|
||||
private static SearchEngine[] engines;
|
||||
|
||||
private Content dataSource;
|
||||
private IngestJobContext context;
|
||||
|
||||
SearchEngineURLQueryAnalyzer() {
|
||||
moduleName = NbBundle.getMessage(ExtractIE.class, "SearchEngineURLQueryAnalyzer.moduleName.text");
|
||||
@Override
|
||||
protected String getModuleName() {
|
||||
return NbBundle.getMessage(ExtractIE.class, "SearchEngineURLQueryAnalyzer.moduleName.text");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -156,13 +164,11 @@ class SearchEngineURLQueryAnalyzer extends Extract {
|
||||
Document xmlinput;
|
||||
try {
|
||||
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
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
xmlinput = db.parse(f);
|
||||
xmlinput = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(configFile);
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@ -175,7 +181,7 @@ class SearchEngineURLQueryAnalyzer extends Extract {
|
||||
}
|
||||
|
||||
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++) {
|
||||
NamedNodeMap nnm = nlist.item(i).getAttributes();
|
||||
|
||||
@ -190,8 +196,8 @@ class SearchEngineURLQueryAnalyzer extends Extract {
|
||||
}
|
||||
}
|
||||
|
||||
SearchEngineURLQueryAnalyzer.SearchEngine Se = new SearchEngineURLQueryAnalyzer.SearchEngine(EngineName, EnginedomainSubstring, keys);
|
||||
listEngines[i] = Se;
|
||||
SearchEngine searchEngine = new SearchEngine(EngineName, EnginedomainSubstring, keys);
|
||||
listEngines[i] = searchEngine;
|
||||
}
|
||||
engines = listEngines;
|
||||
}
|
||||
@ -206,7 +212,7 @@ class SearchEngineURLQueryAnalyzer extends Extract {
|
||||
* is found
|
||||
*
|
||||
*/
|
||||
private static SearchEngineURLQueryAnalyzer.SearchEngine getSearchEngineFromUrl(String domain) {
|
||||
private static SearchEngine getSearchEngineFromUrl(String domain) {
|
||||
if (engines == null) {
|
||||
return null;
|
||||
}
|
||||
@ -225,32 +231,31 @@ class SearchEngineURLQueryAnalyzer extends Extract {
|
||||
*
|
||||
* @return The extracted search query.
|
||||
*/
|
||||
private String extractSearchEngineQuery(SearchEngineURLQueryAnalyzer.SearchEngine eng, String url) {
|
||||
String x = ""; //NON-NLS
|
||||
private String extractSearchEngineQuery(SearchEngine eng, String url) {
|
||||
String value = ""; //NON-NLS
|
||||
|
||||
for (KeyPair kp : eng.getKeys()) {
|
||||
if (url.contains(kp.getKey())) {
|
||||
x = getValue(url, kp.getKeyRegExp());
|
||||
value = getValue(url, kp.getKeyRegExp());
|
||||
break;
|
||||
}
|
||||
}
|
||||
try { //try to decode the url
|
||||
String decoded = URLDecoder.decode(x, "UTF-8"); //NON-NLS
|
||||
return decoded;
|
||||
return URLDecoder.decode(value, "UTF-8"); //NON-NLS
|
||||
} catch (UnsupportedEncodingException exception) { //if it fails, return the encoded string
|
||||
logger.log(Level.FINE, "Error during URL decoding, returning undecoded value:"
|
||||
+ "\n\tURL: " + url
|
||||
+ "\n\tUndecoded value: " + x
|
||||
+ "\n\tEngine name: " + eng.getEngineName()
|
||||
+ "\n\tEngine domain: " + eng.getDomainSubstring(), exception); //NON-NLS
|
||||
return x;
|
||||
+ "\n\tURL: " + url
|
||||
+ "\n\tUndecoded value: " + value
|
||||
+ "\n\tEngine name: " + eng.getEngineName()
|
||||
+ "\n\tEngine domain: " + eng.getDomainSubstring(), exception); //NON-NLS
|
||||
return value;
|
||||
} catch (IllegalArgumentException exception) { //if it fails, return the encoded string
|
||||
logger.log(Level.SEVERE, "Illegal argument passed to URL decoding, returning undecoded value:"
|
||||
+ "\n\tURL: " + url
|
||||
+ "\n\tUndecoded value: " + x
|
||||
+ "\n\tEngine name: " + eng.getEngineName()
|
||||
+ "\n\tEngine domain: " + eng.getDomainSubstring(), exception); //NON-NLS)
|
||||
return x;
|
||||
+ "\n\tURL: " + url
|
||||
+ "\n\tUndecoded value: " + value
|
||||
+ "\n\tEngine name: " + eng.getEngineName()
|
||||
+ "\n\tEngine domain: " + eng.getDomainSubstring(), exception); //NON-NLS)
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -273,126 +278,106 @@ class SearchEngineURLQueryAnalyzer extends Extract {
|
||||
* at more formal approaches of splitting on the "?" and then on "&"
|
||||
* 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 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
|
||||
if (regExpKey.contains("\\?")) {
|
||||
v = regExpKey.replace("\\?", "?");
|
||||
}
|
||||
String[] sp = url.split(v);
|
||||
if (sp.length >= 2) {
|
||||
if (sp[sp.length - 1].contains("&")) {
|
||||
value = sp[sp.length - 1].split("&")[0];
|
||||
|
||||
String[] tokens = url.split(regExpKey.replace("\\?", "?"));
|
||||
if (tokens.length >= 2) {
|
||||
if (tokens[tokens.length - 1].contains("&")) {
|
||||
value = tokens[tokens.length - 1].split("&")[0];
|
||||
} else {
|
||||
value = sp[sp.length - 1];
|
||||
value = tokens[tokens.length - 1];
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private void findSearchQueries() {
|
||||
int totalQueries = 0;
|
||||
|
||||
Collection<BlackboardArtifact> sourceArtifacts = new ArrayList<>();
|
||||
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
|
||||
//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
|
||||
|
||||
for (BlackboardArtifact artifact : listArtifacts) {
|
||||
if (context.dataSourceIngestIsCancelled()) {
|
||||
break; //User cancelled the process.
|
||||
}
|
||||
|
||||
//initializing default attributes
|
||||
String query = "";
|
||||
String searchEngineDomain = "";
|
||||
String browser = "";
|
||||
long last_accessed = -1;
|
||||
|
||||
long fileId = artifact.getObjectID();
|
||||
boolean isFromSource = tskCase.isFileFromSource(dataSource, fileId);
|
||||
if (!isFromSource) {
|
||||
//File was from a different dataSource. Skipping.
|
||||
continue;
|
||||
}
|
||||
|
||||
AbstractFile file = tskCase.getAbstractFileById(fileId);
|
||||
if (file == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SearchEngineURLQueryAnalyzer.SearchEngine se = null;
|
||||
//from blackboard_attributes
|
||||
Collection<BlackboardAttribute> listAttributes = currentCase.getSleuthkitCase().getMatchingAttributes("WHERE artifact_id = " + artifact.getArtifactID()); //NON-NLS
|
||||
|
||||
for (BlackboardAttribute attribute : listAttributes) {
|
||||
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());
|
||||
if (query.equals("")) //False positive match, artifact was not a query. NON-NLS
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID()) {
|
||||
browser = attribute.getValueString();
|
||||
} else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID()) {
|
||||
searchEngineDomain = attribute.getValueString();
|
||||
} else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED.getTypeID()) {
|
||||
last_accessed = attribute.getValueLong();
|
||||
}
|
||||
}
|
||||
|
||||
if (se != null && !query.equals("")) { //NON-NLS
|
||||
// If date doesn't exist, change to 0 (instead of 1969)
|
||||
if (last_accessed == -1) {
|
||||
last_accessed = 0;
|
||||
}
|
||||
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 {
|
||||
Collection<BlackboardArtifact> queryArtifacts = new ArrayList<>();
|
||||
for (BlackboardArtifact sourceArtifact : sourceArtifacts) {
|
||||
if (context.dataSourceIngestIsCancelled()) {
|
||||
logger.info("Operation terminated by user."); //NON-NLS
|
||||
break; //User cancelled the process.
|
||||
}
|
||||
long fileId = sourceArtifact.getObjectID();
|
||||
try {
|
||||
if (false == tskCase.isFileFromSource(dataSource, fileId)) {
|
||||
continue; //File was from a different dataSource. Skipping.
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Encountered error determining if file " + fileId + "is from datasource " + dataSource.getId(), ex); //NON-NLS
|
||||
continue;
|
||||
}
|
||||
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() {
|
||||
String total = "";
|
||||
if (engines == null) {
|
||||
return total;
|
||||
AbstractFile file;
|
||||
try {
|
||||
file = tskCase.getAbstractFileById(fileId);
|
||||
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;
|
||||
}
|
||||
|
||||
try {
|
||||
final String urlString = sourceArtifact.getAttribute(new BlackboardAttribute.Type(TSK_URL)).getValueString();
|
||||
SearchEngine searchEngine = getSearchEngineFromUrl(urlString);
|
||||
if (searchEngine == null) { //TODO: should we log this?
|
||||
continue;
|
||||
}
|
||||
|
||||
String query = extractSearchEngineQuery(searchEngine, urlString);
|
||||
if (query.isEmpty()) { //False positive match, artifact was not a query.
|
||||
continue;
|
||||
}
|
||||
|
||||
String browser = sourceArtifact.getAttribute(new BlackboardAttribute.Type(TSK_PROG_NAME)).getValueString();
|
||||
String searchEngineDomain = sourceArtifact.getAttribute(new BlackboardAttribute.Type(TSK_DOMAIN)).getValueString();
|
||||
long last_accessed = sourceArtifact.getAttribute(new BlackboardAttribute.Type(TSK_DATETIME_ACCESSED)).getValueLong();
|
||||
|
||||
Collection<BlackboardAttribute> bbattributes = Arrays.asList(
|
||||
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
|
||||
}
|
||||
}
|
||||
for (SearchEngineURLQueryAnalyzer.SearchEngine se : engines) {
|
||||
total += se.getEngineName() + " : " + se.getTotal() + "\n";
|
||||
|
||||
try {
|
||||
blackboard.postArtifacts(queryArtifacts, PARENT_MODULE_NAME);
|
||||
} catch (Blackboard.BlackboardException ex) {
|
||||
logger.log(Level.SEVERE, "Encountered error posting search query artifacts.", ex); //NON-NLS
|
||||
}
|
||||
return total;
|
||||
|
||||
logger.log(Level.INFO, "Extracted {0} queries from the blackboard", queryArtifacts.size()); //NON-NLS
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -400,13 +385,20 @@ class SearchEngineURLQueryAnalyzer extends Extract {
|
||||
this.dataSource = dataSource;
|
||||
this.context = context;
|
||||
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
|
||||
|
||||
void configExtractor() throws IngestModuleException {
|
||||
try {
|
||||
PlatformUtil.extractResourceToUserConfigDir(SearchEngineURLQueryAnalyzer.class, XMLFILE, true);
|
||||
PlatformUtil.extractResourceToUserConfigDir(SearchEngineURLQueryExtractor.class,
|
||||
XMLFILE, true);
|
||||
} catch (IOException e) {
|
||||
String message = Bundle.SearchEngineURLQueryAnalyzer_init_exception_msg(XMLFILE);
|
||||
logger.log(Level.SEVERE, message, e);
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
@ -22,7 +22,6 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.recentactivity;
|
||||
|
||||
import org.sleuthkit.autopsy.coreutils.SQLiteDBConnect;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
@ -35,14 +34,16 @@ import java.sql.ResultSet;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
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.Content;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
@ -71,32 +72,24 @@ class Util {
|
||||
}
|
||||
|
||||
public static String readFile(String path) throws IOException {
|
||||
FileInputStream stream = new FileInputStream(new File(path));
|
||||
try {
|
||||
try (FileInputStream stream = new FileInputStream(new File(path))) {
|
||||
FileChannel fc = stream.getChannel();
|
||||
MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
|
||||
/*
|
||||
* Instead of using default, pass in a decoder.
|
||||
*/
|
||||
return Charset.defaultCharset().decode(bb).toString();
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
String cleanUrl = url.replaceFirst(".*:\\/\\/", "");
|
||||
|
||||
//strip after slashes
|
||||
String dirToks[] = cleanUrl.split("\\/");
|
||||
if (dirToks.length > 0) {
|
||||
host = dirToks[0];
|
||||
} else {
|
||||
host = cleanUrl;
|
||||
}
|
||||
String host = (dirToks.length > 0) ? dirToks[0] : cleanUrl;
|
||||
|
||||
//get the domain part from host (last 2)
|
||||
StringTokenizer tok = new StringTokenizer(host, ".");
|
||||
@ -118,6 +111,8 @@ class Util {
|
||||
}
|
||||
|
||||
public static String extractDomain(String value) {
|
||||
|
||||
//TODO: There is no utility in apache or guave to do this for us?
|
||||
if (value == null) {
|
||||
return "";
|
||||
|
||||
@ -207,31 +202,17 @@ class Util {
|
||||
|
||||
public static boolean checkColumn(String column, String tablename, String connection) {
|
||||
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
|
||||
temprs = tempdbconnect.executeQry(query);
|
||||
|
||||
try (SQLiteDBConnect tempdbconnect = new SQLiteDBConnect("org.sqlite.JDBC", "jdbc:sqlite:" + connection); //NON-NLS
|
||||
ResultSet temprs = tempdbconnect.executeQry(query);) {
|
||||
while (temprs.next()) {
|
||||
if (temprs.getString("name") == null ? column == null : temprs.getString("name").equals(column)) { //NON-NLS
|
||||
found = true;
|
||||
if (Objects.equals(temprs.getString("name"), column)) { //NON-NLS
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.WARNING, "Error while trying to get columns from sqlite db." + connection, ex); //NON-NLS
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user