Skip to content
Snippets Groups Projects
Unverified Commit d2b540d1 authored by Richard Cordovano's avatar Richard Cordovano Committed by GitHub
Browse files

Merge pull request #4572 from kellykelly3/1199-safari-cookies

1197, 1198, 1199, 1200 - Support for Safari 
parents 7f75882a ab782a4d
Branches
Tags
No related merge requests found
......@@ -973,7 +973,7 @@
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/dd-plist-1.20.jar</runtime-relative-path>
<binary-origin>C:\Users\kelly\Workspace\autopsy\CoreLibs\release\modules\ext\dd-plist-1.20.jar</binary-origin>
<binary-origin>release/modules/ext/dd-plist-1.20.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/dom4j-1.6.1.jar</runtime-relative-path>
......
......@@ -6,4 +6,7 @@
<conf name="recent-activity"/>
</configurations>
<dependencies>
<dependency conf="recent-activity->default" org="com.googlecode.plist" name="dd-plist" rev="1.20"/>
</dependencies>
</ivy-module>
file.reference.dd-plist-1.20.jar=release/modules/ext/dd-plist-1.20.jar
javac.source=1.8
javac.compilerargs=-Xlint -Xlint:-serial
license.file=../LICENSE-2.0.txt
......
......@@ -74,6 +74,10 @@
</dependency>
</module-dependencies>
<public-packages/>
<class-path-extension>
<runtime-relative-path>ext/dd-plist-1.20.jar</runtime-relative-path>
<binary-origin>release/modules/ext/dd-plist-1.20.jar</binary-origin>
</class-path-extension>
</data>
</configuration>
</project>
/*
*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.recentactivity;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.recentactivity.BinaryCookieReader.Cookie;
/**
* The binary cookie reader encapsulates all the knowledge of how to read the mac
* .binarycookie files into one class.
*
* The binarycookie file has a header which describes how many pages of cookies
* and where they are located. Each cookie page has a header and a list of
* cookies.
*
*/
public final class BinaryCookieReader implements Iterable<Cookie> {
private static final int MAGIC_SIZE = 4;
private static final int SIZEOF_INT_BYTES = 4;
private static final int PAGE_HEADER_VALUE = 256;
private static final String COOKIE_MAGIC = "cook"; //NON-NLS
private static final int MAC_EPOC_FIX = 978307200;
private final int[] pageSizeArray;
private final File cookieFile;
private static final Logger LOG = Logger.getLogger(BinaryCookieReader.class.getName());
/**
* The binary cookie reader encapsulates all the knowledge of how to read the mac
* .binarycookie files into one class.
*
*/
private BinaryCookieReader(File cookieFile, int[] pageSizeArray) {
this.cookieFile = cookieFile;
this.pageSizeArray = pageSizeArray;
}
/**
* initalizeReader opens the given file, reads the header and checks that
* the file is a binarycookie file. This function does not keep the file
* open.
*
* @param file binarycookie file
* @return An instance of the reader
* @throws FileNotFoundException
* @throws IOException
*/
public static BinaryCookieReader initalizeReader(File cookieFile) throws FileNotFoundException, IOException {
BinaryCookieReader reader = null;
try (DataInputStream dataStream = new DataInputStream(new FileInputStream(cookieFile))) {
byte[] magic = new byte[MAGIC_SIZE];
if (dataStream.read(magic) != MAGIC_SIZE) {
throw new IOException("Failed to read header, invalid file size (" + cookieFile.getName() + ")"); //NON-NLS
}
if (!(new String(magic)).equals(COOKIE_MAGIC)) {
throw new IOException(cookieFile.getName() + " is not a cookie file"); //NON-NLS
}
int[] sizeArray = null;
int pageCount = dataStream.readInt();
if (pageCount != 0) {
sizeArray = new int[pageCount];
for (int cnt = 0; cnt < pageCount; cnt++) {
sizeArray[cnt] = dataStream.readInt();
}
LOG.log(Level.INFO, "No cookies found in {0}", cookieFile.getName()); //NON-NLS
}
reader = new BinaryCookieReader(cookieFile, sizeArray);
}
return reader;
}
/**
* Creates and returns a instance of CookiePageIterator.
*
* @return CookiePageIterator
*/
@Override
public Iterator<Cookie> iterator() {
return new CookiePageIterator();
}
/**
* The cookiePageIterator iterates the binarycookie file by page.
*/
private class CookiePageIterator implements Iterator<Cookie> {
int pageIndex = 0;
CookiePage currentPage = null;
Iterator<Cookie> currentIterator = null;
DataInputStream dataStream = null;
/**
* The cookiePageIterator iterates the binarycookie file by page.
*/
CookiePageIterator() {
if(pageSizeArray == null || pageSizeArray.length == 0) {
return;
}
try {
dataStream = new DataInputStream(new FileInputStream(cookieFile));
// skip to the first page
dataStream.skipBytes((2 * SIZEOF_INT_BYTES) + (pageSizeArray.length * SIZEOF_INT_BYTES));
} catch (IOException ex) {
String errorMessage = String.format("An error occurred creating an input stream for %s", cookieFile.getName());
LOG.log(Level.WARNING, errorMessage, ex); //NON-NLS
closeStream(); // Just incase the error was from skip
}
}
/**
* Returns true if there are more cookies in the binarycookie file.
*
* @return True if there are more cookies
*/
@Override
public boolean hasNext() {
if (dataStream == null) {
return false;
}
if (currentIterator == null || !currentIterator.hasNext()) {
try {
if (pageIndex < pageSizeArray.length) {
byte[] nextPage = new byte[pageSizeArray[pageIndex]];
dataStream.read(nextPage);
currentPage = new CookiePage(nextPage);
currentIterator = currentPage.iterator();
} else {
closeStream();
return false;
}
pageIndex++;
} catch (IOException ex) {
closeStream();
String errorMessage = String.format("A read error occured for file %s (pageIndex = %d)", cookieFile.getName(), pageIndex);
LOG.log(Level.WARNING, errorMessage, ex); //NON-NLS
return false;
}
}
return currentIterator.hasNext();
}
/**
* Get the next cookie from the current CookieIterator.
*
* @return The next cookie
*/
@Override
public Cookie next() {
// Just in case someone uses next without hasNext, this check will
// make sure there are more elements and that we iterate properly
// through the pages.
if (!hasNext()) {
throw new NoSuchElementException();
}
return currentIterator.next();
}
/**
* Close the DataInputStream
*/
private void closeStream() {
if (dataStream != null) {
try {
dataStream.close();
dataStream = null;
} catch (IOException ex) {
String errorMessage = String.format("An error occurred trying to close stream for file %s", cookieFile.getName());
LOG.log(Level.WARNING, errorMessage, ex); //NON-NLS
}
}
}
}
/**
* Wrapper class for an instance of a CookiePage in the binarycookie file.
*/
private class CookiePage implements Iterable<Cookie> {
int[] cookieOffSets;
ByteBuffer pageBuffer;
/**
* Setup the CookiePage object. Calidates that the page bytes are in the
* correct format by checking for the header value of 0x0100.
*
* @param page byte array representing a cookie page
* @throws IOException
*/
CookiePage(byte[] page) throws IOException {
if (page == null || page.length == 0) {
throw new IllegalArgumentException("Invalid value for page passed to CookiePage constructor"); //NON-NLS
}
pageBuffer = ByteBuffer.wrap(page);
if (pageBuffer.getInt() != PAGE_HEADER_VALUE) {
pageBuffer = null;
throw new IOException("Invalid file format, bad page head value found"); //NON-NLS
}
pageBuffer.order(ByteOrder.LITTLE_ENDIAN);
int count = pageBuffer.getInt();
cookieOffSets = new int[count];
for (int cnt = 0; cnt < count; cnt++) {
cookieOffSets[cnt] = pageBuffer.getInt();
}
pageBuffer.getInt(); // All 0, not needed
}
/**
* Returns an instance of a CookieIterator.
*
* @return CookieIterator
*/
@Override
public Iterator<Cookie> iterator() {
return new CookieIterator();
}
/**
* Implements Iterator to iterate over the cookies in the page.
*/
private class CookieIterator implements Iterator<Cookie> {
int index = 0;
/**
* Checks to see if there are more cookies.
*
* @return True if there are more cookies, false if there are not
*/
@Override
public boolean hasNext() {
if (pageBuffer == null) {
return false;
}
return index < cookieOffSets.length;
}
/**
* Gets the next cookie from the page.
*
* @return Next cookie
*/
@Override
public Cookie next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
int offset = cookieOffSets[index];
int size = pageBuffer.getInt(offset);
byte[] cookieBytes = new byte[size];
pageBuffer.get(cookieBytes, 0, size);
index++;
return new Cookie(cookieBytes);
}
}
}
/**
* Represents an instance of a cookie from the binarycookie file.
*/
public class Cookie {
private final static int COOKIE_HEAD_SKIP = 16;
private final double expirationDate;
private final double creationDate;
private final String name;
private final String url;
private final String path;
private final String value;
/**
* Creates a cookie object from the given array of bytes.
*
* @param cookieBytes Byte array for the cookie
*/
protected Cookie(byte[] cookieBytes) {
if (cookieBytes == null || cookieBytes.length == 0) {
throw new IllegalArgumentException("Invalid value for cookieBytes passed to Cookie constructor"); //NON-NLS
}
ByteBuffer byteBuffer = ByteBuffer.wrap(cookieBytes);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
// Skip past the four int values that we are not interested in
byteBuffer.position(byteBuffer.position() + COOKIE_HEAD_SKIP);
int urlOffset = byteBuffer.getInt();
int nameOffset = byteBuffer.getInt();
int pathOffset = byteBuffer.getInt();
int valueOffset = byteBuffer.getInt();
byteBuffer.getLong(); // 8 bytes of not needed
expirationDate = byteBuffer.getDouble();
creationDate = byteBuffer.getDouble();
url = decodeString(cookieBytes, urlOffset);
name = decodeString(cookieBytes, nameOffset);
path = decodeString(cookieBytes, pathOffset);
value = decodeString(cookieBytes, valueOffset);
}
/**
* Returns the expiration date of the cookie represented by this cookie
* object.
*
* @return Cookie expiration date in milliseconds with java epoch
*/
public final Long getExpirationDate() {
return ((long)expirationDate) + MAC_EPOC_FIX;
}
/**
* Returns the creation date of the cookie represented by this cookie
* object.
*
* @return Cookie creation date in milliseconds with java epoch
*/
public final Long getCreationDate() {
return ((long)creationDate) + MAC_EPOC_FIX;
}
/**
* Returns the url of the cookie represented by this cookie object.
*
* @return the cookie URL
*/
public final String getURL() {
return url;
}
/**
* Returns the name of the cookie represented by this cookie object.
*
* @return The cookie name
*/
public final String getName() {
return name;
}
/**
* Returns the path of the cookie represented by this cookie object.
*
* @return The cookie path
*/
public final String getPath() {
return path;
}
/**
* Returns the value of the cookie represented by this cookie object.
*
* @return The cookie value
*/
public final String getValue() {
return value;
}
/**
* Creates an ascii string from the bytes in byteArray starting at
* offset ending at the first null terminator found.
*
* @param byteArray Array of bytes
* @param offset starting offset in the array
* @return String with bytes converted to ascii
*/
private String decodeString(byte[] byteArray, int offset) {
byte[] stringBytes = new byte[byteArray.length - offset];
for (int index = 0; index < stringBytes.length; index++) {
byte nibble = byteArray[offset + index];
if (nibble != '\0') { //NON-NLS
stringBytes[index] = nibble;
} else {
break;
}
}
return new String(stringBytes);
}
}
}
......@@ -22,10 +22,18 @@
*/
package org.sleuthkit.autopsy.recentactivity;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
......@@ -35,9 +43,17 @@
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.SQLiteDBConnect;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException;
import org.sleuthkit.datamodel.*;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskException;
abstract class Extract {
......@@ -216,4 +232,207 @@ public boolean foundData() {
protected void setFoundData(boolean foundData){
dataFound = foundData;
}
/**
* Returns the current case instance
* @return Current case instance
*/
protected Case getCurrentCase(){
return this.currentCase;
}
/**
* Creates a list of attributes for a history artifact.
*
* @param url
* @param accessTime Time url was accessed
* @param referrer referred url
* @param title title of the page
* @param programName module name
* @param domain domain of the url
* @param user user that accessed url
* @return List of BlackboardAttributes for giving attributes
* @throws TskCoreException
*/
protected Collection<BlackboardAttribute> createHistoryAttribute(String url, Long accessTime,
String referrer, String title, String programName, String domain, String user) throws TskCoreException {
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL,
RecentActivityExtracterModuleFactory.getModuleName(),
(url != null) ? url : "")); //NON-NLS
if (accessTime != null) {
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
RecentActivityExtracterModuleFactory.getModuleName(), accessTime));
}
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_REFERRER,
RecentActivityExtracterModuleFactory.getModuleName(),
(referrer != null) ? referrer : "")); //NON-NLS
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE,
RecentActivityExtracterModuleFactory.getModuleName(),
(title != null) ? title : "")); //NON-NLS
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME,
RecentActivityExtracterModuleFactory.getModuleName(),
(programName != null) ? programName : "")); //NON-NLS
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN,
RecentActivityExtracterModuleFactory.getModuleName(),
(domain != null) ? domain : "")); //NON-NLS
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME,
RecentActivityExtracterModuleFactory.getModuleName(),
(user != null) ? user : "")); //NON-NLS
return bbattributes;
}
/**
* Creates a list of attributes for a cookie.
*
* @param url cookie url
* @param creationTime cookie creation time
* @param name cookie name
* @param value cookie value
* @param programName Name of the module creating the attribute
* @param domain Domain of the URL
* @return List of BlackboarAttributes for the passed in attributes
*/
protected Collection<BlackboardAttribute> createCookieAttributes(String url,
Long creationTime, String name, String value, String programName, String domain) {
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL,
RecentActivityExtracterModuleFactory.getModuleName(),
(url != null) ? url : "")); //NON-NLS
if (creationTime != null) {
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME,
RecentActivityExtracterModuleFactory.getModuleName(), creationTime));
}
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME,
RecentActivityExtracterModuleFactory.getModuleName(),
(name != null) ? name : "")); //NON-NLS
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE,
RecentActivityExtracterModuleFactory.getModuleName(),
(value != null) ? value : "")); //NON-NLS
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME,
RecentActivityExtracterModuleFactory.getModuleName(),
(programName != null) ? programName : "")); //NON-NLS
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN,
RecentActivityExtracterModuleFactory.getModuleName(),
(domain != null) ? domain : "")); //NON-NLS
return bbattributes;
}
/**
* Creates a list of bookmark attributes from the passed in parameters.
*
* @param url Bookmark url
* @param title Title of the bookmarked page
* @param creationTime Date & time at which the bookmark was created
* @param programName Name of the module creating the attribute
* @param domain The domain of the bookmark's url
* @return A collection of bookmark attributes
*/
protected Collection<BlackboardAttribute> createBookmarkAttributes(String url, String title, Long creationTime, String programName, String domain) {
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL,
RecentActivityExtracterModuleFactory.getModuleName(),
(url != null) ? url : "")); //NON-NLS
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE,
RecentActivityExtracterModuleFactory.getModuleName(),
(title != null) ? title : "")); //NON-NLS
if (creationTime != null) {
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
RecentActivityExtracterModuleFactory.getModuleName(), creationTime));
}
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME,
RecentActivityExtracterModuleFactory.getModuleName(),
(programName != null) ? programName : "")); //NON-NLS
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN,
RecentActivityExtracterModuleFactory.getModuleName(),
(domain != null) ? domain : "")); //NON-NLS
return bbattributes;
}
/**
* Creates a list of the attributes of a downloaded file
*
* @param path
* @param url URL of the downloaded file
* @param accessTime Time the download occurred
* @param domain Domain of the URL
* @param programName Name of the module creating the attribute
* @return A collection of attributed of a downloaded file
*/
protected Collection<BlackboardAttribute> createDownloadAttributes(String path, Long pathID, String url, Long accessTime, String domain, String programName) {
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH,
RecentActivityExtracterModuleFactory.getModuleName(),
(path != null) ? path : "")); //NON-NLS
if (pathID != null && pathID != -1) {
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID,
RecentActivityExtracterModuleFactory.getModuleName(),
pathID));
}
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL,
RecentActivityExtracterModuleFactory.getModuleName(),
(url != null) ? url : "")); //NON-NLS
if (accessTime != null) {
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
RecentActivityExtracterModuleFactory.getModuleName(), accessTime));
}
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN,
RecentActivityExtracterModuleFactory.getModuleName(),
(domain != null) ? domain : "")); //NON-NLS
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME,
RecentActivityExtracterModuleFactory.getModuleName(),
(programName != null) ? programName : "")); //NON-NLS
return bbattributes;
}
/**
* Create temporary file for the given AbstractFile. The new file will be
* created in the temp directory for the module with a unique file name.
*
* @param context
* @param file
* @return Newly created copy of the AbstractFile
* @throws IOException
*/
protected File createTemporaryFile(IngestJobContext context, AbstractFile file) throws IOException{
Path tempFilePath = Paths.get(RAImageIngestModule.getRATempPath(
getCurrentCase(), getName()), file.getName() + file.getId() + file.getNameExtension());
java.io.File tempFile = tempFilePath.toFile();
try {
ContentUtils.writeToFile(file, tempFile, context::dataSourceIngestIsCancelled);
} catch (IOException ex) {
throw new IOException("Error writingToFile: " + file, ex); //NON-NLS
}
return tempFile;
}
}
......@@ -48,7 +48,6 @@
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
......@@ -698,180 +697,7 @@ private BlackboardArtifact getBookmarkArtifact(AbstractFile origFile, List<Strin
this.getName(), NetworkUtils.extractDomain(url)));
return bbart;
}
/**
* Creates a list of attributes for a history artifact.
*
* @param url
* @param accessTime Time url was accessed
* @param referrer referred url
* @param title title of the page
* @param programName module name
* @param domain domain of the url
* @param user user that accessed url
* @return List of BlackboardAttributes for giving attributes
* @throws TskCoreException
*/
private Collection<BlackboardAttribute> createHistoryAttribute(String url, Long accessTime,
String referrer, String title, String programName, String domain, String user) throws TskCoreException {
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL,
RecentActivityExtracterModuleFactory.getModuleName(),
(url != null) ? url : ""));
if (accessTime != null) {
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
RecentActivityExtracterModuleFactory.getModuleName(), accessTime));
}
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_REFERRER,
RecentActivityExtracterModuleFactory.getModuleName(),
(referrer != null) ? referrer : ""));
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE,
RecentActivityExtracterModuleFactory.getModuleName(),
(title != null) ? title : ""));
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME,
RecentActivityExtracterModuleFactory.getModuleName(),
(programName != null) ? programName : ""));
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN,
RecentActivityExtracterModuleFactory.getModuleName(),
(domain != null) ? domain : ""));
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_USER_NAME,
RecentActivityExtracterModuleFactory.getModuleName(),
(user != null) ? user : ""));
return bbattributes;
}
/**
* Creates a list of attributes for a cookie.
*
* @param url cookie url
* @param creationTime cookie creation time
* @param name cookie name
* @param value cookie value
* @param programName Name of the module creating the attribute
* @param domain Domain of the URL
* @return List of BlackboarAttributes for the passed in attributes
*/
private Collection<BlackboardAttribute> createCookieAttributes(String url,
Long creationTime, String name, String value, String programName, String domain) {
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL,
RecentActivityExtracterModuleFactory.getModuleName(),
(url != null) ? url : ""));
if (creationTime != null) {
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME,
RecentActivityExtracterModuleFactory.getModuleName(), creationTime));
}
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME,
RecentActivityExtracterModuleFactory.getModuleName(),
(name != null) ? name : ""));
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE,
RecentActivityExtracterModuleFactory.getModuleName(),
(value != null) ? value : ""));
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME,
RecentActivityExtracterModuleFactory.getModuleName(),
(programName != null) ? programName : ""));
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN,
RecentActivityExtracterModuleFactory.getModuleName(),
(domain != null) ? domain : ""));
return bbattributes;
}
/**
* Creates a list of the attributes of a downloaded file
*
* @param path
* @param url URL of the downloaded file
* @param accessTime Time the download occurred
* @param domain Domain of the URL
* @param programName Name of the module creating the attribute
* @return A collection of attributed of a downloaded file
*/
private Collection<BlackboardAttribute> createDownloadAttributes(String path, String url, Long accessTime, String domain, String programName) {
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH,
RecentActivityExtracterModuleFactory.getModuleName(),
(path != null) ? path : ""));
long pathID = Util.findID(dataSource, path);
if (pathID != -1) {
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_ID,
RecentActivityExtracterModuleFactory.getModuleName(),
pathID));
}
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL,
RecentActivityExtracterModuleFactory.getModuleName(),
(url != null) ? url : ""));
if (accessTime != null) {
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
RecentActivityExtracterModuleFactory.getModuleName(), accessTime));
}
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN,
RecentActivityExtracterModuleFactory.getModuleName(),
(domain != null) ? domain : ""));
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME,
RecentActivityExtracterModuleFactory.getModuleName(),
(programName != null) ? programName : ""));
return bbattributes;
}
/**
* Creates a list of bookmark attributes from the passed in parameters.
*
* @param url Bookmark url
* @param title Title of the bookmarked page
* @param creationTime Date & time at which the bookmark was created
* @param programName Name of the module creating the attribute
* @param domain The domain of the bookmark's url
* @return A collection of bookmark attributes
*/
private Collection<BlackboardAttribute> createBookmarkAttributes(String url, String title, Long creationTime, String programName, String domain) {
Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL,
RecentActivityExtracterModuleFactory.getModuleName(),
(url != null) ? url : ""));
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE,
RecentActivityExtracterModuleFactory.getModuleName(),
(title != null) ? title : ""));
if (creationTime != null) {
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
RecentActivityExtracterModuleFactory.getModuleName(), creationTime));
}
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME,
RecentActivityExtracterModuleFactory.getModuleName(),
(programName != null) ? programName : ""));
bbattributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN,
RecentActivityExtracterModuleFactory.getModuleName(),
(domain != null) ? domain : ""));
return bbattributes;
}
/**
* Converts a space separated string of hex values to ascii characters.
*
......
/*
*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.recentactivity;
import com.dd.plist.NSArray;
import com.dd.plist.NSDate;
import com.dd.plist.NSDictionary;
import com.dd.plist.NSObject;
import com.dd.plist.NSString;
import com.dd.plist.PropertyListFormatException;
import com.dd.plist.PropertyListParser;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import javax.xml.parsers.ParserConfigurationException;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.services.FileManager;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
import org.sleuthkit.autopsy.recentactivity.BinaryCookieReader.Cookie;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
import org.xml.sax.SAXException;
/**
* Extract the bookmarks, cookies, downloads and history from Safari
*
*/
final class ExtractSafari extends Extract {
private final IngestServices services = IngestServices.getInstance();
// visit_time uses an epoch of Jan 1, 2001 thus the addition of 978307200
private static final String HISTORY_QUERY = "SELECT url, title, visit_time + 978307200 as time FROM 'history_items' JOIN history_visits ON history_item = history_items.id;"; //NON-NLS
private static final String HISTORY_FILE_NAME = "History.db"; //NON-NLS
private static final String BOOKMARK_FILE_NAME = "Bookmarks.plist"; //NON-NLS
private static final String DOWNLOAD_FILE_NAME = "Downloads.plist"; //NON-NLS
private static final String COOKIE_FILE_NAME = "Cookies.binarycookies"; //NON-NLS
private static final String COOKIE_FOLDER = "Cookies";
private static final String SAFARI_FOLDER = "Safari";
private static final String HEAD_URL = "url"; //NON-NLS
private static final String HEAD_TITLE = "title"; //NON-NLS
private static final String HEAD_TIME = "time"; //NON-NLS
private static final String PLIST_KEY_CHILDREN = "Children"; //NON-NLS
private static final String PLIST_KEY_URL = "URLString"; //NON-NLS
private static final String PLIST_KEY_URI = "URIDictionary"; //NON-NLS
private static final String PLIST_KEY_TITLE = "title"; //NON-NLS
private static final String PLIST_KEY_DOWNLOAD_URL = "DownloadEntryURL"; //NON-NLS
private static final String PLIST_KEY_DOWNLOAD_DATE = "DownloadEntryDateAddedKey"; //NON-NLS
private static final String PLIST_KEY_DOWNLOAD_PATH = "DownloadEntryPath"; //NON-NLS
private static final String PLIST_KEY_DOWNLOAD_HISTORY = "DownloadHistory"; //NON-NLS
private static final Logger LOG = Logger.getLogger(ExtractSafari.class.getName());
@Messages({
"ExtractSafari_Module_Name=Safari",
"ExtractSafari_Error_Getting_History=An error occurred while processing Safari history files.",
"ExtractSafari_Error_Parsing_Bookmark=An error occured while processing Safari Bookmark files",
"ExtractSafari_Error_Parsing_Cookies=An error occured while processing Safari Cookies files",
})
/**
* Extract the bookmarks, cookies, downloads and history from Safari.
*
*/
ExtractSafari() {
}
@Override
protected String getName() {
return Bundle.ExtractSafari_Module_Name();
}
@Override
void process(Content dataSource, IngestJobContext context) {
setFoundData(false);
try {
processHistoryDB(dataSource, context);
} catch (IOException | TskCoreException ex) {
this.addErrorMessage(Bundle.ExtractSafari_Error_Getting_History());
LOG.log(Level.SEVERE, "Exception thrown while processing history file: {0}", ex); //NON-NLS
}
try {
processBookmarkPList(dataSource, context);
} catch (IOException | TskCoreException | SAXException | PropertyListFormatException | ParseException | ParserConfigurationException ex) {
this.addErrorMessage(Bundle.ExtractSafari_Error_Parsing_Bookmark());
LOG.log(Level.SEVERE, "Exception thrown while parsing Safari Bookmarks file: {0}", ex); //NON-NLS
}
try {
processDownloadsPList(dataSource, context);
} catch (IOException | TskCoreException | SAXException | PropertyListFormatException | ParseException | ParserConfigurationException ex) {
this.addErrorMessage(Bundle.ExtractSafari_Error_Parsing_Bookmark());
LOG.log(Level.SEVERE, "Exception thrown while parsing Safari Download.plist file: {0}", ex); //NON-NLS
}
try {
processBinaryCookieFile(dataSource, context);
} catch (IOException | TskCoreException ex) {
this.addErrorMessage(Bundle.ExtractSafari_Error_Parsing_Cookies());
LOG.log(Level.SEVERE, "Exception thrown while processing Safari cookies file: {0}", ex); //NON-NLS
}
}
/**
* Finds the all of the history.db files in the case looping through them to
* find all of the history artifacts.
*
* @throws TskCoreException
* @throws IOException
*/
private void processHistoryDB(Content dataSource, IngestJobContext context) throws TskCoreException, IOException {
FileManager fileManager = getCurrentCase().getServices().getFileManager();
List<AbstractFile> historyFiles = fileManager.findFiles(dataSource, HISTORY_FILE_NAME, SAFARI_FOLDER);
if (historyFiles == null || historyFiles.isEmpty()) {
return;
}
setFoundData(true);
for (AbstractFile historyFile : historyFiles) {
if (context.dataSourceIngestIsCancelled()) {
break;
}
getHistory(context, historyFile);
}
}
/**
* Finds all Bookmark.plist files and looks for bookmark entries.
* @param dataSource
* @param context
* @throws TskCoreException
* @throws IOException
* @throws SAXException
* @throws PropertyListFormatException
* @throws ParseException
* @throws ParserConfigurationException
*/
private void processBookmarkPList(Content dataSource, IngestJobContext context) throws TskCoreException, IOException, SAXException, PropertyListFormatException, ParseException, ParserConfigurationException {
FileManager fileManager = getCurrentCase().getServices().getFileManager();
List<AbstractFile> files = fileManager.findFiles(dataSource, BOOKMARK_FILE_NAME, SAFARI_FOLDER);
if (files == null || files.isEmpty()) {
return;
}
setFoundData(true);
for (AbstractFile file : files) {
if (context.dataSourceIngestIsCancelled()) {
break;
}
getBookmarks(context, file);
}
}
/**
* Process the safari download.plist file.
*
* @param dataSource
* @param context
* @throws TskCoreException
* @throws IOException
* @throws SAXException
* @throws PropertyListFormatException
* @throws ParseException
* @throws ParserConfigurationException
*/
private void processDownloadsPList(Content dataSource, IngestJobContext context) throws TskCoreException, IOException, SAXException, PropertyListFormatException, ParseException, ParserConfigurationException {
FileManager fileManager = getCurrentCase().getServices().getFileManager();
List<AbstractFile> files = fileManager.findFiles(dataSource, DOWNLOAD_FILE_NAME, SAFARI_FOLDER);
if (files == null || files.isEmpty()) {
return;
}
setFoundData(true);
for (AbstractFile file : files) {
if (context.dataSourceIngestIsCancelled()) {
break;
}
getDownloads(dataSource, context, file);
}
}
/**
* Process the Safari Cookie file.
* @param dataSource
* @param context
* @throws TskCoreException
* @throws IOException
*/
private void processBinaryCookieFile(Content dataSource, IngestJobContext context) throws TskCoreException, IOException {
FileManager fileManager = getCurrentCase().getServices().getFileManager();
List<AbstractFile> files = fileManager.findFiles(dataSource, COOKIE_FILE_NAME, COOKIE_FOLDER);
if (files == null || files.isEmpty()) {
return;
}
setFoundData(true);
for (AbstractFile file : files) {
if (context.dataSourceIngestIsCancelled()) {
break;
}
getCookies(context, file);
}
}
/**
* Creates a temporary copy of historyFile and creates a list of
* BlackboardArtifacts for the history information in the file.
*
* @param historyFile AbstractFile version of the history file from the case
* @throws TskCoreException
* @throws IOException
*/
private void getHistory(IngestJobContext context, AbstractFile historyFile) throws TskCoreException, IOException {
if (historyFile.getSize() == 0) {
return;
}
File tempHistoryFile = createTemporaryFile(context, historyFile);
try {
ContentUtils.writeToFile(historyFile, tempHistoryFile, context::dataSourceIngestIsCancelled);
} catch (IOException ex) {
throw new IOException("Error writingToFile: " + historyFile, ex); //NON-NLS
}
try {
Collection<BlackboardArtifact> bbartifacts = getHistoryArtifacts(historyFile, tempHistoryFile.toPath());
if (!bbartifacts.isEmpty()) {
services.fireModuleDataEvent(new ModuleDataEvent(
RecentActivityExtracterModuleFactory.getModuleName(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY, bbartifacts));
}
} finally {
tempHistoryFile.delete();
}
}
/**
* Creates a temporary bookmark file from the AbstractFile and creates
* BlackboardArtifacts for the any bookmarks found.
*
* @param context IngestJobContext object
* @param file AbstractFile from case
* @throws TskCoreException
* @throws IOException
* @throws SAXException
* @throws PropertyListFormatException
* @throws ParseException
* @throws ParserConfigurationException
*/
private void getBookmarks(IngestJobContext context, AbstractFile file) throws TskCoreException, IOException, SAXException, PropertyListFormatException, ParseException, ParserConfigurationException {
if (file.getSize() == 0) {
return;
}
File tempFile = createTemporaryFile(context, file);
try {
Collection<BlackboardArtifact> bbartifacts = getBookmarkArtifacts(file, tempFile);
if (!bbartifacts.isEmpty()) {
services.fireModuleDataEvent(new ModuleDataEvent(
RecentActivityExtracterModuleFactory.getModuleName(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK, bbartifacts));
}
} finally {
tempFile.delete();
}
}
/**
* Creates a temporary downloads file from the AbstractFile and creates
* BlackboardArtifacts for the any downloads found.
*
* @param context IngestJobContext object
* @param file AbstractFile from case
* @throws TskCoreException
* @throws IOException
* @throws SAXException
* @throws PropertyListFormatException
* @throws ParseException
* @throws ParserConfigurationException
*/
private void getDownloads(Content dataSource, IngestJobContext context, AbstractFile file) throws TskCoreException, IOException, SAXException, PropertyListFormatException, ParseException, ParserConfigurationException {
if (file.getSize() == 0) {
return;
}
File tempFile = createTemporaryFile(context, file);
try {
Collection<BlackboardArtifact> bbartifacts = getDownloadArtifacts(dataSource, file, tempFile);
if (!bbartifacts.isEmpty()) {
services.fireModuleDataEvent(new ModuleDataEvent(
RecentActivityExtracterModuleFactory.getModuleName(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD, bbartifacts));
}
} finally {
if (tempFile != null) {
tempFile.delete();
}
}
}
/**
* Creates a temporary copy of the Cookie file and creates a list of cookie
* BlackboardArtifacts.
*
* @param context IngetstJobContext
* @param file Original Cookie file from the case
* @throws TskCoreException
* @throws IOException
*/
private void getCookies(IngestJobContext context, AbstractFile file) throws TskCoreException, IOException {
if (file.getSize() == 0) {
return;
}
File tempFile = null;
try {
tempFile = createTemporaryFile(context, file);
Collection<BlackboardArtifact> bbartifacts = getCookieArtifacts(file, tempFile);
if (!bbartifacts.isEmpty()) {
services.fireModuleDataEvent(new ModuleDataEvent(
RecentActivityExtracterModuleFactory.getModuleName(),
BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE, bbartifacts));
}
} finally {
if (tempFile != null) {
tempFile.delete();
}
}
}
/**
* Queries the history db for the history information creating a list of
* BlackBoardArtifact for each row returned from the db.
*
* @param origFile AbstractFile of the history file from the case
* @param tempFilePath Path to temporary copy of the history db
* @return Blackboard Artifacts for the history db or null if there are no
* history artifacts
* @throws TskCoreException
*/
private Collection<BlackboardArtifact> getHistoryArtifacts(AbstractFile origFile, Path tempFilePath) throws TskCoreException {
List<HashMap<String, Object>> historyList = this.dbConnect(tempFilePath.toString(), HISTORY_QUERY);
if (historyList == null || historyList.isEmpty()) {
return null;
}
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
for (HashMap<String, Object> row : historyList) {
String url = row.get(HEAD_URL).toString();
String title = row.get(HEAD_TITLE).toString();
Long time = (Double.valueOf(row.get(HEAD_TIME).toString())).longValue();
BlackboardArtifact bbart = origFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_HISTORY);
bbart.addAttributes(createHistoryAttribute(url, time, null, title,
this.getName(), NetworkUtils.extractDomain(url), null));
bbartifacts.add(bbart);
}
return bbartifacts;
}
/**
* Parses the temporary version of bookmarks.plist and creates
*
* @param origFile The origFile Bookmark.plist file from the case
* @param tempFile The temporary local version of Bookmark.plist
* @return Collection of BlackboardArtifacts for the bookmarks in origFile
* @throws IOException
* @throws PropertyListFormatException
* @throws ParseException
* @throws ParserConfigurationException
* @throws SAXException
* @throws TskCoreException
*/
private Collection<BlackboardArtifact> getBookmarkArtifacts(AbstractFile origFile, File tempFile) throws IOException, PropertyListFormatException, ParseException, ParserConfigurationException, SAXException, TskCoreException {
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
try {
NSDictionary root = (NSDictionary) PropertyListParser.parse(tempFile);
parseBookmarkDictionary(bbartifacts, origFile, root);
} catch (PropertyListFormatException ex) {
PropertyListFormatException plfe = new PropertyListFormatException(origFile.getName() + ": " + ex.getMessage());
plfe.setStackTrace(ex.getStackTrace());
throw plfe;
} catch (ParseException ex) {
ParseException pe = new ParseException(origFile.getName() + ": " + ex.getMessage(), ex.getErrorOffset());
pe.setStackTrace(ex.getStackTrace());
throw pe;
} catch (ParserConfigurationException ex) {
ParserConfigurationException pce = new ParserConfigurationException(origFile.getName() + ": " + ex.getMessage());
pce.setStackTrace(ex.getStackTrace());
throw pce;
} catch (SAXException ex) {
SAXException se = new SAXException(origFile.getName() + ": " + ex.getMessage());
se.setStackTrace(ex.getStackTrace());
throw se;
}
return bbartifacts;
}
/**
* Finds the download entries in the tempFile and creates a list of artifacts from them.
*
* @param origFile Download.plist file from case
* @param tempFile Temporary copy of download.plist file
* @return Collection of BlackboardArtifacts for the downloads in origFile
* @throws IOException
* @throws PropertyListFormatException
* @throws ParseException
* @throws ParserConfigurationException
* @throws SAXException
* @throws TskCoreException
*/
private Collection<BlackboardArtifact> getDownloadArtifacts(Content dataSource, AbstractFile origFile, File tempFile)throws IOException, PropertyListFormatException, ParseException, ParserConfigurationException, SAXException, TskCoreException {
Collection<BlackboardArtifact> bbartifacts = null;
try {
while(true){
NSDictionary root = (NSDictionary)PropertyListParser.parse(tempFile);
if(root == null)
break;
NSArray nsArray = (NSArray)root.get(PLIST_KEY_DOWNLOAD_HISTORY);
if(nsArray == null)
break;
NSObject[] objectArray = nsArray.getArray();
bbartifacts = new ArrayList<>();
for(NSObject obj: objectArray){
if(obj instanceof NSDictionary){
bbartifacts.add(parseDownloadDictionary(dataSource, origFile, (NSDictionary)obj));
}
}
break;
}
} catch (PropertyListFormatException ex) {
PropertyListFormatException plfe = new PropertyListFormatException(origFile.getName() + ": " + ex.getMessage());
plfe.setStackTrace(ex.getStackTrace());
throw plfe;
} catch (ParseException ex) {
ParseException pe = new ParseException(origFile.getName() + ": " + ex.getMessage(), ex.getErrorOffset());
pe.setStackTrace(ex.getStackTrace());
throw pe;
} catch (ParserConfigurationException ex) {
ParserConfigurationException pce = new ParserConfigurationException(origFile.getName() + ": " + ex.getMessage());
pce.setStackTrace(ex.getStackTrace());
throw pce;
} catch (SAXException ex) {
SAXException se = new SAXException(origFile.getName() + ": " + ex.getMessage());
se.setStackTrace(ex.getStackTrace());
throw se;
}
return bbartifacts;
}
/**
* Finds the cookies in the tempFile creating a list of BlackboardArtifacts
* each representing one cookie.
*
* @param origFile Original Cookies.binarycookie file from case
* @param tempFile Temporary copy of the cookies file
* @return List of Blackboard Artifacts, one for each cookie
* @throws TskCoreException
* @throws IOException
*/
private Collection<BlackboardArtifact> getCookieArtifacts(AbstractFile origFile, File tempFile) throws TskCoreException, IOException {
Collection<BlackboardArtifact> bbartifacts = null;
BinaryCookieReader reader = BinaryCookieReader.initalizeReader(tempFile);
if (reader != null) {
bbartifacts = new ArrayList<>();
Iterator<Cookie> iter = reader.iterator();
while (iter.hasNext()) {
Cookie cookie = iter.next();
BlackboardArtifact bbart = origFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_COOKIE);
bbart.addAttributes(createCookieAttributes(cookie.getURL(), cookie.getCreationDate(), cookie.getName(), cookie.getValue(), this.getName(), NetworkUtils.extractDomain(cookie.getURL())));
bbartifacts.add(bbart);
}
}
return bbartifacts;
}
/**
* Parses the plist object to find the bookmark child objects, then creates
* an artifact with the bookmark information.
*
* @param bbartifacts BlackboardArtifact list to add new the artifacts to
* @param origFile The origFile Bookmark.plist file from the case
* @param root NSDictionary object to parse
* @throws TskCoreException
*/
private void parseBookmarkDictionary(Collection<BlackboardArtifact> bbartifacts, AbstractFile origFile, NSDictionary root) throws TskCoreException {
if (root.containsKey(PLIST_KEY_CHILDREN)) {
NSArray children = (NSArray) root.objectForKey(PLIST_KEY_CHILDREN);
if (children != null) {
for (NSObject obj : children.getArray()) {
parseBookmarkDictionary(bbartifacts, origFile, (NSDictionary) obj);
}
}
} else if (root.containsKey(PLIST_KEY_URL)) {
String url = null;
String title = null;
NSString nsstr = (NSString) root.objectForKey(PLIST_KEY_URL);
if (nsstr != null) {
url = nsstr.toString();
}
NSDictionary dic = (NSDictionary) root.get(PLIST_KEY_URI);
nsstr = (NSString) root.objectForKey(PLIST_KEY_TITLE);
if (nsstr != null) {
title = ((NSString) dic.get(PLIST_KEY_TITLE)).toString();
}
if (url != null || title != null) {
BlackboardArtifact bbart = origFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_BOOKMARK);
bbart.addAttributes(createBookmarkAttributes(url, title, null, getName(), NetworkUtils.extractDomain(url)));
bbartifacts.add(bbart);
}
}
}
/**
* Parse the NSDictionary object that represents one download.
*
* @param origFile Download.plist file from the case
* @param entry One NSDictionary Object that represents one download
* instance
* @return a Blackboard Artifact for the download.
* @throws TskCoreException
*/
private BlackboardArtifact parseDownloadDictionary(Content dataSource, AbstractFile origFile, NSDictionary entry) throws TskCoreException {
String url = null;
String path = null;
Long time = null;
Long pathID = null;
NSString nsstring = (NSString) entry.get(PLIST_KEY_DOWNLOAD_URL);
if (nsstring != null) {
url = nsstring.toString();
}
nsstring = (NSString) entry.get(PLIST_KEY_DOWNLOAD_PATH);
if (nsstring != null) {
path = nsstring.toString();
pathID = Util.findID(dataSource, path);
}
NSDate date = (NSDate) entry.get(PLIST_KEY_DOWNLOAD_DATE);
if (date != null) {
time = date.getDate().getTime();
}
BlackboardArtifact bbart = origFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_DOWNLOAD);
bbart.addAttributes(this.createDownloadAttributes(path, pathID, url, time, NetworkUtils.extractDomain(url), getName()));
return bbart;
}
}
......@@ -74,11 +74,13 @@ public void startUp(IngestJobContext context) throws IngestModuleException {
Extract SEUQA = new SearchEngineURLQueryAnalyzer();
Extract osExtract = new ExtractOs();
Extract dataSourceAnalyzer = new DataSourceUsageAnalyzer();
Extract safari = new ExtractSafari();
extractors.add(chrome);
extractors.add(firefox);
extractors.add(iexplore);
extractors.add(edge);
extractors.add(safari);
extractors.add(recentDocuments);
extractors.add(SEUQA); // this needs to run after the web browser modules
extractors.add(registry); // this should run after quicker modules like the browser modules and needs to run before the DataSourceUsageAnalyzer
......@@ -89,6 +91,7 @@ public void startUp(IngestJobContext context) throws IngestModuleException {
browserExtractors.add(firefox);
browserExtractors.add(iexplore);
browserExtractors.add(edge);
browserExtractors.add(safari);
for (Extract extractor : extractors) {
extractor.init();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment