diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chrome.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chrome.java index 14bdddd501..76a74fab79 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chrome.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chrome.java @@ -28,8 +28,6 @@ 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.*; @@ -40,10 +38,9 @@ import java.io.IOException; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; import org.openide.util.NbBundle; -import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.coreutils.NetworkUtils; import org.sleuthkit.autopsy.ingest.IngestJobContext; -import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Account; import org.sleuthkit.datamodel.BlackboardArtifact; diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Extract.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Extract.java index dccbb3fc2c..09bf37c985 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Extract.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Extract.java @@ -37,15 +37,20 @@ 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; -import org.sleuthkit.datamodel.*; +import org.sleuthkit.datamodel.Blackboard; +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; @Messages({"Extract.indexError.message=Failed to index artifact for keyword search.", "Extract.noOpenCase.errMsg=No open case available.", - "#{0} - the module name", + "# {0} - the module name", "Extractor.errPostingArtifacts=Error posting {0} artifacts to the blackboard."}) abstract class Extract { - private static final Logger logger = Logger.getLogger(Extract.class.getName()); + protected static final Logger logger = Logger.getLogger(Extract.class.getName()); protected Case currentCase; protected SleuthkitCase tskCase; @@ -180,21 +185,22 @@ abstract class Extract { /** * Returns a List of AbstractFile objects from TSK based on sql query. * - * @param rs is the resultset that needs to be converted to an arraylist + * @param results is the resultset that needs to be converted to an + * arraylist * * @return list returns the arraylist built from the converted resultset */ - private List> resultSetToArrayList(ResultSet rs) throws SQLException { - ResultSetMetaData md = rs.getMetaData(); - int columns = md.getColumnCount(); + private List> resultSetToArrayList(ResultSet results) throws SQLException { + ResultSetMetaData metaData = results.getMetaData(); + int columns = metaData.getColumnCount(); List> list = new ArrayList<>(50); - while (rs.next()) { + while (results.next()) { HashMap row = new HashMap<>(columns); for (int i = 1; i <= columns; ++i) { - if (rs.getObject(i) == null) { - row.put(md.getColumnName(i), ""); + if (results.getObject(i) == null) { + row.put(metaData.getColumnName(i), ""); } else { - row.put(md.getColumnName(i), rs.getObject(i)); + row.put(metaData.getColumnName(i), results.getObject(i)); } } list.add(row); diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index dae1e7e1f4..b5bc552445 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -49,7 +49,14 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; +import java.nio.file.Path; import static java.util.TimeZone.getTimeZone; +import org.openide.util.Lookup; +import org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException; +import org.sleuthkit.autopsy.ingest.IngestServices; +import org.sleuthkit.autopsy.ingest.ModuleDataEvent; +import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; +import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException; /** * Extract windows registry data using regripper. Runs two versions of @@ -76,8 +83,6 @@ class ExtractRegistry extends Extract { final private static int MS_IN_SEC = 1000; final private static String NEVER_DATE = "Never"; final private static String SECTION_DIVIDER = "-------------------------"; - private IngestJobContext context; - private final List rrCmd = new ArrayList<>(); private final List rrFullCmd = new ArrayList<>(); @@ -226,6 +231,7 @@ class ExtractRegistry extends Extract { } // create a report for the full output + if (!regOutputFiles.fullPlugins.isEmpty()) { //parse the full regripper output from SAM hive files if (regFileNameLocal.toLowerCase().contains("sam")) { if (parseSamPluginOutput(regOutputFiles.fullPlugins, regFile) == false) { @@ -353,6 +359,53 @@ class ExtractRegistry extends Extract { * * @return */ + private boolean parseAutopsyPluginOutput(String regFilePath, AbstractFile regFile) { + FileInputStream fstream = null; + try { + // Read the file in and create a Document and elements + File regfile = new File(regFilePath); + fstream = new FileInputStream(regfile); + String regString = new Scanner(fstream, "UTF-8").useDelimiter("\\Z").next(); //NON-NLS + String startdoc = ""; //NON-NLS + String result = regString.replaceAll("----------------------------------------", ""); + result = result.replaceAll("\\n", ""); //NON-NLS + result = result.replaceAll("\\r", ""); //NON-NLS + result = result.replaceAll("'", "'"); //NON-NLS + result = result.replaceAll("&", "&"); //NON-NLS + result = result.replace('\0', ' '); // NON-NLS + String enddoc = ""; //NON-NLS + String stringdoc = startdoc + result + enddoc; + DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + Document doc = builder.parse(new InputSource(new StringReader(stringdoc))); + + // cycle through the elements in the doc + Element oroot = doc.getDocumentElement(); + NodeList children = oroot.getChildNodes(); + int len = children.getLength(); + // Add all "usb" dataType nodes to collection of BlackboardArtifacts + // that we will submit in a ModuleDataEvent for additional processing. + Collection usbBBartifacts = new ArrayList<>(); + // Add all "ssid" dataType nodes to collection of BlackboardArtifacts + // that we will submit in a ModuleDataEvent for additional processing. + Collection wifiBBartifacts = new ArrayList<>(); + for (int i = 0; i < len; i++) { + Element tempnode = (Element) children.item(i); + + String dataType = tempnode.getNodeName(); + NodeList timenodes = tempnode.getElementsByTagName("mtime"); //NON-NLS + Long mtime = null; + if (timenodes.getLength() > 0) { + Element timenode = (Element) timenodes.item(0); + String etime = timenode.getTextContent(); + try { + Long epochtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(etime).getTime(); + mtime = epochtime; + String Tempdate = mtime.toString(); + mtime = Long.valueOf(Tempdate) / MS_IN_SEC; + } catch (ParseException ex) { + logger.log(Level.WARNING, "Failed to parse epoch time when parsing the registry."); //NON-NLS + } + } NodeList artroots = tempnode.getElementsByTagName("artifacts"); //NON-NLS if (artroots.getLength() == 0) { @@ -365,30 +418,402 @@ class ExtractRegistry extends Extract { String parentModuleName = NbBundle.getMessage(this.getClass(), "ExtractRegistry.parentModuleName.noSpace"); String winver = ""; - mtime = Long.valueOf(Tempdate) / MS_IN_SEC; + // If all artifact nodes should really go under one Blackboard artifact, need to process it differently + switch (dataType) { + case "WinVersion": //NON-NLS + String version = ""; + String systemRoot = ""; + String productId = ""; + String regOwner = ""; + String regOrg = ""; + Long installtime = null; + for (int j = 0; j < myartlist.getLength(); j++) { + Node artchild = myartlist.item(j); + // If it has attributes, then it is an Element (based off API) + if (artchild.hasAttributes()) { + Element artnode = (Element) artchild; + + String value = artnode.getTextContent().trim(); + String name = artnode.getAttribute("name"); //NON-NLS + switch (name) { + case "ProductName": // NON-NLS + version = value; + break; + case "CSDVersion": // NON-NLS + // This is dependant on the fact that ProductName shows up first in the module output + version = version + " " + value; + break; + case "SystemRoot": //NON-NLS + systemRoot = value; + break; + case "ProductId": //NON-NLS + productId = value; + break; + case "RegisteredOwner": //NON-NLS + regOwner = value; + break; + case "RegisteredOrganization": //NON-NLS + regOrg = value; + break; + case "InstallDate": //NON-NLS + try { + Long epochtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(value).getTime(); + installtime = epochtime; + String Tempdate = installtime.toString(); + installtime = Long.valueOf(Tempdate) / MS_IN_SEC; + } catch (ParseException e) { + logger.log(Level.SEVERE, "RegRipper::Conversion on DateTime -> ", e); //NON-NLS + } + break; + default: + break; + } + } + } + try { + Collection bbattributes = new ArrayList<>(); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, version)); + if (installtime != null) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, installtime)); + } + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, systemRoot)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PRODUCT_ID, parentModuleName, productId)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_OWNER, parentModuleName, regOwner)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ORGANIZATION, parentModuleName, regOrg)); + + // Check if there is already an OS_INFO artifact for this file, and add to that if possible. + ArrayList results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId()); + if (results.isEmpty()) { + BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO); + bbart.addAttributes(bbattributes); + + // index the artifact for keyword search + this.indexArtifact(bbart); + } else { + results.get(0).addAttributes(bbattributes); + } + + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard."); //NON-NLS } break; - case "shellfolders": // NON-NLS - // The User Shell Folders subkey stores the paths to Windows Explorer folders for the current user of the computer - // (https://technet.microsoft.com/en-us/library/Cc962613.aspx). - // No useful information. Skip. + case "Profiler": // NON-NLS + String os = ""; + String procArch = ""; + String procId = ""; + String tempDir = ""; + for (int j = 0; j < myartlist.getLength(); j++) { + Node artchild = myartlist.item(j); + // If it has attributes, then it is an Element (based off API) + if (artchild.hasAttributes()) { + Element artnode = (Element) artchild; + + String value = artnode.getTextContent().trim(); + String name = artnode.getAttribute("name"); //NON-NLS + switch (name) { + case "OS": // NON-NLS + os = value; + break; + case "PROCESSOR_ARCHITECTURE": // NON-NLS + procArch = value; + break; + case "PROCESSOR_IDENTIFIER": //NON-NLS + procId = value; + break; + case "TEMP": //NON-NLS + tempDir = value; + break; + default: + break; + } + } + } + try { + Collection bbattributes = new ArrayList<>(); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VERSION, parentModuleName, os)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE, parentModuleName, procArch)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEMP_DIR, parentModuleName, tempDir)); + + // Check if there is already an OS_INFO artifact for this file and add to that if possible + ArrayList results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId()); + if (results.isEmpty()) { + BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO); + bbart.addAttributes(bbattributes); + + // index the artifact for keyword search + this.indexArtifact(bbart); + } else { + results.get(0).addAttributes(bbattributes); + } + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS + } + break; + case "CompName": // NON-NLS + String compName = ""; + String domain = ""; + for (int j = 0; j < myartlist.getLength(); j++) { + Node artchild = myartlist.item(j); + // If it has attributes, then it is an Element (based off API) + if (artchild.hasAttributes()) { + Element artnode = (Element) artchild; + + String value = artnode.getTextContent().trim(); + String name = artnode.getAttribute("name"); //NON-NLS + + if (name.equals("ComputerName")) { // NON-NLS + compName = value; + } else if (name.equals("Domain")) { // NON-NLS + domain = value; + } + } + } + try { + Collection bbattributes = new ArrayList<>(); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, compName)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, parentModuleName, domain)); + + // Check if there is already an OS_INFO artifact for this file and add to that if possible + ArrayList results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId()); + if (results.isEmpty()) { + BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO); + bbart.addAttributes(bbattributes); + + // index the artifact for keyword search + this.indexArtifact(bbart); + } else { + results.get(0).addAttributes(bbattributes); + } + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS + } break; default: - logger.log(Level.WARNING, "Unrecognized node name: {0}", dataType); //NON-NLS - break; - } - ArrayList results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId()); - ArrayList results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId()); + for (int j = 0; j < myartlist.getLength(); j++) { + Node artchild = myartlist.item(j); + // If it has attributes, then it is an Element (based off API) + if (artchild.hasAttributes()) { + Element artnode = (Element) artchild; + + String value = artnode.getTextContent().trim(); + Collection bbattributes = new ArrayList<>(); + + switch (dataType) { + case "recentdocs": //NON-NLS + // BlackboardArtifact bbart = tskCase.getContentById(orgId).newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT); + // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", dataType, mtime)); + // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity", dataType, mtimeItem)); + // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), "RecentActivity", dataType, value)); + // bbart.addAttributes(bbattributes); + // @@@ BC: Why are we ignoring this... + break; + case "usb": //NON-NLS + try { + Long usbMtime = Long.parseLong(artnode.getAttribute("mtime")); //NON-NLS + usbMtime = Long.valueOf(usbMtime.toString()); + + BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime)); + String dev = artnode.getAttribute("dev"); //NON-NLS + String make = ""; + String model = dev; + if (dev.toLowerCase().contains("vid")) { //NON-NLS + USBInfo info = USB_MAPPER.parseAndLookup(dev); + if (info.getVendor() != null) { + make = info.getVendor(); + } + if (info.getProduct() != null) { + model = info.getProduct(); + } + } + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value)); + bbart.addAttributes(bbattributes); + + // index the artifact for keyword search + this.indexArtifact(bbart); + // add to collection for ModuleDataEvent + usbBBartifacts.add(bbart); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding device attached artifact to blackboard."); //NON-NLS + } + break; + case "uninstall": //NON-NLS + Long itemMtime = null; + try { + Long epochtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(artnode.getAttribute("mtime")).getTime(); //NON-NLS + itemMtime = epochtime; + itemMtime = itemMtime / MS_IN_SEC; + } catch (ParseException e) { + logger.log(Level.WARNING, "Failed to parse epoch time for installed program artifact."); //NON-NLS + } + + try { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, value)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, itemMtime)); + BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG); + bbart.addAttributes(bbattributes); + + // index the artifact for keyword search + this.indexArtifact(bbart); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard."); //NON-NLS + } + break; + case "office": //NON-NLS + String officeName = artnode.getAttribute("name"); //NON-NLS + + try { + BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT); + // @@@ BC: Consider removing this after some more testing. It looks like an Mtime associated with the root key and not the individual item + if (mtime != null) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, parentModuleName, mtime)); + } + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, officeName)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, parentModuleName, value)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, artnode.getNodeName())); + bbart.addAttributes(bbattributes); + + // index the artifact for keyword search + this.indexArtifact(bbart); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding recent object artifact to blackboard."); //NON-NLS + } + break; + + case "ProcessorArchitecture": //NON-NLS + // Architecture is now included under Profiler + //try { + // String processorArchitecture = value; + // if (processorArchitecture.equals("AMD64")) + // processorArchitecture = "x86-64"; + + // BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO); + // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE.getTypeID(), parentModuleName, processorArchitecture)); + // bbart.addAttributes(bbattributes); + //} catch (TskCoreException ex) { + // logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS + //} + break; + + case "ProfileList": //NON-NLS + try { + String homeDir = value; + String sid = artnode.getAttribute("sid"); //NON-NLS + String username = artnode.getAttribute("username"); //NON-NLS + BlackboardArtifact bbart = null; + try { + //check if any of the existing artifacts match this username + ArrayList existingArtifacts = currentCase.getSleuthkitCase().getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT); + for (BlackboardArtifact artifact : existingArtifacts) { + if (artifact.getDataSource().getId() == regFile.getDataSourceObjectId()) { + BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID)); + if (attribute != null && attribute.getValueString().equals(sid)) { + bbart = artifact; + break; + } + } + } + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Error getting existing os account artifact", ex); + } + if (bbart == null) { + //create new artifact + bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, + parentModuleName, username)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID, + parentModuleName, sid)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, + parentModuleName, homeDir)); + } else { + //add attributes to existing artifact + BlackboardAttribute bbattr = bbart.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_NAME)); + + if (bbattr == null) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, + parentModuleName, username)); + } + bbattr = bbart.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH)); + if (bbattr == null) { + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, + parentModuleName, homeDir)); + } + } + bbart.addAttributes(bbattributes); + // index the artifact for keyword search + this.indexArtifact(bbart); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding account artifact to blackboard."); //NON-NLS + } + break; + + case "NtuserNetwork": // NON-NLS + try { + String localPath = artnode.getAttribute("localPath"); //NON-NLS + String remoteName = value; + BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_REMOTE_DRIVE); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH, + parentModuleName, localPath)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH, + parentModuleName, remoteName)); + bbart.addAttributes(bbattributes); + // index the artifact for keyword search + this.indexArtifact(bbart); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding network artifact to blackboard."); //NON-NLS + } + break; + case "SSID": // NON-NLS + String adapter = artnode.getAttribute("adapter"); //NON-NLS + try { + Long lastWriteTime = Long.parseLong(artnode.getAttribute("writeTime")); //NON-NLS + lastWriteTime = Long.valueOf(lastWriteTime.toString()); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SSID, parentModuleName, value)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, lastWriteTime)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, adapter)); + BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_WIFI_NETWORK); + bbart.addAttributes(bbattributes); + // index the artifact for keyword search + this.indexArtifact(bbart); + wifiBBartifacts.add(bbart); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error adding SSID artifact to blackboard."); //NON-NLS + } + break; + case "shellfolders": // NON-NLS + // The User Shell Folders subkey stores the paths to Windows Explorer folders for the current user of the computer + // (https://technet.microsoft.com/en-us/library/Cc962613.aspx). + // No useful information. Skip. + break; + + default: + logger.log(Level.WARNING, "Unrecognized node name: {0}", dataType); //NON-NLS + break; + } + } + } break; } } // for - // BlackboardArtifact bbart = tskCase.getContentById(orgId).newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT); - itemMtime = itemMtime / MS_IN_SEC; - + + return true; + } catch (FileNotFoundException ex) { + logger.log(Level.SEVERE, "Error finding the registry file.", ex); //NON-NLS + } catch (SAXException ex) { + logger.log(Level.SEVERE, "Error parsing the registry XML: {0}", ex); //NON-NLS + } catch (IOException ex) { + logger.log(Level.SEVERE, "Error building the document parser: {0}", ex); //NON-NLS + } catch (ParserConfigurationException ex) { + logger.log(Level.SEVERE, "Error configuring the registry parser: {0}", ex); //NON-NLS + } finally { + try { + if (fstream != null) { + fstream.close(); } } catch (IOException ex) { } - logger.log(Level.SEVERE, "Error finding the registry file.", ex); //NON-NLS } return false; } diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java index f858942375..2b41d8b5ff 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java @@ -89,7 +89,6 @@ class Firefox extends Extract { private final IngestServices services = IngestServices.getInstance(); private Content dataSource; private IngestJobContext context; - private final String moduleName; Firefox() { moduleName = NbBundle.getMessage(Firefox.class, "Firefox.moduleName"); @@ -969,320 +968,6 @@ class Firefox extends Extract { } - /** - * Gets data from formshistory.sqlite database. - * Parses and creates artifacts. - */ - private void getFormsHistory() { - FileManager fileManager = currentCase.getServices().getFileManager(); - List formHistoryFiles; - - // Some fields are just noisy and can me excluded - Set excludedFieldNames = new HashSet<>(Arrays.asList( - "it", // some kind of timestamp - "ts" // some kind of timestamp - )); - - try { - formHistoryFiles = fileManager.findFiles(dataSource, "formhistory.sqlite", "Firefox"); //NON-NLS - } catch (TskCoreException ex) { - String msg = NbBundle.getMessage(this.getClass(), "Firefox.getFormsAutofill.errMsg.errFetchingFiles"); - logger.log(Level.WARNING, msg); - this.addErrorMessage(this.getName() + ": " + msg); - return; - } - - if (formHistoryFiles.isEmpty()) { - String msg = NbBundle.getMessage(this.getClass(), "Firefox.getFormsAutofill.errMsg.noFilesFound"); - logger.log(Level.INFO, msg); - return; - } - - dataFound = true; - Collection bbartifacts = new ArrayList<>(); - int j = 0; - for (AbstractFile formHistoryFile : formHistoryFiles) { - if (formHistoryFile.getSize() == 0) { - continue; - } - - String fileName = formHistoryFile.getName(); - String tempFilePath = RAImageIngestModule.getRATempPath(currentCase, "firefox") + File.separator + fileName + j + ".db"; //NON-NLS - try { - ContentUtils.writeToFile(formHistoryFile, new File(tempFilePath), context::dataSourceIngestIsCancelled); - } catch (ReadContentInputStreamException ex) { - logger.log(Level.WARNING, String.format("Error reading Firefox web history artifacts file '%s' (id=%d).", - fileName, formHistoryFile.getId()), ex); //NON-NLS - this.addErrorMessage( - NbBundle.getMessage(this.getClass(), "Firefox.getFormsAutofill.errMsg.errAnalyzeFile", this.getName(), - 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).", - tempFilePath, fileName, formHistoryFile.getId()), ex); //NON-NLS - this.addErrorMessage( - NbBundle.getMessage(this.getClass(), "Firefox.getFormsAutofill.errMsg.errAnalyzeFile", this.getName(), - fileName)); - continue; - } - File dbFile = new File(tempFilePath); - if (context.dataSourceIngestIsCancelled()) { - dbFile.delete(); - break; - } - - // The table schema is a little different in newer version of Firefox - boolean isFirefoxV64 = Util.checkColumn("timesUsed", "moz_formhistory", tempFilePath); - String formHistoryQuery = (isFirefoxV64) ? FORMHISTORY_QUERY_V64 : FORMHISTORY_QUERY; - - List> tempList = this.dbConnect(tempFilePath, formHistoryQuery); - logger.log(Level.INFO, "{0} - Now getting history from {1} with {2} artifacts identified.", new Object[]{moduleName, tempFilePath, tempList.size()}); //NON-NLS - for (HashMap result : tempList) { - Collection bbattributes = new ArrayList<>(); - - String fieldName = ((result.get("fieldname").toString() != null) ? result.get("fieldname").toString() : ""); - // filter out unuseful values - if (excludedFieldNames.contains(fieldName.toLowerCase())) { - continue; - } - - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, - NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), - fieldName)); //NON-NLS - - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, - NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), - ((result.get("value").toString() != null) ? result.get("value").toString() : ""))); //NON-NLS - - // Newer versions of firefox have additional columns - if (isFirefoxV64) { - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED, - NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), - (Long.valueOf(result.get("firstUsed").toString()) / 1000000))); //NON-NLS - - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, - NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), - (Long.valueOf(result.get("lastUsed").toString()) / 1000000))); //NON-NLS - - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT, - NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), - (Integer.valueOf(result.get("timesUsed").toString())))); //NON-NLS - - } - // Add artifact - BlackboardArtifact bbart = this.addArtifact(ARTIFACT_TYPE.TSK_WEB_FORM_AUTOFILL, formHistoryFile, bbattributes); - if (bbart != null) { - this.indexArtifact(bbart); - bbartifacts.add(bbart); - } - } - ++j; - dbFile.delete(); - } - - services.fireModuleDataEvent(new ModuleDataEvent( - NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), - BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_FORM_AUTOFILL, bbartifacts)); - } - - - /** - * Gets data from autofill-profiles.json file. - * Parses file and makes artifacts. - * - */ - private void getAutofillProfiles() { - FileManager fileManager = currentCase.getServices().getFileManager(); - List autofillProfilesFiles; - try { - autofillProfilesFiles = fileManager.findFiles(dataSource, "autofill-profiles.json", "Firefox"); //NON-NLS - } catch (TskCoreException ex) { - String msg = NbBundle.getMessage(this.getClass(), "Firefox.getAutofillProfiles.errMsg.errGettingFiles"); - logger.log(Level.SEVERE, msg, ex); - this.addErrorMessage(this.getName() + ": " + msg); - return; - } - - if (autofillProfilesFiles.isEmpty()) { - logger.log(Level.INFO, "Didn't find any Firefox Autofill Profiles files."); //NON-NLS - return; - } - - dataFound = true; - Collection bbartifacts = new ArrayList<>(); - int j = 0; - - while (j < autofillProfilesFiles.size()) { - AbstractFile profileFile = autofillProfilesFiles.get(j++); - if (profileFile.getSize() == 0) { - continue; - } - String temps = RAImageIngestModule.getRATempPath(currentCase, "Firefox") + File.separator + profileFile.getName() + j + ".json"; //NON-NLS - try { - ContentUtils.writeToFile(profileFile, new File(temps), context::dataSourceIngestIsCancelled); - } catch (ReadContentInputStreamException ex) { - logger.log(Level.WARNING, String.format("Error reading Firefox Autofill profiles artifacts file '%s' (id=%d).", - profileFile.getName(), profileFile.getId()), ex); //NON-NLS - this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getAutofillProfiles.errMsg.errAnalyzingFile", - this.getName(), profileFile.getName())); - continue; - } catch (IOException ex) { - logger.log(Level.SEVERE, String.format("Error writing temp file '%s' for Firefox Autofill profiles file '%s' (id=%d).", - temps, profileFile.getName(), profileFile.getId()), ex); //NON-NLS - this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getAutofillProfiles.errMsg.errAnalyzingFile", - this.getName(), profileFile.getName())); - continue; - } - - logger.log(Level.INFO, "{0}- Now getting Bookmarks from {1}", new Object[]{moduleName, temps}); //NON-NLS - File dbFile = new File(temps); - if (context.dataSourceIngestIsCancelled()) { - dbFile.delete(); - break; - } - - FileReader tempReader; - try { - tempReader = new FileReader(temps); - } catch (FileNotFoundException ex) { - logger.log(Level.SEVERE, "Error while trying to read the Autofill profiles json file for Firefox.", ex); //NON-NLS - this.addErrorMessage( - NbBundle.getMessage(this.getClass(), "Firefox.getAutofillProfiles.errMsg.errAnalyzeFile", this.getName(), - profileFile.getName())); - continue; - } - - final JsonParser parser = new JsonParser(); - - JsonObject jsonRootObject; - JsonArray jAddressesArray; - - try { - jsonRootObject = parser.parse(tempReader).getAsJsonObject(); - jAddressesArray = jsonRootObject.getAsJsonArray("addresses"); //NON-NLS - } catch (JsonIOException | JsonSyntaxException | IllegalStateException ex) { - logger.log(Level.WARNING, "Error parsing Json for Firefox Autofill profiles.", ex); //NON-NLS - this.addErrorMessage(NbBundle.getMessage(this.getClass(), "Firefox.getAutofillProfiles.errMsg.errAnalyzingFile3", - this.getName(), profileFile.getName())); - continue; - } - - for (JsonElement result : jAddressesArray) { - JsonObject address = result.getAsJsonObject(); - if (address == null) { - continue; - } - - JsonElement nameEl = address.get("name"); //NON-NLS - String name = (nameEl != null) ? nameEl.getAsString() : ""; - - JsonElement emailEl = address.get("email"); //NON-NLS - String email = (emailEl != null) ? emailEl.getAsString() : ""; - - JsonElement telEl = address.get("tel"); //NON-NLS - String tel = (telEl != null) ? telEl.getAsString() : ""; - JsonElement telCountryCodeEl = address.get("tel-country-code"); //NON-NLS - String telCountryCode = (telCountryCodeEl != null) ? telCountryCodeEl.getAsString() : ""; - JsonElement telNationalEl = address.get("tel-national"); //NON-NLS - String telNational = (telNationalEl != null) ? telNationalEl.getAsString() : ""; - - String phoneNumber = makeTelNumber(tel, telCountryCode, telNational); - - JsonElement createdEl = address.get("timeCreated"); //NON-NLS - Long datetimeCreated = (createdEl != null) ? createdEl.getAsLong()/1000 : Long.valueOf(0); - JsonElement lastusedEl = address.get("timeLastUsed"); //NON-NLS - Long datetimeLastUsed = (lastusedEl != null) ? lastusedEl.getAsLong()/1000 : Long.valueOf(0); - JsonElement timesUsedEl = address.get("timesUsed"); //NON-NLS - Integer timesUsed = (timesUsedEl != null) ? timesUsedEl.getAsShort() : Integer.valueOf(0); - - JsonElement addressLine1El = address.get("address-line1"); //NON-NLS - String addressLine1 = (addressLine1El != null) ? addressLine1El.getAsString() : ""; - JsonElement addressLine2El = address.get("address-line2"); //NON-NLS - String addressLine2 = (addressLine2El != null) ? addressLine2El.getAsString() : ""; - JsonElement addressLine3El = address.get("address-line3"); //NON-NLS - String addressLine3 = (addressLine3El != null) ? addressLine3El.getAsString() : ""; - - JsonElement postalCodeEl = address.get("postal-code"); //NON-NLS - String postalCode = (postalCodeEl != null) ? postalCodeEl.getAsString() : ""; - JsonElement countryEl = address.get("country"); //NON-NLS - String country = (countryEl != null) ? countryEl.getAsString() : ""; - - String mailingAddress = makeFullAddress(addressLine1, addressLine2, addressLine3, postalCode, country ); - - try { - Collection bbattributes = new ArrayList<>(); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME_PERSON, - NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), - name)); //NON-NLS - - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL, - NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), - email)); //NON-NLS - - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, - NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), - phoneNumber)); //NON-NLS - - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCATION, - NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), - mailingAddress)); //NON-NLS - - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED, - NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), - datetimeCreated)); //NON-NLS - - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, - NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), - datetimeLastUsed)); //NON-NLS - - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT, - NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), - timesUsed)); //NON-NLS - - BlackboardArtifact bbart = profileFile.newArtifact(ARTIFACT_TYPE.TSK_WEB_FORM_ADDRESS); - - // index the artifact for keyword search - if (bbart != null) { - bbart.addAttributes(bbattributes); - this.indexArtifact(bbart); - bbartifacts.add(bbart); - } - - // If an email address is found, create an account instance for it - if (email != null && !email.isEmpty()) { - try { - Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(Account.Type.EMAIL, email, NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), profileFile); - } catch (NoCurrentCaseException | TskCoreException ex) { - logger.log(Level.SEVERE, String.format("Error creating email account instance for '%s' from Firefox profiles file '%s' .", - email, profileFile.getName()), ex); //NON-NLS - } - } - - // If a phone number is found, create an account instance for it - if (phoneNumber != null && !phoneNumber.isEmpty()) { - try { - Case.getCurrentCaseThrows().getSleuthkitCase().getCommunicationsManager().createAccountFileInstance(Account.Type.PHONE, phoneNumber, NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), profileFile); - } catch (NoCurrentCaseException | TskCoreException ex) { - logger.log(Level.SEVERE, String.format("Error creating phone number account instance for '%s' from Chrome profiles file '%s' .", - phoneNumber, profileFile.getName()), ex); //NON-NLS - } - } - - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error while trying to insert Firefox Autofill profile artifact{0}", ex); //NON-NLS - this.addErrorMessage( - NbBundle.getMessage(this.getClass(), "Firefox.getAutofillProfiles.errMsg.errAnalyzingFile4", - this.getName(), profileFile.getName())); - } - } - dbFile.delete(); - } - - IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent( - NbBundle.getMessage(this.getClass(), "Firefox.parentModuleName"), - BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_FORM_ADDRESS, bbartifacts)); - } - /** * Extract the domain from the supplied URL. This method does additional * checks to detect invalid URLs. diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java index ae0ad97e9c..5f1c31664a 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java @@ -47,7 +47,7 @@ public final class RAImageIngestModule implements DataSourceIngestModule { private static final Logger logger = Logger.getLogger(RAImageIngestModule.class.getName()); private final List extractors = new ArrayList<>(); private final List browserExtractors = new ArrayList<>(); - private final IngestServices services = IngestServices.getInstance(); + private IngestServices services = IngestServices.getInstance(); private IngestJobContext context; private StringBuilder subCompleted = new StringBuilder(); @@ -68,6 +68,8 @@ public final class RAImageIngestModule implements DataSourceIngestModule { Extract registry = new ExtractRegistry(); Extract recentDocuments = new RecentDocumentsByLnk(); Extract chrome = new Chrome(); + Extract firefox = new Firefox(); + Extract SEUQA = new SearchEngineURLQueryAnalyzer(); Extract osExtract = new ExtractOs(); Extract dataSourceAnalyzer = new DataSourceUsageAnalyzer(); @@ -156,7 +158,7 @@ public final class RAImageIngestModule implements DataSourceIngestModule { historyMsg.append( NbBundle.getMessage(this.getClass(), "RAImageIngestModule.process.histMsg.title", dataSource.getName())); for (Extract module : browserExtractors) { - historyMsg.append("
  • ").append(module.getModuleName()); //NON-NLS + historyMsg.append("
  • ").append(module.getName()); //NON-NLS historyMsg.append(": ").append((module.foundData()) ? NbBundle .getMessage(this.getClass(), "RAImageIngestModule.process.histMsg.found") : NbBundle .getMessage(this.getClass(), "RAImageIngestModule.process.histMsg.notFnd")); @@ -176,6 +178,15 @@ public final class RAImageIngestModule implements DataSourceIngestModule { for (int i = 0; i < extractors.size(); i++) { Extract extracter = extractors.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; }