Merge branch 'develop' of github.com:sleuthkit/autopsy into central_repo_fixes_3693

This commit is contained in:
Eugene Livis 2018-04-05 12:19:01 -04:00
commit ec0583a69e
11 changed files with 845 additions and 635 deletions

View File

@ -31,7 +31,6 @@ import javax.swing.JPanel;
import javax.swing.filechooser.FileFilter; import javax.swing.filechooser.FileFilter;
import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.FilenameUtils;
import org.openide.modules.InstalledFileLocator; import org.openide.modules.InstalledFileLocator;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProvider;
@ -52,8 +51,8 @@ import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
*/ */
@ServiceProviders(value = { @ServiceProviders(value = {
@ServiceProvider(service = DataSourceProcessor.class), @ServiceProvider(service = DataSourceProcessor.class),
@ServiceProvider(service = AutoIngestDataSourceProcessor.class)} @ServiceProvider(service = AutoIngestDataSourceProcessor.class)
) })
@Messages({ @Messages({
"LocalFilesDSProcessor.logicalEvidenceFilter.desc=Logical Evidence Files (L01)" "LocalFilesDSProcessor.logicalEvidenceFilter.desc=Logical Evidence Files (L01)"
}) })
@ -344,15 +343,15 @@ public class LocalFilesDSProcessor implements DataSourceProcessor, AutoIngestDat
// It should return lowest possible non-zero confidence level and be treated // It should return lowest possible non-zero confidence level and be treated
// as the "option of last resort" for auto ingest purposes // as the "option of last resort" for auto ingest purposes
this.localFilePaths = Arrays.asList(new String[]{dataSourcePath.toString()}); List<String> filePaths = Arrays.asList(new String[]{dataSourcePath.toString()});
//If there is only 1 file check if it is an L01 file and if it is extract the //If there is only 1 file check if it is an L01 file and if it is extract the
//contents and replace the paths, if the contents can't be extracted return 0 //contents and replace the paths, if the contents can't be extracted return 0
if (localFilePaths.size() == 1) { if (filePaths.size() == 1) {
for (final String path : localFilePaths) { for (final String path : filePaths) {
if (new File(path).isFile() && LOGICAL_EVIDENCE_FILTER.accept(new File(path))) { if (new File(path).isFile() && LOGICAL_EVIDENCE_FILTER.accept(new File(path))) {
try { try {
//if the L01 option was chosen //if the L01 option was chosen
localFilePaths = extractLogicalEvidenceFileContents(localFilePaths); filePaths = extractLogicalEvidenceFileContents(filePaths);
} catch (L01Exception ex) { } catch (L01Exception ex) {
logger.log(Level.WARNING, "File extension was .l01 but contents of logical evidence file were unable to be extracted", ex); logger.log(Level.WARNING, "File extension was .l01 but contents of logical evidence file were unable to be extracted", ex);
//contents of l01 could not be extracted don't add data source or run ingest //contents of l01 could not be extracted don't add data source or run ingest
@ -369,7 +368,8 @@ public class LocalFilesDSProcessor implements DataSourceProcessor, AutoIngestDat
@Override @Override
public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) { public void process(String deviceId, Path dataSourcePath, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callBack) {
run(deviceId, deviceId, this.localFilePaths, progressMonitor, callBack); List<String> filePaths = Arrays.asList(new String[]{dataSourcePath.toString()});
run(deviceId, deviceId, filePaths, progressMonitor, callBack);
} }
/** /**

View File

@ -177,9 +177,15 @@ public abstract class AbstractSqlEamDb implements EamDb {
* @returns New Case class with populated database ID * @returns New Case class with populated database ID
*/ */
@Override @Override
public CorrelationCase newCase(CorrelationCase eamCase) throws EamDbException { public synchronized CorrelationCase newCase(CorrelationCase eamCase) throws EamDbException {
Connection conn = connect();
// check if there is already an existing CorrelationCase for this Case
CorrelationCase cRCase = getCaseByUUID(eamCase.getCaseUUID());
if (cRCase != null) {
return cRCase;
}
Connection conn = connect();
PreparedStatement preparedStatement = null; PreparedStatement preparedStatement = null;
String sql = "INSERT INTO cases(case_uid, org_id, case_name, creation_date, case_number, " String sql = "INSERT INTO cases(case_uid, org_id, case_name, creation_date, case_number, "

View File

@ -503,7 +503,6 @@ public class MessageContentViewer extends javax.swing.JPanel implements DataCont
rtfbodyTextPane.setText(""); rtfbodyTextPane.setText("");
htmlbodyTextPane.setText(""); htmlbodyTextPane.setText("");
textbodyTextArea.setText(""); textbodyTextArea.setText("");
drp.setNode(null);
showImagesToggleButton.setEnabled(false); showImagesToggleButton.setEnabled(false);
msgbodyTabbedPane.setEnabled(false); msgbodyTabbedPane.setEnabled(false);
} }

View File

@ -24,7 +24,7 @@ DataContentViewerString.pageLabel2.text=Page
# Product Information panel # Product Information panel
LBL_Description=<div style=\"font-size: 12pt; font-family: Verdana, 'Verdana CE', Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif;\">\n <b>Product Version:</b> {0} ({9}) <br><b>Sleuth Kit Version:</b> {7} <br><b>Netbeans RCP Build:</b> {8} <br> <b>Java:</b> {1}; {2}<br> <b>System:</b> {3}; {4}; {5}<br><b>Userdir:</b> {6}</div> LBL_Description=<div style=\"font-size: 12pt; font-family: Verdana, 'Verdana CE', Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif;\">\n <b>Product Version:</b> {0} ({9}) <br><b>Sleuth Kit Version:</b> {7} <br><b>Netbeans RCP Build:</b> {8} <br> <b>Java:</b> {1}; {2}<br> <b>System:</b> {3}; {4}; {5}<br><b>Userdir:</b> {6}</div>
Format_OperatingSystem_Value={0} version {1} running on {2} Format_OperatingSystem_Value={0} version {1} running on {2}
LBL_Copyright=<div style\="font-size\: 12pt; font-family\: Verdana, 'Verdana CE', Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif; ">Autopsy&trade; is a digital forensics platform based on The Sleuth Kit&trade; and other tools. <br><ul><li>General Information: <a style\="color\: \#1E2A60;" href\="http\://www.sleuthkit.org">http\://www.sleuthkit.org</a>.</li><li>Training: <a style\="color\: \#1E2A60;" href\="http://www.basistech.com/autopsy-training">http://www.basistech.com/autopsy-training</a></li><li>Commercial Support: <a style\="color\: \#1E2A60;" href\="http://www.basistech.com/digital-forensics/autopsy/support/">http://www.basistech.com/digital-forensics/autopsy/support/</a></li></ul>Copyright &copy; 2003-2017. </div> LBL_Copyright=<div style\="font-size\: 12pt; font-family\: Verdana, 'Verdana CE', Arial, 'Arial CE', 'Lucida Grande CE', lucida, 'Helvetica CE', sans-serif; ">Autopsy&trade; is a digital forensics platform based on The Sleuth Kit&trade; and other tools. <br><ul><li>General Information: <a style\="color\: \#1E2A60;" href\="http\://www.sleuthkit.org">http\://www.sleuthkit.org</a>.</li><li>Training: <a style\="color\: \#1E2A60;" href\="http://www.basistech.com/autopsy-training">http://www.basistech.com/autopsy-training</a></li><li>Commercial Support: <a style\="color\: \#1E2A60;" href\="http://www.basistech.com/digital-forensics/autopsy/support/">http://www.basistech.com/digital-forensics/autopsy/support/</a></li></ul>Copyright &copy; 2003-2018. </div>
URL_ON_IMG=http://www.sleuthkit.org/ URL_ON_IMG=http://www.sleuthkit.org/
URL_ON_HELP=http://sleuthkit.org/autopsy/docs/user-docs/4.6.0/ URL_ON_HELP=http://sleuthkit.org/autopsy/docs/user-docs/4.6.0/
FILE_FOR_LOCAL_HELP=file:/// FILE_FOR_LOCAL_HELP=file:///

View File

@ -72,8 +72,8 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
private static final Logger logger = Logger.getLogger(IngestJobSettingsPanel.class.getName()); private static final Logger logger = Logger.getLogger(IngestJobSettingsPanel.class.getName());
/** /**
* Construct a panel to allow a user to make ingest job settings. * Construct a panel to allow a user to make ingest job settings. This
* This constructor assumes there is no ingest history. * constructor assumes there is no ingest history.
* *
* @param settings The initial settings for the ingest job. * @param settings The initial settings for the ingest job.
*/ */
@ -88,8 +88,8 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
} }
/** /**
* Construct a panel to allow a user to make ingest job settings. * Construct a panel to allow a user to make ingest job settings. This
* This constructor enables tracking of ingest job history. * constructor enables tracking of ingest job history.
* *
* @param settings The initial settings for the ingest job. * @param settings The initial settings for the ingest job.
* @param dataSources The data sources ingest is being run on. * @param dataSources The data sources ingest is being run on.
@ -423,16 +423,20 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
} catch (FilesSetsManager.FilesSetsManagerException ex) { } catch (FilesSetsManager.FilesSetsManagerException ex) {
logger.log(Level.SEVERE, "Failed to get user created file ingest filters, only default available for selection", ex); //NON-NLS logger.log(Level.SEVERE, "Failed to get user created file ingest filters, only default available for selection", ex); //NON-NLS
} }
String filterToSelect = settings.getFileFilter().getName();
for (FilesSet filter : newFilterList) { //getting one of the recently created filters for (FilesSet filter : newFilterList) { //getting one of the recently created filters
if (!oldFilterList.contains(filter.getName())) { if (!oldFilterList.contains(filter.getName())) {
//set newly created filter to selected filter //set newly created filter to selected filter
settings.setFileFilter(filter); filterToSelect = filter.getName();
break; break;
} }
} }
fileIngestFilterComboBox.setModel(new DefaultComboBoxModel<>(getComboBoxContents())); fileIngestFilterComboBox.setModel(new DefaultComboBoxModel<>(getComboBoxContents()));
//set the selected filter after the comboBox Contents were updated to include it //set the selected filter after the comboBox Contents were updated to include it
fileIngestFilterComboBox.setSelectedItem(settings.getFileFilter().getName()); fileIngestFilterComboBox.setSelectedItem(filterToSelect);
//refresh the saved filter in use case where the selected modified filter
//has the same name as a previously existing filter
updateSelectedFilter(filterToSelect);
dialog.close(); dialog.close();
} }
); );
@ -440,21 +444,25 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
//return to saved selection in case they cancel out of filter creation //return to saved selection in case they cancel out of filter creation
fileIngestFilterComboBox.setSelectedItem(settings.getFileFilter().getName()); fileIngestFilterComboBox.setSelectedItem(settings.getFileFilter().getName());
} else if (evt.getActionCommand().equals("comboBoxChanged")) { } else if (evt.getActionCommand().equals("comboBoxChanged")) {
try { updateSelectedFilter(fileIngestFilterComboBox.getSelectedItem().toString());
Map<String, FilesSet> fileIngestFilters = FilesSetsManager.getInstance()
.getCustomFileIngestFilters();
for (FilesSet fSet : FilesSetsManager.getStandardFileIngestFilters()) {
fileIngestFilters.put(fSet.getName(), fSet);
}
settings.setFileFilter(fileIngestFilters
.get(fileIngestFilterComboBox.getSelectedItem().toString()));
} catch (FilesSetsManager.FilesSetsManagerException ex) {
settings.setFileFilter(FilesSetsManager.getDefaultFilter());
logger.log(Level.SEVERE, "Failed to get file ingest filter from combobox selection, default filter being used", ex); //NON-NLS
}
} }
}//GEN-LAST:event_fileIngestFilterComboBoxActionPerformed }//GEN-LAST:event_fileIngestFilterComboBoxActionPerformed
private void updateSelectedFilter(String filterName) {
try {
Map<String, FilesSet> fileIngestFilters = FilesSetsManager.getInstance()
.getCustomFileIngestFilters();
for (FilesSet fSet : FilesSetsManager.getStandardFileIngestFilters()) {
fileIngestFilters.put(fSet.getName(), fSet);
}
settings.setFileFilter(fileIngestFilters
.get(filterName));
} catch (FilesSetsManager.FilesSetsManagerException ex) {
settings.setFileFilter(FilesSetsManager.getDefaultFilter());
logger.log(Level.SEVERE, "Failed to get file ingest filter from combobox selection, default filter being used", ex); //NON-NLS
}
}
/** /**
* Returns an array which will contain the names of all options which should * Returns an array which will contain the names of all options which should
* exist in the "Run Ingest Modules On:" JCombobox * exist in the "Run Ingest Modules On:" JCombobox

View File

@ -44,6 +44,8 @@ import org.sleuthkit.autopsy.ingest.IngestJobSettings.IngestType;
import org.sleuthkit.autopsy.modules.filetypeid.FileTypeIdModuleFactory; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeIdModuleFactory;
import org.sleuthkit.autopsy.modules.interestingitems.FilesSet; import org.sleuthkit.autopsy.modules.interestingitems.FilesSet;
import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule; import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule;
import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.ExtensionCondition;
import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.FullNameCondition;
import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.MetaTypeCondition; import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.MetaTypeCondition;
import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.ParentPathCondition; import org.sleuthkit.autopsy.modules.interestingitems.FilesSet.Rule.ParentPathCondition;
import org.sleuthkit.autopsy.testutils.DataSourceProcessorRunner; import org.sleuthkit.autopsy.testutils.DataSourceProcessorRunner;
@ -147,8 +149,8 @@ public class IngestFileFiltersTest extends NbTestCase {
//All files in dir1 should have MIME type, except '.' '..' and slack files //All files in dir1 should have MIME type, except '.' '..' and slack files
if (file.getParentPath().equalsIgnoreCase("/dir1/")) { if (file.getParentPath().equalsIgnoreCase("/dir1/")) {
if (!(file.getName().equals(".") || file.getName().equals("..") || file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)) { if (!(file.getName().equals(".") || file.getName().equals("..") || file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.SLACK)) {
String errMsg = String.format("File %s (objId=%d) unexpectedly blocked by the file filter.", file.getName(), file.getId()); String errMsg = String.format("File %s (objId=%d) unexpectedly passed by the file filter.", file.getName(), file.getId());
assertTrue(errMsg, !(file.getMIMEType() == null || file.getMIMEType().isEmpty())); assertTrue(errMsg, file.getMIMEType() != null && !file.getMIMEType().isEmpty());
} }
} else { //All files not in dir1 shouldn't have MIME type } else { //All files not in dir1 shouldn't have MIME type
String errMsg = String.format("File %s (objId=%d) unexpectedly passed by the file filter.", file.getName(), file.getId()); String errMsg = String.format("File %s (objId=%d) unexpectedly passed by the file filter.", file.getName(), file.getId());
@ -161,6 +163,98 @@ public class IngestFileFiltersTest extends NbTestCase {
} }
} }
public void testExtAndDirWithOneRule() {
HashMap<String, Rule> rules = new HashMap<>();
rules.put("Rule", new Rule("testExtAndDirWithOneRule", new ExtensionCondition("jpg"), new MetaTypeCondition(MetaTypeCondition.Type.FILES), new ParentPathCondition("dir1"), null, null, null));
//Build the filter that ignore unallocated space and with one rule
FilesSet filesExtDirsFilter = new FilesSet("Filter", "Filter to find all jpg files in dir1.", false, true, rules);
try {
Case openCase = Case.getOpenCase();
runIngestJob(openCase.getDataSources(), filesExtDirsFilter);
FileManager fileManager = Case.getOpenCase().getServices().getFileManager();
List<AbstractFile> results = fileManager.findFiles("%%");
assertEquals(62, results.size());
for (AbstractFile file : results) {
//Files with jpg extension in dir1 should have MIME Type
if (file.getParentPath().equalsIgnoreCase("/dir1/") && file.getNameExtension().equalsIgnoreCase("jpg")) {
String errMsg = String.format("File %s (objId=%d) unexpectedly blocked by the file filter.", file.getName(), file.getId());
assertTrue(errMsg, file.getMIMEType() != null && !file.getMIMEType().isEmpty());
} else { //All others shouldn't have MIME Type
String errMsg = String.format("File %s (objId=%d) unexpectedly passed by the file filter.", file.getName(), file.getId());
assertTrue(errMsg, file.getMIMEType() == null);
}
}
} catch (NoCurrentCaseException | TskCoreException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
public void testExtAndDirWithTwoRules() {
HashMap<String, Rule> rules = new HashMap<>();
rules.put("rule1", new Rule("FindJpgExtention", new ExtensionCondition("jpg"), new MetaTypeCondition(MetaTypeCondition.Type.FILES), null, null, null, null));
rules.put("rule2", new Rule("FindDir1Directory", null, new MetaTypeCondition(MetaTypeCondition.Type.FILES), new ParentPathCondition("dir1"), null, null, null));
//Build the filter that ingnore unallocated space and with 2 rules
FilesSet filesExtDirsFilter = new FilesSet("Filter", "Filter to find all files in dir1 and all files with jpg extention.", false, true, rules);
try {
Case openCase = Case.getOpenCase();
runIngestJob(openCase.getDataSources(), filesExtDirsFilter);
FileManager fileManager = Case.getOpenCase().getServices().getFileManager();
List<AbstractFile> results = fileManager.findFiles("%%");
assertEquals(62, results.size());
for (AbstractFile file : results) {
if (file.getNameExtension().equalsIgnoreCase("jpg")) { //All files with .jpg extension should have MIME type
String errMsg = String.format("File %s (objId=%d) unexpectedly blocked by the file filter.", file.getName(), file.getId());
assertTrue(errMsg, file.getMIMEType() != null && !file.getMIMEType().isEmpty());
} else if (file.getParentPath().equalsIgnoreCase("/dir1/")) {
//All files in dir1 should have MIME type except '.' '..' slack files
if (file.getName().equals(".") || file.getName().equals("..") || file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.SLACK) {
String errMsg = String.format("File %s (objId=%d) unexpectedly passed by the file filter.", file.getName(), file.getId());
assertTrue(errMsg, file.getMIMEType() == null);
} else {
String errMsg = String.format("File %s (objId=%d) unexpectedly blocked by the file filter.", file.getName(), file.getId());
assertTrue(errMsg, file.getMIMEType() != null && !file.getMIMEType().isEmpty());
}
} else { //All files that are not in dir1 or not with .jpg extension should not have MIME type
String errMsg = String.format("File %s (objId=%d) unexpectedly passed by the file filter.", file.getName(), file.getId());
assertTrue(errMsg, file.getMIMEType() == null);
}
}
} catch (NoCurrentCaseException | TskCoreException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
public void testFullFileNameRule() {
HashMap<String, Rule> rules = new HashMap<>();
rules.put("rule", new Rule("FindFileWithFullName", new FullNameCondition("file.docx"), new MetaTypeCondition(MetaTypeCondition.Type.FILES), null, null, null, null));
//Build the filter to find file: file.docx
FilesSet fullNameFilter = new FilesSet("Filter", "Filter to find file.docx.", false, true, rules);
try {
Case openCase = Case.getOpenCase();
runIngestJob(openCase.getDataSources(), fullNameFilter);
FileManager fileManager = Case.getOpenCase().getServices().getFileManager();
List<AbstractFile> results = fileManager.findFiles("%%");
assertEquals(62, results.size());
for (AbstractFile file : results) {
//Only file.docx has MIME Type
if (file.getName().equalsIgnoreCase("file.docx")) {
String errMsg = String.format("File %s (objId=%d) unexpectedly blocked by the file filter.", file.getName(), file.getId());
assertTrue(errMsg, file.getMIMEType() != null && !file.getMIMEType().isEmpty());
} else {
String errMsg = String.format("File %s (objId=%d) unexpectedly passed by the file filter.", file.getName(), file.getId());
assertTrue(errMsg, file.getMIMEType() == null);
}
}
} catch (NoCurrentCaseException | TskCoreException ex) {
Exceptions.printStackTrace(ex);
Assert.fail(ex);
}
}
private void runIngestJob(List<Content> datasources, FilesSet filter) { private void runIngestJob(List<Content> datasources, FilesSet filter) {
FileTypeIdModuleFactory factory = new FileTypeIdModuleFactory(); FileTypeIdModuleFactory factory = new FileTypeIdModuleFactory();
IngestModuleIngestJobSettings settings = factory.getDefaultIngestJobSettings(); IngestModuleIngestJobSettings settings = factory.getDefaultIngestJobSettings();
@ -171,6 +265,9 @@ public class IngestFileFiltersTest extends NbTestCase {
IngestJobSettings ingestJobSettings = new IngestJobSettings(IngestFileFiltersTest.class.getCanonicalName(), IngestType.FILES_ONLY, templates, filter); IngestJobSettings ingestJobSettings = new IngestJobSettings(IngestFileFiltersTest.class.getCanonicalName(), IngestType.FILES_ONLY, templates, filter);
try { try {
List<IngestModuleError> errs = IngestJobRunner.runIngestJob(datasources, ingestJobSettings); List<IngestModuleError> errs = IngestJobRunner.runIngestJob(datasources, ingestJobSettings);
for (IngestModuleError err : errs) {
System.out.println(String.format("Error: %s: %s.", err.getModuleDisplayName(), err.toString()));
}
assertEquals(0, errs.size()); assertEquals(0, errs.size());
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
Exceptions.printStackTrace(ex); Exceptions.printStackTrace(ex);

View File

@ -1,15 +1,15 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -23,80 +23,89 @@ import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.logging.Level;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Content;
/* /*
* A runnable that adds a raw data source to a case database. * A runnable that adds a memory image data source to a case database.
*/ */
final class AddMemoryImageTask implements Runnable { final class AddMemoryImageTask implements Runnable {
private static final Logger logger = Logger.getLogger(AddMemoryImageTask.class.getName()); private final static Logger logger = Logger.getLogger(AddMemoryImageTask.class.getName());
private final String deviceId; private final String deviceId;
private final String imageFilePath; private final String memoryImagePath;
private final String timeZone; private final String timeZone;
private final List<String> pluginsToRun; private final List<String> pluginsToRun;
private final DataSourceProcessorProgressMonitor progressMonitor; private final DataSourceProcessorProgressMonitor progressMonitor;
private final DataSourceProcessorCallback callback; private final DataSourceProcessorCallback callback;
private VolatilityProcessor volatilityProcessor = null; private volatile VolatilityProcessor volatilityProcessor;
private boolean isCancelled = false; private volatile boolean isCancelled;
/** /**
* Constructs a runnable that adds a raw data source to a case database. * Constructs a runnable that adds a memory image to a case database.
* *
* @param deviceId An ASCII-printable identifier for the * @param deviceId An ASCII-printable identifier for the device
* device associated with the data source * associated with the data source that is intended
* that is intended to be unique across * to be unique across multiple cases (e.g., a UUID).
* multiple cases (e.g., a UUID). * @param memoryImagePath Path to the memory image file.
* @param imageFilePath Path to a Raw data source file. * @param pluginsToRun The Volatility plugins to run.
* @param timeZone The time zone to use when processing dates * @param timeZone The time zone to use when processing dates and
* and times for the image, obtained from * times for the image, obtained from
* java.util.TimeZone.getID. * java.util.TimeZone.getID.
* @param breakupChunks 2GB or not breakup. * @param progressMonitor Progress monitor for reporting progressMonitor
* @param progressMonitor Progress monitor for reporting * during processing.
* progressMonitor during processing. * @param callback Callback to call when processing is done.
* @param callback Callback to call when processing is done.
*/ */
AddMemoryImageTask(String deviceId, String imageFilePath, List<String> PluginsToRun, String timeZone, long chunkSize, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { AddMemoryImageTask(String deviceId, String memoryImagePath, List<String> pluginsToRun, String timeZone, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
this.deviceId = deviceId; this.deviceId = deviceId;
this.imageFilePath = imageFilePath; this.memoryImagePath = memoryImagePath;
this.pluginsToRun = PluginsToRun; this.pluginsToRun = pluginsToRun;
this.timeZone = timeZone; this.timeZone = timeZone;
this.callback = callback; this.callback = callback;
this.progressMonitor = progressMonitor; this.progressMonitor = progressMonitor;
} }
/** /**
* Adds a raw data source to a case database. * Adds a memory image data source to a case database.
*/ */
@Override @Messages({
"# {0} - exception message",
"AddMemoryImageTask_errorMessage_criticalException= Critical error: {0}",
})
@Override
public void run() { public void run() {
if (isCancelled) {
return;
}
progressMonitor.setIndeterminate(true); progressMonitor.setIndeterminate(true);
progressMonitor.setProgress(0); progressMonitor.setProgress(0);
List<Content> dataSources = new ArrayList<>();
List<String> errorMessages = new ArrayList<>(); List<String> errorMessages = new ArrayList<>();
boolean criticalErrorOccurred = false; boolean criticalErrorOccurred = false;
Image dataSource = addImageToCase(errorMessages); try {
if (dataSource == null) { Image dataSource = addImageToCase();
dataSources.add(dataSource);
volatilityProcessor = new VolatilityProcessor(memoryImagePath, dataSource, pluginsToRun, progressMonitor);
volatilityProcessor.run();
} catch (NoCurrentCaseException | TskCoreException | VolatilityProcessor.VolatilityProcessorException ex) {
criticalErrorOccurred = true; criticalErrorOccurred = true;
errorMessages.add(Bundle.AddMemoryImageTask_errorMessage_criticalException(ex.getLocalizedMessage()));
/*
* Log the exception as well as add it to the error messages, to
* ensure that the stack trace is not lost.
*/
logger.log(Level.SEVERE, String.format("Critical error processing memory image data source at %s for device %s", memoryImagePath, deviceId), ex);
} }
/* call Volatility to process the image */ errorMessages.addAll(volatilityProcessor.getErrorMessages());
else {
if (isCancelled)
return;
volatilityProcessor = new VolatilityProcessor(imageFilePath, dataSource, pluginsToRun, progressMonitor);
if (volatilityProcessor.run()) {
criticalErrorOccurred = true;
}
errorMessages.addAll(volatilityProcessor.getErrorMessages());
}
progressMonitor.setProgress(100); progressMonitor.setProgress(100);
/** /**
@ -110,55 +119,64 @@ final class AddMemoryImageTask implements Runnable {
} else { } else {
result = DataSourceProcessorCallback.DataSourceProcessorResult.NO_ERRORS; result = DataSourceProcessorCallback.DataSourceProcessorResult.NO_ERRORS;
} }
callback.done(result, errorMessages, dataSources);
callback.done(result, errorMessages, new ArrayList<>(Arrays.asList(dataSource)));
} }
/** /**
* Attempts to add the input image to the case. * Attempts to add the input memory image to the case as a data source.
* *
* @param errorMessages If there are any error messages, the error messages * @return The Image object representation of the memeory image file data
* are added to this list for eventual return to the * source.
* caller via the callback. *
* @returns Image that was added to DB or null on error * @throws NoCurrentCaseException If there is no current case.
* @throws TskCoreException If there is an error adding the data
* source to the case database.
*/ */
@Messages({"AddMemoryImageTask.progress.add.text=Adding memory image: ", @Messages({
"AddMemoryImageTask.image.critical.error.adding=Critical error adding ", "# {0} - image file path",
"AddMemoryImageTask.for.device=for device ", "AddMemoryImageTask_progressMessage_addingImageFile= Adding memory image {0}",
"AddMemoryImageTask.image.notExisting=is not existing.", "# {0} - image file path",
"AddMemoryImageTask.image.noncritical.error.adding=Non-critical error adding "}) "# {1} - device id",
private Image addImageToCase(List<String> errorMessages) { "AddMemoryImageTask_exceptionMessage_noImageFile= Memory image file {0} for device {1} does not exist"
progressMonitor.setProgressText(Bundle.AddMemoryImageTask_progress_add_text() + imageFilePath); })
private Image addImageToCase() throws NoCurrentCaseException, TskCoreException {
SleuthkitCase caseDatabase = Case.getCurrentCase().getSleuthkitCase(); progressMonitor.setProgressText(Bundle.AddMemoryImageTask_progressMessage_addingImageFile( memoryImagePath));
caseDatabase.acquireExclusiveLock();
// verify it exists SleuthkitCase caseDatabase = Case.getOpenCase().getSleuthkitCase();
File imageFile = Paths.get(imageFilePath).toFile(); caseDatabase.acquireSingleUserCaseWriteLock();
if (!imageFile.exists()) {
errorMessages.add(Bundle.AddMemoryImageTask_image_critical_error_adding() + imageFilePath + Bundle.AddMemoryImageTask_for_device()
+ deviceId + Bundle.AddMemoryImageTask_image_notExisting());
return null;
}
try { try {
// add it to the DB /*
List<String> imageFilePaths = new ArrayList<>(); * Verify the memory image file exists.
imageFilePaths.add(imageFilePath); */
Image dataSource = caseDatabase.addImageInfo(0, imageFilePaths, timeZone); //TODO: change hard coded deviceId. File imageFile = Paths.get(memoryImagePath).toFile();
if (!imageFile.exists()) {
throw new TskCoreException(Bundle.AddMemoryImageTask_exceptionMessage_noImageFile(memoryImagePath, deviceId));
}
/*
* Add the data source.
*
* NOTE: The object id for device passed to
* SleuthkitCase.addImageInfo is hard-coded to zero for now. This
* will need to be changed when a Device abstraction is added to the
* SleuthKit data model.
*/
Image dataSource = caseDatabase.addImageInfo(0, new ArrayList<>(Arrays.asList(memoryImagePath)), timeZone);
return dataSource; return dataSource;
} catch (TskCoreException ex) {
errorMessages.add(Bundle.AddMemoryImageTask_image_critical_error_adding() + imageFilePath + Bundle.AddMemoryImageTask_for_device() + deviceId + ":" + ex.getLocalizedMessage());
return null;
} finally { } finally {
caseDatabase.releaseExclusiveLock(); caseDatabase.releaseSingleUserCaseWriteLock();
} }
} }
/**
* Requests cancellation of this task by setting a cancelled flag.
*/
void cancelTask() { void cancelTask() {
isCancelled = true; isCancelled = true;
if (volatilityProcessor != null) { if (volatilityProcessor != null) {
volatilityProcessor.cancel(); volatilityProcessor.cancel();
} }
} }
} }

View File

@ -1,15 +1,15 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -37,11 +37,13 @@ import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn; import javax.swing.table.TableColumn;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PathValidator; import org.sleuthkit.autopsy.coreutils.PathValidator;
final class MemoryDSInputPanel extends JPanel implements DocumentListener { final class MemoryDSInputPanel extends JPanel implements DocumentListener {
private static final long serialVersionUID = 1L; //default private static final long serialVersionUID = 1L; //default
private final String PROP_LASTINPUT_PATH = "LBL_LastInputFile_PATH"; private final String PROP_LASTINPUT_PATH = "LBL_LastInputFile_PATH";
private final JFileChooser fc = new JFileChooser(); private final JFileChooser fc = new JFileChooser();
@ -52,14 +54,14 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
private final List<String> PluginListNames = new ArrayList<>(); private final List<String> PluginListNames = new ArrayList<>();
private final Map<String, Boolean> pluginListStates = new HashMap<>(); // is set by listeners when users select and deselect items private final Map<String, Boolean> pluginListStates = new HashMap<>(); // is set by listeners when users select and deselect items
private final Boolean isEnabled = true; private final Boolean isEnabled = true;
/** /**
* Creates new MemoryDSInputPanel panel for user input * Creates new MemoryDSInputPanel panel for user input
*/ */
private MemoryDSInputPanel(String context) { private MemoryDSInputPanel(String context) {
this.pluginList = new String[]{"amcache","cmdline","cmdscan","consoles","malfind","netscan","notepad","pslist","psxview","shellbags","shimcache","shutdown","userassist", "apihooks","connscan","devicetree","dlllist","envars","filescan","gahti","getservicesids","getsids","handles","hashdump","hivelist","hivescan","impscan","ldrmodules","lsadump","modules","mutantscan","privs","psscan","pstree","sockets","svcscan","shimcache","timeliner","unloadedmodules","userhandles","vadinfo","verinfo"}; this.pluginList = new String[]{"amcache", "cmdline", "cmdscan", "consoles", "malfind", "netscan", "notepad", "pslist", "psxview", "shellbags", "shimcache", "shutdown", "userassist", "apihooks", "connscan", "devicetree", "dlllist", "envars", "filescan", "gahti", "getservicesids", "getsids", "handles", "hashdump", "hivelist", "hivescan", "impscan", "ldrmodules", "lsadump", "modules", "mutantscan", "privs", "psscan", "pstree", "sockets", "svcscan", "shimcache", "timeliner", "unloadedmodules", "userhandles", "vadinfo", "verinfo"};
Arrays.sort(this.pluginList); Arrays.sort(this.pluginList);
initComponents(); initComponents();
errorLabel.setVisible(false); errorLabel.setVisible(false);
@ -91,7 +93,7 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
private void postInit() { private void postInit() {
pathTextField.getDocument().addDocumentListener(this); pathTextField.getDocument().addDocumentListener(this);
} }
private void customizePluginListTable() { private void customizePluginListTable() {
PluginList.setModel(tableModel); PluginList.setModel(tableModel);
PluginList.setTableHeader(null); PluginList.setTableHeader(null);
@ -135,14 +137,14 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
// set the selected timezone // set the selected timezone
timeZoneComboBox.setSelectedItem(formatted); timeZoneComboBox.setSelectedItem(formatted);
} }
private void createVolatilityVersionList() { private void createVolatilityVersionList() {
volExecutableComboBox.addItem("2.6"); volExecutableComboBox.addItem("2.6");
volExecutableComboBox.addItem("2.5"); volExecutableComboBox.addItem("2.5");
} }
private void createPluginList() { private void createPluginList() {
PluginListNames.clear(); PluginListNames.clear();
pluginListStates.clear(); pluginListStates.clear();
@ -150,19 +152,19 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
// if the config file doesn't exist, then set them all to enabled // if the config file doesn't exist, then set them all to enabled
boolean allEnabled = !ModuleSettings.configExists(this.contextName); boolean allEnabled = !ModuleSettings.configExists(this.contextName);
Map<String, String> pluginMap = ModuleSettings.getConfigSettings(this.contextName); Map<String, String> pluginMap = ModuleSettings.getConfigSettings(this.contextName);
for (String plugin : pluginList) { for (String plugin : pluginList) {
PluginListNames.add(plugin); PluginListNames.add(plugin);
if (allEnabled) if (allEnabled) {
pluginListStates.put(plugin, true); pluginListStates.put(plugin, true);
else } else {
pluginListStates.put(plugin, pluginMap.containsKey(plugin)); pluginListStates.put(plugin, pluginMap.containsKey(plugin));
}
} }
tableModel.fireTableDataChanged(); tableModel.fireTableDataChanged();
//this.tableModel = pluginsToRun.getModel(); //this.tableModel = pluginsToRun.getModel();
} }
/** /**
* This method is called from within the constructor to initialize the form. * This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always * WARNING: Do NOT modify this code. The content of this method is always
@ -282,18 +284,18 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed
String oldText = pathTextField.getText(); String oldText = pathTextField.getText();
// set the current directory of the FileChooser if the ImagePath Field is valid // set the current directory of the FileChooser if the ImagePath Field is valid
File currentDir = new File(oldText); File currentDir = new File(oldText);
if (currentDir.exists()) { if (currentDir.exists()) {
fc.setCurrentDirectory(currentDir); fc.setCurrentDirectory(currentDir);
} }
int retval = fc.showOpenDialog(this); int retval = fc.showOpenDialog(this);
if (retval == JFileChooser.APPROVE_OPTION) { if (retval == JFileChooser.APPROVE_OPTION) {
String path = fc.getSelectedFile().getPath(); String path = fc.getSelectedFile().getPath();
pathTextField.setText(path); pathTextField.setText(path);
} }
}//GEN-LAST:event_browseButtonActionPerformed }//GEN-LAST:event_browseButtonActionPerformed
private void volExecutableComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_volExecutableComboBoxActionPerformed private void volExecutableComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_volExecutableComboBoxActionPerformed
@ -322,7 +324,7 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
String getImageFilePath() { String getImageFilePath() {
return pathTextField.getText(); return pathTextField.getText();
} }
List<String> getPluginsToRun() { List<String> getPluginsToRun() {
List<String> enabledPlugins = new ArrayList<>(); List<String> enabledPlugins = new ArrayList<>();
Map<String, String> pluginMap = new HashMap<>(); Map<String, String> pluginMap = new HashMap<>();
@ -332,7 +334,7 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
pluginMap.put(plugin, ""); pluginMap.put(plugin, "");
} }
} }
ModuleSettings.setConfigSettings(this.contextName, pluginMap); ModuleSettings.setConfigSettings(this.contextName, pluginMap);
// @@ Could return keys of set // @@ Could return keys of set
return enabledPlugins; return enabledPlugins;
@ -374,11 +376,19 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
* *
* @param path Absolute path to the selected data source * @param path Absolute path to the selected data source
*/ */
@Messages({"MemoryDSInputPanel.error.text=Path to multi-user data source is on \"C:\" drive"}) @Messages({
"MemoryDSInputPanel_errorMsg_noOpenCase=No open case",
"MemoryDSInputPanel_errorMsg_dataSourcePathOnCdrive=Path to multi-user data source is on \"C:\" drive"
})
private void warnIfPathIsInvalid(String path) { private void warnIfPathIsInvalid(String path) {
if (!PathValidator.isValid(path, Case.getCurrentCase().getCaseType())) { try {
if (!PathValidator.isValid(path, Case.getOpenCase().getCaseType())) {
errorLabel.setVisible(true);
errorLabel.setText(Bundle.MemoryDSInputPanel_errorMsg_dataSourcePathOnCdrive());
}
} catch (NoCurrentCaseException unused) {
errorLabel.setVisible(true); errorLabel.setVisible(true);
errorLabel.setText(Bundle.MemoryDSInputPanel_error_text()); errorLabel.setText(Bundle.MemoryDSInputPanel_errorMsg_dataSourcePathOnCdrive());
} }
} }
@ -470,5 +480,4 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
} }
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -28,21 +28,21 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
/** /**
* A MEmory data source processor that implements the DataSourceProcessor service * A memory image data source processor that implements the DataSourceProcessor
* provider interface to allow integration with the add data source wizard. It * service provider interface to allow integration with the Add Data Source
* also provides a run method overload to allow it to be used independently of * wizard. It also provides a run method overload to allow it to be used
* the wizard. * independently of the wizard.
*/ */
@ServiceProvider(service = DataSourceProcessor.class) @ServiceProvider(service = DataSourceProcessor.class)
public class MemoryDSProcessor implements DataSourceProcessor { public class MemoryDSProcessor implements DataSourceProcessor {
private final MemoryDSInputPanel configPanel; private final MemoryDSInputPanel configPanel;
private AddMemoryImageTask addImageTask = null; private AddMemoryImageTask addImageTask;
/* /*
* Constructs a Memory data source processor that implements the * Constructs a memory data source processor that implements the
* DataSourceProcessor service provider interface to allow integration with * DataSourceProcessor service provider interface to allow integration with
* the add data source wizard. It also provides a run method overload to * the Add Data source wizard. It also provides a run method overload to
* allow it to be used independently of the wizard. * allow it to be used independently of the wizard.
*/ */
public MemoryDSProcessor() { public MemoryDSProcessor() {
@ -117,37 +117,40 @@ public class MemoryDSProcessor implements DataSourceProcessor {
@Override @Override
public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
configPanel.storeSettings(); configPanel.storeSettings();
run(UUID.randomUUID().toString(), configPanel.getImageFilePath(), configPanel.getPluginsToRun(), configPanel.getTimeZone(), 0, progressMonitor, callback); run(UUID.randomUUID().toString(), configPanel.getImageFilePath(), configPanel.getPluginsToRun(), configPanel.getTimeZone(), progressMonitor, callback);
} }
/** /**
* Adds a "memory" data source to the case database using a background task in * Adds a memory image data source to the case database using a background
* a separate thread and the given settings instead of those provided by the * task in a separate thread and the given settings instead of those
* selection and configuration panel. Returns as soon as the background task * provided by the selection and configuration panel. Returns as soon as the
* is started and uses the callback object to signal task completion and * background task is started and uses the callback object to signal task
* return results. * completion and return results.
* *
* @param deviceId An ASCII-printable identifier for the device * @param deviceId An ASCII-printable identifier for the device
* associated with the data source that is * associated with the data source that is intended
* intended to be unique across multiple cases * to be unique across multiple cases (e.g., a UUID).
* (e.g., a UUID). * @param memoryImagePath Path to the memory image file.
* @param imageFilePath Path to the image file. * @param pluginsToRun The Volatility plugins to run.
* @param timeZone The time zone to use when processing dates * @param timeZone The time zone to use when processing dates and
* and times for the image, obtained from * times for the image, obtained from
* java.util.TimeZone.getID. * java.util.TimeZone.getID.
* @param chunkSize The maximum size of each chunk of the raw * @param progressMonitor Progress monitor for reporting progress during
* data source as it is divided up into virtual * processing.
* unallocated space files. * @param callback Callback to call when processing is done.
* @param progressMonitor Progress monitor for reporting progress
* during processing.
* @param callback Callback to call when processing is done.
*/ */
private void run(String deviceId, String imageFilePath, List<String> pluginsToRun, String timeZone, long chunkSize, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { private void run(String deviceId, String memoryImagePath, List<String> pluginsToRun, String timeZone, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
addImageTask = new AddMemoryImageTask(deviceId, imageFilePath, pluginsToRun, timeZone, 0, progressMonitor, callback); addImageTask = new AddMemoryImageTask(deviceId, memoryImagePath, pluginsToRun, timeZone, progressMonitor, callback);
new Thread(addImageTask).start(); new Thread(addImageTask).start();
//new Thread(new AddLocalFilesTask(deviceId, rootVirtualDirectoryName, localFilePaths, progressMonitor, callback)).start();
} }
/**
* Requests cancellation of the background task that adds a data source to
* the case database, after the task is started using the run method. This
* is a "best effort" cancellation, with no guarantees that the case
* database will be unchanged. If cancellation succeeded, the list of new
* data sources returned by the background task will be empty.
*/
@Override @Override
public void cancel() { public void cancel() {
if (addImageTask != null) { if (addImageTask != null) {
@ -165,4 +168,3 @@ public class MemoryDSProcessor implements DataSourceProcessor {
} }
} }

View File

@ -645,18 +645,18 @@ final class RegexQuery implements KeywordSearchQuery {
*/ */
static private void addAttributeIfNotAlreadyCaptured(Map<BlackboardAttribute.Type, BlackboardAttribute> attributeMap, ATTRIBUTE_TYPE attrType, String groupName, Matcher matcher) { static private void addAttributeIfNotAlreadyCaptured(Map<BlackboardAttribute.Type, BlackboardAttribute> attributeMap, ATTRIBUTE_TYPE attrType, String groupName, Matcher matcher) {
BlackboardAttribute.Type type = new BlackboardAttribute.Type(attrType); BlackboardAttribute.Type type = new BlackboardAttribute.Type(attrType);
attributeMap.computeIfAbsent(type, t -> {
if( ! attributeMap.containsKey(type)) {
String value = matcher.group(groupName); String value = matcher.group(groupName);
if (attrType.equals(ATTRIBUTE_TYPE.TSK_CARD_NUMBER)) { if (attrType.equals(ATTRIBUTE_TYPE.TSK_CARD_NUMBER)) {
attributeMap.put(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_KEYWORD), attributeMap.put(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_KEYWORD),
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD, MODULE_NAME, value)); new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD, MODULE_NAME, value));
value = CharMatcher.anyOf(" -").removeFrom(value); value = CharMatcher.anyOf(" -").removeFrom(value);
} }
if (StringUtils.isNotBlank(value)) { if (StringUtils.isNotBlank(value)) {
return new BlackboardAttribute(attrType, MODULE_NAME, value); attributeMap.put(type, new BlackboardAttribute(attrType, MODULE_NAME, value));
} else {
return null;
} }
}); }
} }
} }