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 org.apache.commons.io.FilenameUtils;
import org.openide.modules.InstalledFileLocator;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.openide.util.lookup.ServiceProvider;
@ -52,8 +51,8 @@ import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
*/
@ServiceProviders(value = {
@ServiceProvider(service = DataSourceProcessor.class),
@ServiceProvider(service = AutoIngestDataSourceProcessor.class)}
)
@ServiceProvider(service = AutoIngestDataSourceProcessor.class)
})
@Messages({
"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
// 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
//contents and replace the paths, if the contents can't be extracted return 0
if (localFilePaths.size() == 1) {
for (final String path : localFilePaths) {
if (filePaths.size() == 1) {
for (final String path : filePaths) {
if (new File(path).isFile() && LOGICAL_EVIDENCE_FILTER.accept(new File(path))) {
try {
//if the L01 option was chosen
localFilePaths = extractLogicalEvidenceFileContents(localFilePaths);
filePaths = extractLogicalEvidenceFileContents(filePaths);
} catch (L01Exception 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
@ -369,7 +368,8 @@ public class LocalFilesDSProcessor implements DataSourceProcessor, AutoIngestDat
@Override
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
*/
@Override
public CorrelationCase newCase(CorrelationCase eamCase) throws EamDbException {
Connection conn = connect();
public synchronized CorrelationCase newCase(CorrelationCase eamCase) throws EamDbException {
// 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;
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("");
htmlbodyTextPane.setText("");
textbodyTextArea.setText("");
drp.setNode(null);
showImagesToggleButton.setEnabled(false);
msgbodyTabbedPane.setEnabled(false);
}

View File

@ -24,7 +24,7 @@ DataContentViewerString.pageLabel2.text=Page
# 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>
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_HELP=http://sleuthkit.org/autopsy/docs/user-docs/4.6.0/
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());
/**
* Construct a panel to allow a user to make ingest job settings.
* This constructor assumes there is no ingest history.
* Construct a panel to allow a user to make ingest job settings. This
* constructor assumes there is no ingest history.
*
* @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.
* This constructor enables tracking of ingest job history.
* Construct a panel to allow a user to make ingest job settings. This
* constructor enables tracking of ingest job history.
*
* @param settings The initial settings for the ingest job.
* @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) {
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
if (!oldFilterList.contains(filter.getName())) {
//set newly created filter to selected filter
settings.setFileFilter(filter);
filterToSelect = filter.getName();
break;
}
}
fileIngestFilterComboBox.setModel(new DefaultComboBoxModel<>(getComboBoxContents()));
//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();
}
);
@ -440,21 +444,25 @@ public final class IngestJobSettingsPanel extends javax.swing.JPanel {
//return to saved selection in case they cancel out of filter creation
fileIngestFilterComboBox.setSelectedItem(settings.getFileFilter().getName());
} else if (evt.getActionCommand().equals("comboBoxChanged")) {
try {
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
}
updateSelectedFilter(fileIngestFilterComboBox.getSelectedItem().toString());
}
}//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
* 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.interestingitems.FilesSet;
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.ParentPathCondition;
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
if (file.getParentPath().equalsIgnoreCase("/dir1/")) {
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());
assertTrue(errMsg, !(file.getMIMEType() == null || file.getMIMEType().isEmpty()));
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());
}
} 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());
@ -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) {
FileTypeIdModuleFactory factory = new FileTypeIdModuleFactory();
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);
try {
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());
} catch (InterruptedException ex) {
Exceptions.printStackTrace(ex);

View File

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

View File

@ -1,15 +1,15 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 Basis Technology Corp.
*
* Copyright 2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -37,11 +37,13 @@ import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PathValidator;
final class MemoryDSInputPanel extends JPanel implements DocumentListener {
private static final long serialVersionUID = 1L; //default
private final String PROP_LASTINPUT_PATH = "LBL_LastInputFile_PATH";
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 Map<String, Boolean> pluginListStates = new HashMap<>(); // is set by listeners when users select and deselect items
private final Boolean isEnabled = true;
/**
* Creates new MemoryDSInputPanel panel for user input
* Creates new MemoryDSInputPanel panel for user input
*/
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);
initComponents();
errorLabel.setVisible(false);
@ -91,7 +93,7 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
private void postInit() {
pathTextField.getDocument().addDocumentListener(this);
}
private void customizePluginListTable() {
PluginList.setModel(tableModel);
PluginList.setTableHeader(null);
@ -135,14 +137,14 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
// set the selected timezone
timeZoneComboBox.setSelectedItem(formatted);
}
private void createVolatilityVersionList() {
volExecutableComboBox.addItem("2.6");
volExecutableComboBox.addItem("2.5");
}
private void createPluginList() {
PluginListNames.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
boolean allEnabled = !ModuleSettings.configExists(this.contextName);
Map<String, String> pluginMap = ModuleSettings.getConfigSettings(this.contextName);
for (String plugin : pluginList) {
PluginListNames.add(plugin);
if (allEnabled)
if (allEnabled) {
pluginListStates.put(plugin, true);
else
} else {
pluginListStates.put(plugin, pluginMap.containsKey(plugin));
}
}
tableModel.fireTableDataChanged();
//this.tableModel = pluginsToRun.getModel();
}
/**
* 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
@ -282,18 +284,18 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
}// </editor-fold>//GEN-END:initComponents
@SuppressWarnings("deprecation")
private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed
String oldText = pathTextField.getText();
// set the current directory of the FileChooser if the ImagePath Field is valid
File currentDir = new File(oldText);
if (currentDir.exists()) {
fc.setCurrentDirectory(currentDir);
}
String oldText = pathTextField.getText();
// set the current directory of the FileChooser if the ImagePath Field is valid
File currentDir = new File(oldText);
if (currentDir.exists()) {
fc.setCurrentDirectory(currentDir);
}
int retval = fc.showOpenDialog(this);
if (retval == JFileChooser.APPROVE_OPTION) {
String path = fc.getSelectedFile().getPath();
pathTextField.setText(path);
}
int retval = fc.showOpenDialog(this);
if (retval == JFileChooser.APPROVE_OPTION) {
String path = fc.getSelectedFile().getPath();
pathTextField.setText(path);
}
}//GEN-LAST:event_browseButtonActionPerformed
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() {
return pathTextField.getText();
}
List<String> getPluginsToRun() {
List<String> enabledPlugins = new ArrayList<>();
Map<String, String> pluginMap = new HashMap<>();
@ -332,7 +334,7 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
pluginMap.put(plugin, "");
}
}
ModuleSettings.setConfigSettings(this.contextName, pluginMap);
// @@ Could return keys of set
return enabledPlugins;
@ -374,11 +376,19 @@ final class MemoryDSInputPanel extends JPanel implements DocumentListener {
*
* @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) {
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.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
*
* Copyright 2011-2016 Basis Technology Corp.
* Copyright 2018 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* 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;
/**
* A MEmory data source processor that implements the DataSourceProcessor service
* provider interface to allow integration with the add data source wizard. It
* also provides a run method overload to allow it to be used independently of
* the wizard.
* A memory image data source processor that implements the DataSourceProcessor
* service provider interface to allow integration with the Add Data Source
* wizard. It also provides a run method overload to allow it to be used
* independently of the wizard.
*/
@ServiceProvider(service = DataSourceProcessor.class)
public class MemoryDSProcessor implements DataSourceProcessor {
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
* 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.
*/
public MemoryDSProcessor() {
@ -117,37 +117,40 @@ public class MemoryDSProcessor implements DataSourceProcessor {
@Override
public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
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
* a separate thread and the given settings instead of those provided by the
* selection and configuration panel. Returns as soon as the background task
* is started and uses the callback object to signal task completion and
* return results.
* Adds a memory image data source to the case database using a background
* task in a separate thread and the given settings instead of those
* provided by the selection and configuration panel. Returns as soon as the
* background task is started and uses the callback object to signal task
* completion and return results.
*
* @param deviceId An ASCII-printable identifier for the device
* associated with the data source that is
* intended to be unique across multiple cases
* (e.g., a UUID).
* @param imageFilePath Path to the image file.
* @param timeZone The time zone to use when processing dates
* and times for the image, obtained from
* java.util.TimeZone.getID.
* @param chunkSize The maximum size of each chunk of the raw
* data source as it is divided up into virtual
* unallocated space files.
* @param progressMonitor Progress monitor for reporting progress
* during processing.
* @param callback Callback to call when processing is done.
* @param deviceId An ASCII-printable identifier for the device
* associated with the data source that is intended
* to be unique across multiple cases (e.g., a UUID).
* @param memoryImagePath Path to the memory image file.
* @param pluginsToRun The Volatility plugins to run.
* @param timeZone The time zone to use when processing dates and
* times for the image, obtained from
* java.util.TimeZone.getID.
* @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) {
addImageTask = new AddMemoryImageTask(deviceId, imageFilePath, pluginsToRun, timeZone, 0, progressMonitor, callback);
private void run(String deviceId, String memoryImagePath, List<String> pluginsToRun, String timeZone, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
addImageTask = new AddMemoryImageTask(deviceId, memoryImagePath, pluginsToRun, timeZone, progressMonitor, callback);
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
public void cancel() {
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) {
BlackboardAttribute.Type type = new BlackboardAttribute.Type(attrType);
attributeMap.computeIfAbsent(type, t -> {
if( ! attributeMap.containsKey(type)) {
String value = matcher.group(groupName);
if (attrType.equals(ATTRIBUTE_TYPE.TSK_CARD_NUMBER)) {
attributeMap.put(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_KEYWORD),
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD, MODULE_NAME, value));
value = CharMatcher.anyOf(" -").removeFrom(value);
}
if (StringUtils.isNotBlank(value)) {
return new BlackboardAttribute(attrType, MODULE_NAME, value);
} else {
return null;
attributeMap.put(type, new BlackboardAttribute(attrType, MODULE_NAME, value));
}
});
}
}
}