Merge branch 'develop' of https://github.com/sleuthkit/autopsy into substring_search_2384
@ -18,17 +18,23 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.actions;
|
package org.sleuthkit.autopsy.actions;
|
||||||
|
|
||||||
|
import java.awt.Cursor;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
import javax.swing.SwingWorker;
|
||||||
import org.openide.LifecycleManager;
|
import org.openide.LifecycleManager;
|
||||||
import org.openide.awt.ActionID;
|
import org.openide.awt.ActionID;
|
||||||
import org.openide.awt.ActionReference;
|
import org.openide.awt.ActionReference;
|
||||||
import org.openide.awt.ActionRegistration;
|
import org.openide.awt.ActionRegistration;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
|
import org.openide.windows.WindowManager;
|
||||||
import org.sleuthkit.autopsy.casemodule.Case;
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.casemodule.CaseActionException;
|
import org.sleuthkit.autopsy.casemodule.CaseActionException;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.StartupWindowProvider;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
|
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The action associated with the Case/Exit menu item. It closes the current
|
* The action associated with the Case/Exit menu item. It closes the current
|
||||||
@ -39,23 +45,40 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
|||||||
@ActionID(id = "org.sleuthkit.autopsy.casemodule.ExitAction", category = "Case")
|
@ActionID(id = "org.sleuthkit.autopsy.casemodule.ExitAction", category = "Case")
|
||||||
final public class ExitAction implements ActionListener {
|
final public class ExitAction implements ActionListener {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(ExitAction.class.getName());
|
||||||
|
|
||||||
@NbBundle.Messages({
|
@NbBundle.Messages({
|
||||||
"ExitAction.confirmationDialog.title=Ingest is Running",
|
"ExitAction.confirmationDialog.title=Ingest is Running",
|
||||||
"ExitAction.confirmationDialog.message=Ingest is running, are you sure you want to exit?"
|
"ExitAction.confirmationDialog.message=Ingest is running, are you sure you want to exit?",
|
||||||
|
"# {0} - exception message", "ExitAction.messageBox.caseCloseExceptionMessage=Error closing case: {0}"
|
||||||
})
|
})
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (IngestRunningCheck.checkAndConfirmProceed(Bundle.ExitAction_confirmationDialog_title(), Bundle.ExitAction_confirmationDialog_message())) {
|
if (IngestRunningCheck.checkAndConfirmProceed(Bundle.ExitAction_confirmationDialog_title(), Bundle.ExitAction_confirmationDialog_message())) {
|
||||||
new Thread(() -> {
|
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||||
try {
|
new SwingWorker<Void, Void>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground() throws Exception {
|
||||||
Case.closeCurrentCase();
|
Case.closeCurrentCase();
|
||||||
} catch (CaseActionException ex) {
|
return null;
|
||||||
Logger.getLogger(ExitAction.class.getName()).log(Level.SEVERE, "Error closing the current case on exit", ex); //NON-NLS
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void done() {
|
||||||
|
try {
|
||||||
|
get();
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Unexpected interrupt closing the current case", ex);
|
||||||
|
} catch (ExecutionException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Error closing the current case", ex);
|
||||||
|
MessageNotifyUtil.Message.error(Bundle.ExitAction_messageBox_caseCloseExceptionMessage(ex.getMessage()));
|
||||||
} finally {
|
} finally {
|
||||||
|
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||||
LifecycleManager.getDefault().exit();
|
LifecycleManager.getDefault().exit();
|
||||||
}
|
}
|
||||||
}).start();
|
}
|
||||||
|
}.execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ 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.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.imagewriter.ImageWriterService;
|
import org.sleuthkit.autopsy.imagewriter.ImageWriterService;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
import org.sleuthkit.autopsy.imagewriter.ImageWriterSettings;
|
||||||
import org.sleuthkit.datamodel.Content;
|
import org.sleuthkit.datamodel.Content;
|
||||||
import org.sleuthkit.datamodel.Image;
|
import org.sleuthkit.datamodel.Image;
|
||||||
import org.sleuthkit.datamodel.SleuthkitJNI;
|
import org.sleuthkit.datamodel.SleuthkitJNI;
|
||||||
@ -43,7 +43,7 @@ class AddImageTask implements Runnable {
|
|||||||
private final String deviceId;
|
private final String deviceId;
|
||||||
private final String imagePath;
|
private final String imagePath;
|
||||||
private final String timeZone;
|
private final String timeZone;
|
||||||
private final String imageWriterPath;
|
private final ImageWriterSettings imageWriterSettings;
|
||||||
private final boolean ignoreFatOrphanFiles;
|
private final boolean ignoreFatOrphanFiles;
|
||||||
private final DataSourceProcessorProgressMonitor progressMonitor;
|
private final DataSourceProcessorProgressMonitor progressMonitor;
|
||||||
private final DataSourceProcessorCallback callback;
|
private final DataSourceProcessorCallback callback;
|
||||||
@ -83,13 +83,13 @@ class AddImageTask implements Runnable {
|
|||||||
* processing.
|
* processing.
|
||||||
* @param callback Callback to call when processing is done.
|
* @param callback Callback to call when processing is done.
|
||||||
*/
|
*/
|
||||||
AddImageTask(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, String imageWriterPath,
|
AddImageTask(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, ImageWriterSettings imageWriterSettings,
|
||||||
DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||||
this.deviceId = deviceId;
|
this.deviceId = deviceId;
|
||||||
this.imagePath = imagePath;
|
this.imagePath = imagePath;
|
||||||
this.timeZone = timeZone;
|
this.timeZone = timeZone;
|
||||||
this.ignoreFatOrphanFiles = ignoreFatOrphanFiles;
|
this.ignoreFatOrphanFiles = ignoreFatOrphanFiles;
|
||||||
this.imageWriterPath = imageWriterPath;
|
this.imageWriterSettings = imageWriterSettings;
|
||||||
this.callback = callback;
|
this.callback = callback;
|
||||||
this.progressMonitor = progressMonitor;
|
this.progressMonitor = progressMonitor;
|
||||||
tskAddImageProcessLock = new Object();
|
tskAddImageProcessLock = new Object();
|
||||||
@ -103,12 +103,17 @@ class AddImageTask implements Runnable {
|
|||||||
progressMonitor.setIndeterminate(true);
|
progressMonitor.setIndeterminate(true);
|
||||||
progressMonitor.setProgress(0);
|
progressMonitor.setProgress(0);
|
||||||
Case currentCase = Case.getCurrentCase();
|
Case currentCase = Case.getCurrentCase();
|
||||||
|
String imageWriterPath = "";
|
||||||
|
if(imageWriterSettings != null){
|
||||||
|
imageWriterPath = imageWriterSettings.getPath();
|
||||||
|
}
|
||||||
List<String> errorMessages = new ArrayList<>();
|
List<String> errorMessages = new ArrayList<>();
|
||||||
List<Content> newDataSources = new ArrayList<>();
|
List<Content> newDataSources = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
currentCase.getSleuthkitCase().acquireExclusiveLock();
|
currentCase.getSleuthkitCase().acquireExclusiveLock();
|
||||||
synchronized (tskAddImageProcessLock) {
|
synchronized (tskAddImageProcessLock) {
|
||||||
tskAddImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, true, ignoreFatOrphanFiles, imageWriterPath);
|
tskAddImageProcess = currentCase.getSleuthkitCase().makeAddImageProcess(timeZone, true,
|
||||||
|
ignoreFatOrphanFiles, imageWriterPath);
|
||||||
}
|
}
|
||||||
Thread progressUpdateThread = new Thread(new ProgressUpdater(progressMonitor, tskAddImageProcess));
|
Thread progressUpdateThread = new Thread(new ProgressUpdater(progressMonitor, tskAddImageProcess));
|
||||||
progressUpdateThread.start();
|
progressUpdateThread.start();
|
||||||
@ -208,8 +213,8 @@ class AddImageTask implements Runnable {
|
|||||||
if (!verificationError.isEmpty()) {
|
if (!verificationError.isEmpty()) {
|
||||||
errorMessages.add(verificationError);
|
errorMessages.add(verificationError);
|
||||||
}
|
}
|
||||||
if(! imageWriterPath.isEmpty()){
|
if(imageWriterSettings != null){
|
||||||
ImageWriterService.createImageWriter(imageId);
|
ImageWriterService.createImageWriter(imageId, imageWriterSettings);
|
||||||
}
|
}
|
||||||
newDataSources.add(newImage);
|
newDataSources.add(newImage);
|
||||||
} else {
|
} else {
|
||||||
|
@ -241,3 +241,4 @@ CasePropertiesPanel.lbDbType.text=Case Type:
|
|||||||
CasePropertiesPanel.examinerLabel.text=Examiner:
|
CasePropertiesPanel.examinerLabel.text=Examiner:
|
||||||
CasePropertiesPanel.caseNumberLabel.text=Case Number:
|
CasePropertiesPanel.caseNumberLabel.text=Case Number:
|
||||||
CasePropertiesPanel.deleteCaseButton.text=Delete Case
|
CasePropertiesPanel.deleteCaseButton.text=Delete Case
|
||||||
|
LocalDiskPanel.changeDatabasePathCheckbox.text=Change image path in the case to the VHD upon completion
|
||||||
|
@ -185,7 +185,7 @@ public class ImageDSProcessor implements DataSourceProcessor, AutoIngestDataSour
|
|||||||
* @param callback Callback to call when processing is done.
|
* @param callback Callback to call when processing is done.
|
||||||
*/
|
*/
|
||||||
public void run(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
public void run(String deviceId, String imagePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||||
addImageTask = new AddImageTask(deviceId, imagePath, timeZone, ignoreFatOrphanFiles, "", progressMonitor, callback);
|
addImageTask = new AddImageTask(deviceId, imagePath, timeZone, ignoreFatOrphanFiles, null, progressMonitor, callback);
|
||||||
new Thread(addImageTask).start();
|
new Thread(addImageTask).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback
|
|||||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
|
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
|
||||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||||
import org.sleuthkit.autopsy.coreutils.DriveUtils;
|
import org.sleuthkit.autopsy.coreutils.DriveUtils;
|
||||||
|
import org.sleuthkit.autopsy.imagewriter.ImageWriterSettings;
|
||||||
import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor;
|
import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,6 +56,7 @@ public class LocalDiskDSProcessor implements DataSourceProcessor, AutoIngestData
|
|||||||
private String drivePath;
|
private String drivePath;
|
||||||
private String timeZone;
|
private String timeZone;
|
||||||
private String imageWriterPath = "";
|
private String imageWriterPath = "";
|
||||||
|
private ImageWriterSettings imageWriterSettings = null;
|
||||||
private boolean ignoreFatOrphanFiles;
|
private boolean ignoreFatOrphanFiles;
|
||||||
private boolean setDataSourceOptionsCalled;
|
private boolean setDataSourceOptionsCalled;
|
||||||
|
|
||||||
@ -139,10 +141,10 @@ public class LocalDiskDSProcessor implements DataSourceProcessor, AutoIngestData
|
|||||||
timeZone = configPanel.getTimeZone();
|
timeZone = configPanel.getTimeZone();
|
||||||
ignoreFatOrphanFiles = configPanel.getNoFatOrphans();
|
ignoreFatOrphanFiles = configPanel.getNoFatOrphans();
|
||||||
if (configPanel.getImageWriterEnabled()) {
|
if (configPanel.getImageWriterEnabled()) {
|
||||||
imageWriterPath = configPanel.getImageWriterPath();
|
imageWriterSettings = configPanel.getImageWriterSettings();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addDiskTask = new AddImageTask(deviceId, drivePath, timeZone, ignoreFatOrphanFiles, imageWriterPath, progressMonitor, callback);
|
addDiskTask = new AddImageTask(deviceId, drivePath, timeZone, ignoreFatOrphanFiles, imageWriterSettings, progressMonitor, callback);
|
||||||
new Thread(addDiskTask).start();
|
new Thread(addDiskTask).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +170,7 @@ public class LocalDiskDSProcessor implements DataSourceProcessor, AutoIngestData
|
|||||||
* @param callback Callback to call when processing is done.
|
* @param callback Callback to call when processing is done.
|
||||||
*/
|
*/
|
||||||
public void run(String deviceId, String drivePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
public void run(String deviceId, String drivePath, String timeZone, boolean ignoreFatOrphanFiles, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
|
||||||
addDiskTask = new AddImageTask(deviceId, drivePath, timeZone, ignoreFatOrphanFiles, imageWriterPath, progressMonitor, callback);
|
addDiskTask = new AddImageTask(deviceId, drivePath, timeZone, ignoreFatOrphanFiles, imageWriterSettings, progressMonitor, callback);
|
||||||
new Thread(addDiskTask).start();
|
new Thread(addDiskTask).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,14 +45,18 @@
|
|||||||
<Group type="102" alignment="0" attributes="0">
|
<Group type="102" alignment="0" attributes="0">
|
||||||
<EmptySpace min="21" pref="21" max="-2" attributes="0"/>
|
<EmptySpace min="21" pref="21" max="-2" attributes="0"/>
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
<Component id="imageWriterErrorLabel" min="-2" max="-2" attributes="0"/>
|
|
||||||
<Group type="103" groupAlignment="0" attributes="0">
|
|
||||||
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
|
|
||||||
<Group type="102" attributes="0">
|
<Group type="102" attributes="0">
|
||||||
<Component id="pathTextField" min="-2" pref="342" max="-2" attributes="0"/>
|
<Component id="pathTextField" min="-2" pref="342" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="browseButton" pref="0" max="32767" attributes="0"/>
|
<Component id="browseButton" pref="0" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
|
<Group type="102" attributes="0">
|
||||||
|
<Group type="103" groupAlignment="0" attributes="0">
|
||||||
|
<Component id="imageWriterErrorLabel" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
|
||||||
|
<Component id="changeDatabasePathCheckbox" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||||
|
</Group>
|
||||||
|
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
@ -87,11 +91,13 @@
|
|||||||
<Component id="browseButton" min="-2" max="-2" attributes="0"/>
|
<Component id="browseButton" min="-2" max="-2" attributes="0"/>
|
||||||
<Component id="pathTextField" min="-2" pref="23" max="-2" attributes="0"/>
|
<Component id="pathTextField" min="-2" pref="23" max="-2" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
|
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||||
|
<Component id="changeDatabasePathCheckbox" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
|
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="-2" attributes="0"/>
|
<EmptySpace max="-2" attributes="0"/>
|
||||||
<Component id="imageWriterErrorLabel" min="-2" max="-2" attributes="0"/>
|
<Component id="imageWriterErrorLabel" min="-2" max="-2" attributes="0"/>
|
||||||
<EmptySpace max="32767" attributes="0"/>
|
<EmptySpace pref="66" max="32767" attributes="0"/>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
</DimensionLayout>
|
</DimensionLayout>
|
||||||
@ -247,5 +253,12 @@
|
|||||||
</Property>
|
</Property>
|
||||||
</Properties>
|
</Properties>
|
||||||
</Component>
|
</Component>
|
||||||
|
<Component class="javax.swing.JCheckBox" name="changeDatabasePathCheckbox">
|
||||||
|
<Properties>
|
||||||
|
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||||
|
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LocalDiskPanel.changeDatabasePathCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||||
|
</Property>
|
||||||
|
</Properties>
|
||||||
|
</Component>
|
||||||
</SubComponents>
|
</SubComponents>
|
||||||
</Form>
|
</Form>
|
||||||
|
@ -40,6 +40,7 @@ import org.sleuthkit.autopsy.coreutils.LocalDisk;
|
|||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||||
|
import org.sleuthkit.autopsy.imagewriter.ImageWriterSettings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ImageTypePanel for adding a local disk or partition such as PhysicalDrive0 or
|
* ImageTypePanel for adding a local disk or partition such as PhysicalDrive0 or
|
||||||
@ -114,6 +115,7 @@ final class LocalDiskPanel extends JPanel {
|
|||||||
imageWriterErrorLabel.setText("");
|
imageWriterErrorLabel.setText("");
|
||||||
pathTextField.setEnabled(copyImageCheckbox.isSelected());
|
pathTextField.setEnabled(copyImageCheckbox.isSelected());
|
||||||
browseButton.setEnabled(copyImageCheckbox.isSelected());
|
browseButton.setEnabled(copyImageCheckbox.isSelected());
|
||||||
|
changeDatabasePathCheckbox.setEnabled(copyImageCheckbox.isSelected());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -138,6 +140,7 @@ final class LocalDiskPanel extends JPanel {
|
|||||||
browseButton = new javax.swing.JButton();
|
browseButton = new javax.swing.JButton();
|
||||||
jLabel1 = new javax.swing.JLabel();
|
jLabel1 = new javax.swing.JLabel();
|
||||||
imageWriterErrorLabel = new javax.swing.JLabel();
|
imageWriterErrorLabel = new javax.swing.JLabel();
|
||||||
|
changeDatabasePathCheckbox = new javax.swing.JCheckBox();
|
||||||
|
|
||||||
setMinimumSize(new java.awt.Dimension(0, 420));
|
setMinimumSize(new java.awt.Dimension(0, 420));
|
||||||
setPreferredSize(new java.awt.Dimension(485, 410));
|
setPreferredSize(new java.awt.Dimension(485, 410));
|
||||||
@ -193,6 +196,8 @@ final class LocalDiskPanel extends JPanel {
|
|||||||
imageWriterErrorLabel.setForeground(new java.awt.Color(255, 0, 0));
|
imageWriterErrorLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||||
org.openide.awt.Mnemonics.setLocalizedText(imageWriterErrorLabel, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.imageWriterErrorLabel.text")); // NOI18N
|
org.openide.awt.Mnemonics.setLocalizedText(imageWriterErrorLabel, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.imageWriterErrorLabel.text")); // NOI18N
|
||||||
|
|
||||||
|
org.openide.awt.Mnemonics.setLocalizedText(changeDatabasePathCheckbox, org.openide.util.NbBundle.getMessage(LocalDiskPanel.class, "LocalDiskPanel.changeDatabasePathCheckbox.text")); // NOI18N
|
||||||
|
|
||||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||||
this.setLayout(layout);
|
this.setLayout(layout);
|
||||||
layout.setHorizontalGroup(
|
layout.setHorizontalGroup(
|
||||||
@ -216,13 +221,16 @@ final class LocalDiskPanel extends JPanel {
|
|||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addGap(21, 21, 21)
|
.addGap(21, 21, 21)
|
||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
.addComponent(imageWriterErrorLabel)
|
|
||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
|
||||||
.addComponent(jLabel1)
|
|
||||||
.addGroup(layout.createSequentialGroup()
|
.addGroup(layout.createSequentialGroup()
|
||||||
.addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 342, javax.swing.GroupLayout.PREFERRED_SIZE)
|
.addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 342, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(browseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))))))))
|
.addComponent(browseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))
|
||||||
|
.addGroup(layout.createSequentialGroup()
|
||||||
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||||
|
.addComponent(imageWriterErrorLabel)
|
||||||
|
.addComponent(jLabel1)
|
||||||
|
.addComponent(changeDatabasePathCheckbox))
|
||||||
|
.addGap(0, 0, Short.MAX_VALUE)))))))
|
||||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||||
);
|
);
|
||||||
layout.setVerticalGroup(
|
layout.setVerticalGroup(
|
||||||
@ -247,17 +255,20 @@ final class LocalDiskPanel extends JPanel {
|
|||||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||||
.addComponent(browseButton)
|
.addComponent(browseButton)
|
||||||
.addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
|
.addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||||
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||||
|
.addComponent(changeDatabasePathCheckbox)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(jLabel1)
|
.addComponent(jLabel1)
|
||||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||||
.addComponent(imageWriterErrorLabel)
|
.addComponent(imageWriterErrorLabel)
|
||||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
.addContainerGap(66, Short.MAX_VALUE))
|
||||||
);
|
);
|
||||||
}// </editor-fold>//GEN-END:initComponents
|
}// </editor-fold>//GEN-END:initComponents
|
||||||
|
|
||||||
private void copyImageCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_copyImageCheckboxActionPerformed
|
private void copyImageCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_copyImageCheckboxActionPerformed
|
||||||
pathTextField.setEnabled(copyImageCheckbox.isSelected());
|
pathTextField.setEnabled(copyImageCheckbox.isSelected());
|
||||||
browseButton.setEnabled(copyImageCheckbox.isSelected());
|
browseButton.setEnabled(copyImageCheckbox.isSelected());
|
||||||
|
changeDatabasePathCheckbox.setEnabled(copyImageCheckbox.isSelected());
|
||||||
fireUpdateEvent();
|
fireUpdateEvent();
|
||||||
}//GEN-LAST:event_copyImageCheckboxActionPerformed
|
}//GEN-LAST:event_copyImageCheckboxActionPerformed
|
||||||
|
|
||||||
@ -283,6 +294,7 @@ final class LocalDiskPanel extends JPanel {
|
|||||||
|
|
||||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||||
private javax.swing.JButton browseButton;
|
private javax.swing.JButton browseButton;
|
||||||
|
private javax.swing.JCheckBox changeDatabasePathCheckbox;
|
||||||
private javax.swing.JCheckBox copyImageCheckbox;
|
private javax.swing.JCheckBox copyImageCheckbox;
|
||||||
private javax.swing.JLabel descLabel;
|
private javax.swing.JLabel descLabel;
|
||||||
private javax.swing.JLabel diskLabel;
|
private javax.swing.JLabel diskLabel;
|
||||||
@ -397,8 +409,8 @@ final class LocalDiskPanel extends JPanel {
|
|||||||
return copyImageCheckbox.isSelected();
|
return copyImageCheckbox.isSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
String getImageWriterPath() {
|
ImageWriterSettings getImageWriterSettings() {
|
||||||
return pathTextField.getText();
|
return new ImageWriterSettings(pathTextField.getText(), changeDatabasePathCheckbox.isSelected());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Autopsy Forensic Browser
|
* Autopsy Forensic Browser
|
||||||
*
|
*
|
||||||
* Copyright 2011-2014 Basis Technology Corp.
|
* Copyright 2011-2017 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");
|
||||||
@ -18,16 +18,24 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.core;
|
package org.sleuthkit.autopsy.core;
|
||||||
|
|
||||||
|
import java.awt.Cursor;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.FutureTask;
|
||||||
import java.util.logging.Handler;
|
import java.util.logging.Handler;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import javafx.application.Platform;
|
import javafx.application.Platform;
|
||||||
import javafx.embed.swing.JFXPanel;
|
import javafx.embed.swing.JFXPanel;
|
||||||
|
import javax.swing.SwingWorker;
|
||||||
|
import org.openide.LifecycleManager;
|
||||||
import org.openide.modules.ModuleInstall;
|
import org.openide.modules.ModuleInstall;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.windows.WindowManager;
|
import org.openide.windows.WindowManager;
|
||||||
|
import org.sleuthkit.autopsy.actions.IngestRunningCheck;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||||
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
||||||
@ -38,6 +46,8 @@ import org.sleuthkit.autopsy.coreutils.PlatformUtil;
|
|||||||
*/
|
*/
|
||||||
public class Installer extends ModuleInstall {
|
public class Installer extends ModuleInstall {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
private final List<ModuleInstall> packageInstallers;
|
private final List<ModuleInstall> packageInstallers;
|
||||||
private static final Logger logger = Logger.getLogger(Installer.class.getName());
|
private static final Logger logger = Logger.getLogger(Installer.class.getName());
|
||||||
private static volatile boolean javaFxInit = false;
|
private static volatile boolean javaFxInit = false;
|
||||||
@ -142,7 +152,9 @@ public class Installer extends ModuleInstall {
|
|||||||
logger.log(Level.SEVERE, "Error loading VHDI library, ", e); //NON-NLS
|
logger.log(Level.SEVERE, "Error loading VHDI library, ", e); //NON-NLS
|
||||||
}
|
}
|
||||||
|
|
||||||
/* PostgreSQL */
|
/*
|
||||||
|
* PostgreSQL
|
||||||
|
*/
|
||||||
try {
|
try {
|
||||||
System.loadLibrary("msvcr120"); //NON-NLS
|
System.loadLibrary("msvcr120"); //NON-NLS
|
||||||
logger.log(Level.INFO, "MSVCR 120 library loaded"); //NON-NLS
|
logger.log(Level.INFO, "MSVCR 120 library loaded"); //NON-NLS
|
||||||
@ -217,7 +229,7 @@ public class Installer extends ModuleInstall {
|
|||||||
System.setProperty("javafx.macosx.embedded", "true");
|
System.setProperty("javafx.macosx.embedded", "true");
|
||||||
try {
|
try {
|
||||||
// Creating a JFXPanel initializes JavaFX
|
// Creating a JFXPanel initializes JavaFX
|
||||||
new JFXPanel();
|
JFXPanel panel = new JFXPanel();
|
||||||
Platform.setImplicitExit(false);
|
Platform.setImplicitExit(false);
|
||||||
javaFxInit = true;
|
javaFxInit = true;
|
||||||
} catch (UnsatisfiedLinkError | NoClassDefFoundError | Exception e) {
|
} catch (UnsatisfiedLinkError | NoClassDefFoundError | Exception e) {
|
||||||
@ -267,7 +279,7 @@ public class Installer extends ModuleInstall {
|
|||||||
logger.log(Level.INFO, "{0} validate()", mi.getClass().getName()); //NON-NLS
|
logger.log(Level.INFO, "{0} validate()", mi.getClass().getName()); //NON-NLS
|
||||||
try {
|
try {
|
||||||
mi.validate();
|
mi.validate();
|
||||||
} catch (Exception e) {
|
} catch (IllegalStateException e) {
|
||||||
logger.log(Level.WARNING, "", e);
|
logger.log(Level.WARNING, "", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -289,6 +301,40 @@ public class Installer extends ModuleInstall {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NbBundle.Messages({
|
||||||
|
"Installer.closing.confirmationDialog.title=Ingest is Running",
|
||||||
|
"Installer.closing.confirmationDialog.message=Ingest is running, are you sure you want to exit?",
|
||||||
|
"# {0} - exception message", "Installer.closing.messageBox.caseCloseExceptionMessage=Error closing case: {0}"
|
||||||
|
})
|
||||||
|
@Override
|
||||||
|
public boolean closing() {
|
||||||
|
if (IngestRunningCheck.checkAndConfirmProceed(Bundle.Installer_closing_confirmationDialog_title(), Bundle.Installer_closing_confirmationDialog_message())) {
|
||||||
|
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||||
|
FutureTask<Void> future = new FutureTask<>(new Callable<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void call() throws Exception {
|
||||||
|
Case.closeCurrentCase();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Thread thread = new Thread(future);
|
||||||
|
thread.start();
|
||||||
|
try {
|
||||||
|
future.get();
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Unexpected interrupt closing the current case", ex);
|
||||||
|
} catch (ExecutionException ex) {
|
||||||
|
logger.log(Level.SEVERE, "Error closing the current case", ex);
|
||||||
|
MessageNotifyUtil.Message.error(Bundle.Installer_closing_messageBox_caseCloseExceptionMessage(ex.getMessage()));
|
||||||
|
} finally {
|
||||||
|
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
super.close();
|
super.close();
|
||||||
|
@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.imagewriter;
|
|||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
@ -33,6 +34,7 @@ import org.sleuthkit.autopsy.casemodule.Case;
|
|||||||
import org.sleuthkit.autopsy.core.RuntimeProperties;
|
import org.sleuthkit.autopsy.core.RuntimeProperties;
|
||||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||||
import org.sleuthkit.datamodel.Image;
|
import org.sleuthkit.datamodel.Image;
|
||||||
|
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||||
import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent;
|
import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent;
|
||||||
import org.sleuthkit.datamodel.SleuthkitJNI;
|
import org.sleuthkit.datamodel.SleuthkitJNI;
|
||||||
@ -50,9 +52,10 @@ class ImageWriter implements PropertyChangeListener{
|
|||||||
private final Logger logger = Logger.getLogger(ImageWriter.class.getName());
|
private final Logger logger = Logger.getLogger(ImageWriter.class.getName());
|
||||||
|
|
||||||
private final Long dataSourceId;
|
private final Long dataSourceId;
|
||||||
|
private final ImageWriterSettings settings;
|
||||||
|
|
||||||
private Long imageHandle = null;
|
private Long imageHandle = null;
|
||||||
private Future<?> finishTask = null;
|
private Future<Integer> finishTask = null;
|
||||||
private ProgressHandle progressHandle = null;
|
private ProgressHandle progressHandle = null;
|
||||||
private ScheduledFuture<?> progressUpdateTask = null;
|
private ScheduledFuture<?> progressUpdateTask = null;
|
||||||
private boolean isCancelled = false;
|
private boolean isCancelled = false;
|
||||||
@ -62,15 +65,27 @@ class ImageWriter implements PropertyChangeListener{
|
|||||||
|
|
||||||
private ScheduledThreadPoolExecutor periodicTasksExecutor = null;
|
private ScheduledThreadPoolExecutor periodicTasksExecutor = null;
|
||||||
private final boolean doUI;
|
private final boolean doUI;
|
||||||
|
private SleuthkitCase caseDb = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the Image Writer object.
|
* Create the Image Writer object.
|
||||||
* After creation, startListeners() should be called.
|
* After creation, startListeners() should be called.
|
||||||
* @param dataSourceId
|
* @param dataSourceId
|
||||||
*/
|
*/
|
||||||
ImageWriter(Long dataSourceId){
|
ImageWriter(Long dataSourceId, ImageWriterSettings settings){
|
||||||
this.dataSourceId = dataSourceId;
|
this.dataSourceId = dataSourceId;
|
||||||
|
this.settings = settings;
|
||||||
doUI = RuntimeProperties.runningWithGUI();
|
doUI = RuntimeProperties.runningWithGUI();
|
||||||
|
|
||||||
|
// We save the reference to the sleuthkit case here in case getCurrentCase() is set to
|
||||||
|
// null before Image Writer finishes. The user can still elect to wait for image writer
|
||||||
|
// (in ImageWriterService.closeCaseResources) even though the case is closing.
|
||||||
|
try{
|
||||||
|
caseDb = Case.getCurrentCase().getSleuthkitCase();
|
||||||
|
} catch (IllegalStateException ex){
|
||||||
|
logger.log(Level.SEVERE, "Unable to load case. Image writer will be cancelled.");
|
||||||
|
this.isCancelled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -160,11 +175,23 @@ class ImageWriter implements PropertyChangeListener{
|
|||||||
// The added complexity here with the Future is because we absolutely need to make sure
|
// The added complexity here with the Future is because we absolutely need to make sure
|
||||||
// the call to finishImageWriter returns before allowing the TSK data structures to be freed
|
// the call to finishImageWriter returns before allowing the TSK data structures to be freed
|
||||||
// during case close.
|
// during case close.
|
||||||
finishTask = Executors.newSingleThreadExecutor().submit(() -> {
|
finishTask = Executors.newSingleThreadExecutor().submit(new Callable<Integer>(){
|
||||||
|
@Override
|
||||||
|
public Integer call() throws TskCoreException{
|
||||||
try{
|
try{
|
||||||
SleuthkitJNI.finishImageWriter(imageHandle);
|
int result = SleuthkitJNI.finishImageWriter(imageHandle);
|
||||||
|
|
||||||
|
// We've decided to always update the path to the VHD, even if it wasn't finished.
|
||||||
|
// This supports the case where an analyst has partially ingested a device
|
||||||
|
// but has to stop before completion. They will at least have part of the image.
|
||||||
|
if(settings.getUpdateDatabasePath()){
|
||||||
|
caseDb.updateImagePath(settings.getPath(), dataSourceId);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
} catch (TskCoreException ex){
|
} catch (TskCoreException ex){
|
||||||
logger.log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS
|
logger.log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -173,9 +200,10 @@ class ImageWriter implements PropertyChangeListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Wait for finishImageWriter to complete
|
// Wait for finishImageWriter to complete
|
||||||
|
int result = 0;
|
||||||
try{
|
try{
|
||||||
// The call to get() can happen multiple times if the user closes the case, which is ok
|
// The call to get() can happen multiple times if the user closes the case, which is ok
|
||||||
finishTask.get();
|
result = finishTask.get();
|
||||||
} catch (InterruptedException | ExecutionException ex){
|
} catch (InterruptedException | ExecutionException ex){
|
||||||
logger.log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS
|
logger.log(Level.SEVERE, "Error finishing VHD image", ex); //NON-NLS
|
||||||
}
|
}
|
||||||
@ -189,7 +217,11 @@ class ImageWriter implements PropertyChangeListener{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.log(Level.INFO, String.format("Finished writing VHD image for %s", dataSourceName)); //NON-NLS
|
if(result == 0){
|
||||||
|
logger.log(Level.INFO, String.format("Successfully finished writing VHD image for %s", dataSourceName)); //NON-NLS
|
||||||
|
} else {
|
||||||
|
logger.log(Level.INFO, String.format("Finished VHD image for %s with errors", dataSourceName)); //NON-NLS
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -18,14 +18,15 @@
|
|||||||
*/
|
*/
|
||||||
package org.sleuthkit.autopsy.imagewriter;
|
package org.sleuthkit.autopsy.imagewriter;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.ArrayList;
|
||||||
import java.util.Set;
|
import java.util.List;
|
||||||
import org.openide.DialogDescriptor;
|
import org.openide.DialogDescriptor;
|
||||||
import org.openide.DialogDisplayer;
|
import org.openide.DialogDisplayer;
|
||||||
import org.openide.NotifyDescriptor;
|
import org.openide.NotifyDescriptor;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.openide.util.lookup.ServiceProvider;
|
import org.openide.util.lookup.ServiceProvider;
|
||||||
import org.openide.util.lookup.ServiceProviders;
|
import org.openide.util.lookup.ServiceProviders;
|
||||||
|
import org.sleuthkit.autopsy.casemodule.Case;
|
||||||
import org.sleuthkit.autopsy.framework.AutopsyService;
|
import org.sleuthkit.autopsy.framework.AutopsyService;
|
||||||
|
|
||||||
@ServiceProviders(value = {@ServiceProvider(service = AutopsyService.class)})
|
@ServiceProviders(value = {@ServiceProvider(service = AutopsyService.class)})
|
||||||
@ -39,20 +40,20 @@ import org.sleuthkit.autopsy.framework.AutopsyService;
|
|||||||
|
|
||||||
public class ImageWriterService implements AutopsyService {
|
public class ImageWriterService implements AutopsyService {
|
||||||
|
|
||||||
private static final Set<ImageWriter> imageWriters = new HashSet<>(); // Contains all Image Writer objects
|
private static final List<ImageWriter> imageWriters = new ArrayList<>(); // Contains all Image Writer objects
|
||||||
private static final Object imageWritersLock = new Object(); // Get this lock before accessing currentImageWriters
|
private static final Object imageWritersLock = new Object(); // Get this lock before accessing currentImageWriters
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an image writer object for the given data source ID.
|
* Create an image writer object for the given data source ID.
|
||||||
* @param imageId ID for the image
|
* @param imageId ID for the image
|
||||||
*/
|
*/
|
||||||
public static void createImageWriter(Long imageId){
|
public static void createImageWriter(Long imageId, ImageWriterSettings settings){
|
||||||
|
|
||||||
// ImageWriter objects are created during the addImageTask. They can not arrive while
|
// ImageWriter objects are created during the addImageTask. They can not arrive while
|
||||||
// we're closing case resources so we don't need to worry about one showing up while
|
// we're closing case resources so we don't need to worry about one showing up while
|
||||||
// doing our close/cleanup.
|
// doing our close/cleanup.
|
||||||
synchronized(imageWritersLock){
|
synchronized(imageWritersLock){
|
||||||
ImageWriter writer = new ImageWriter(imageId);
|
ImageWriter writer = new ImageWriter(imageId, settings);
|
||||||
writer.subscribeToEvents();
|
writer.subscribeToEvents();
|
||||||
imageWriters.add(writer);
|
imageWriters.add(writer);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Autopsy Forensic Browser
|
||||||
|
*
|
||||||
|
* Copyright 2011-2016 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.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.sleuthkit.autopsy.imagewriter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class to hold the image writer settings from the local disk panel
|
||||||
|
*/
|
||||||
|
public class ImageWriterSettings {
|
||||||
|
private final String path;
|
||||||
|
private final boolean updateDatabasePath;
|
||||||
|
|
||||||
|
public ImageWriterSettings(String path, boolean updateDatabasePath){
|
||||||
|
this.path = path;
|
||||||
|
this.updateDatabasePath = updateDatabasePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPath(){
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getUpdateDatabasePath(){
|
||||||
|
return updateDatabasePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -74,6 +74,7 @@ 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 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.
|
||||||
*/
|
*/
|
||||||
@ -89,11 +90,12 @@ 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 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.
|
||||||
*/
|
*/
|
||||||
IngestJobSettingsPanel(IngestJobSettings settings, List<Content> dataSources) {
|
public IngestJobSettingsPanel(IngestJobSettings settings, List<Content> dataSources) {
|
||||||
this.settings = settings;
|
this.settings = settings;
|
||||||
this.dataSources.addAll(dataSources);
|
this.dataSources.addAll(dataSources);
|
||||||
try {
|
try {
|
||||||
|
@ -19,12 +19,14 @@
|
|||||||
package org.sleuthkit.autopsy.ingest.runIngestModuleWizard;
|
package org.sleuthkit.autopsy.ingest.runIngestModuleWizard;
|
||||||
|
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
|
import java.util.List;
|
||||||
import javax.swing.event.ChangeListener;
|
import javax.swing.event.ChangeListener;
|
||||||
import org.openide.WizardDescriptor;
|
import org.openide.WizardDescriptor;
|
||||||
import org.openide.util.HelpCtx;
|
import org.openide.util.HelpCtx;
|
||||||
import org.openide.util.NbBundle;
|
import org.openide.util.NbBundle;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
|
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestJobSettingsPanel;
|
import org.sleuthkit.autopsy.ingest.IngestJobSettingsPanel;
|
||||||
|
import org.sleuthkit.datamodel.Content;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A wizard panel for configuring an ingest job.
|
* A wizard panel for configuring an ingest job.
|
||||||
@ -34,16 +36,17 @@ class IngestModulesConfigWizardPanel extends ShortcutWizardDescriptorPanel {
|
|||||||
private final String executionContext;
|
private final String executionContext;
|
||||||
private final IngestJobSettings.IngestType ingestType;
|
private final IngestJobSettings.IngestType ingestType;
|
||||||
private IngestJobSettingsPanel ingestJobSettingsPanel;
|
private IngestJobSettingsPanel ingestJobSettingsPanel;
|
||||||
|
private final List<Content> dataSources;
|
||||||
/**
|
/**
|
||||||
* Constructs a wizard panel for configuring an ingest job.
|
* Constructs a wizard panel for configuring an ingest job.
|
||||||
*
|
*
|
||||||
* @param executionContest The execution context for the wizard.
|
* @param executionContest The execution context for the wizard.
|
||||||
* @param ingestType The ingest type.
|
* @param ingestType The ingest type.
|
||||||
*/
|
*/
|
||||||
IngestModulesConfigWizardPanel(String executionContest, IngestJobSettings.IngestType ingestType) {
|
IngestModulesConfigWizardPanel(String executionContest, IngestJobSettings.IngestType ingestType, List<Content> dataSources) {
|
||||||
this.executionContext = executionContest;
|
this.executionContext = executionContest;
|
||||||
this.ingestType = ingestType;
|
this.ingestType = ingestType;
|
||||||
|
this.dataSources = dataSources;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,7 +67,7 @@ class IngestModulesConfigWizardPanel extends ShortcutWizardDescriptorPanel {
|
|||||||
* Creating an ingest job settings object is expensive, so it is
|
* Creating an ingest job settings object is expensive, so it is
|
||||||
* deferred until this panel is actually used in the wizard.
|
* deferred until this panel is actually used in the wizard.
|
||||||
*/
|
*/
|
||||||
ingestJobSettingsPanel = new IngestJobSettingsPanel(new IngestJobSettings(executionContext, ingestType));
|
ingestJobSettingsPanel = new IngestJobSettingsPanel(new IngestJobSettings(executionContext, ingestType), dataSources);
|
||||||
}
|
}
|
||||||
ingestJobSettingsPanel.setName(Bundle.IngestModulesConfigWizardPanel_name_text());
|
ingestJobSettingsPanel.setName(Bundle.IngestModulesConfigWizardPanel_name_text());
|
||||||
return ingestJobSettingsPanel;
|
return ingestJobSettingsPanel;
|
||||||
|
@ -91,7 +91,7 @@ public final class RunIngestModulesAction extends CallableSystemAction {
|
|||||||
* WizardDescriptor.Panel.getComponent().getName().
|
* WizardDescriptor.Panel.getComponent().getName().
|
||||||
*/
|
*/
|
||||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||||
RunIngestModulesWizardIterator wizard = new RunIngestModulesWizardIterator(EXECUTION_CONTEXT, this.ingestType);
|
RunIngestModulesWizardIterator wizard = new RunIngestModulesWizardIterator(EXECUTION_CONTEXT, this.ingestType, this.dataSources);
|
||||||
WizardDescriptor wiz = new WizardDescriptor(wizard);
|
WizardDescriptor wiz = new WizardDescriptor(wizard);
|
||||||
wiz.setTitleFormat(new MessageFormat("{0}"));
|
wiz.setTitleFormat(new MessageFormat("{0}"));
|
||||||
wiz.setTitle(Bundle.RunIngestModulesAction_name());
|
wiz.setTitle(Bundle.RunIngestModulesAction_name());
|
||||||
|
@ -27,6 +27,7 @@ import javax.swing.event.ChangeListener;
|
|||||||
import org.openide.WizardDescriptor;
|
import org.openide.WizardDescriptor;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
|
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
|
||||||
import org.sleuthkit.autopsy.ingest.IngestProfiles;
|
import org.sleuthkit.autopsy.ingest.IngestProfiles;
|
||||||
|
import org.sleuthkit.datamodel.Content;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A wizard that allows a user to configure an ingest job.
|
* A wizard that allows a user to configure an ingest job.
|
||||||
@ -45,7 +46,7 @@ final class RunIngestModulesWizardIterator implements WizardDescriptor.Iterator<
|
|||||||
* settings can differ by execution context.
|
* settings can differ by execution context.
|
||||||
* @param ingestType The type of ingest to be configured.
|
* @param ingestType The type of ingest to be configured.
|
||||||
*/
|
*/
|
||||||
RunIngestModulesWizardIterator(String executionContext, IngestJobSettings.IngestType ingestType) {
|
RunIngestModulesWizardIterator(String executionContext, IngestJobSettings.IngestType ingestType, List<Content> dataSources) {
|
||||||
this.ingestType = ingestType;
|
this.ingestType = ingestType;
|
||||||
panels = new ArrayList<>();
|
panels = new ArrayList<>();
|
||||||
List<IngestProfiles.IngestProfile> profiles = IngestProfiles.getIngestProfiles();
|
List<IngestProfiles.IngestProfile> profiles = IngestProfiles.getIngestProfiles();
|
||||||
@ -53,7 +54,7 @@ final class RunIngestModulesWizardIterator implements WizardDescriptor.Iterator<
|
|||||||
panels.add(new IngestProfileSelectionWizardPanel(executionContext, PROP_LASTPROFILE_NAME));
|
panels.add(new IngestProfileSelectionWizardPanel(executionContext, PROP_LASTPROFILE_NAME));
|
||||||
}
|
}
|
||||||
|
|
||||||
panels.add(new IngestModulesConfigWizardPanel(executionContext, this.ingestType));
|
panels.add(new IngestModulesConfigWizardPanel(executionContext, this.ingestType, dataSources));
|
||||||
String[] steps = new String[panels.size()];
|
String[] steps = new String[panels.size()];
|
||||||
for (int i = 0; i < panels.size(); i++) {
|
for (int i = 0; i < panels.size(); i++) {
|
||||||
Component c = panels.get(i).getComponent();
|
Component c = panels.get(i).getComponent();
|
||||||
|
@ -763,7 +763,7 @@ public final class FilesSet implements Serializable {
|
|||||||
* matched.
|
* matched.
|
||||||
*/
|
*/
|
||||||
ExtensionCondition(Pattern extension) {
|
ExtensionCondition(Pattern extension) {
|
||||||
super(extension.pattern(), false);
|
super(extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -21,23 +21,25 @@ The data source must remain accessible for the duration of the analysis because
|
|||||||
|
|
||||||
Regardless of the type of data source, there are some common steps in the process:
|
Regardless of the type of data source, there are some common steps in the process:
|
||||||
|
|
||||||
1) You will be prompted to specify the data source to add (details are provided below)
|
1) You will select the type of data source.
|
||||||
|
|
||||||
\image html select-data-source-type.PNG
|
\image html select-data-source-type.PNG
|
||||||
|
|
||||||
|
2) You will be prompted to specify the data source to add. This screen varies based on the data source type. Details on adding each type of data source are provided below.
|
||||||
|
|
||||||
NOTE: If you are adding a data source to a multi-user case, ensure that all Autopsy clients will have access to the data source at the same path. We recommend using UNC paths to ensure this consistent mapping.
|
NOTE: If you are adding a data source to a multi-user case, ensure that all Autopsy clients will have access to the data source at the same path. We recommend using UNC paths to ensure this consistent mapping.
|
||||||
|
|
||||||
2) Autopsy will perform a basic examination of the data source and populate an embedded database with an entry for each file in the data source. No content is analyzed in the process, only the files are enumerated.
|
3) Autopsy will perform a basic examination of the data source and populate an embedded database with an entry for each file in the data source. No content is analyzed in the process, only the files are enumerated.
|
||||||
|
|
||||||
3) While it is examining the data source, you will be prompted with a list of ingest modules to enable.
|
4) While it is examining the data source, you will be prompted with a list of ingest modules to enable. If one or more ingest profiles have been saved, there will be a screen before this asking whether to use one of the saved profiles or do a custom setup. See \ref ingest_page for more information on setting up ingest profiles.
|
||||||
|
|
||||||
\image html select-ingest-modules.PNG
|
\image html select-ingest-modules.PNG
|
||||||
|
|
||||||
4) After you configure the ingest modules, you may need to wait for Autopsy to finish its basic examination of the data source.
|
5) After you configure the ingest modules, you may need to wait for Autopsy to finish its basic examination of the data source.
|
||||||
|
|
||||||
\image html data-source-progress-bar.PNG
|
\image html data-source-progress-bar.PNG
|
||||||
|
|
||||||
5) After the ingest modules have been configured and the basic examination of the data source is complete, the ingest modules will begin to analyze the file contents.
|
6) After the ingest modules have been configured and the basic examination of the data source is complete, the ingest modules will begin to analyze the file contents.
|
||||||
|
|
||||||
You cannot remove a data source from a case.
|
You cannot remove a data source from a case.
|
||||||
|
|
||||||
@ -52,24 +54,29 @@ Autopsy supports disk images in the following formats:
|
|||||||
|
|
||||||
To add a disk image:
|
To add a disk image:
|
||||||
|
|
||||||
-# Choose "Disk Image or VM File" from the pull down.
|
-# Choose "Disk Image or VM File" from the data source types.
|
||||||
-# Browse to the first file in the disk image. You need to specify only the first file and Autopsy will find the rest.
|
-# Browse to the first file in the disk image. You need to specify only the first file and Autopsy will find the rest.
|
||||||
-# Choose the timezone that the disk image came from. This is most important for when adding FAT file systems because it does not store timezone information and Autopsy will not know how to normalize to UTC.
|
-# Choose the timezone that the disk image came from. This is most important for when adding FAT file systems because it does not store timezone information and Autopsy will not know how to normalize to UTC.
|
||||||
-# Choose to perform orphan file finding on FAT file systems. This can be a time intensive process because it will require that Autopsy look at each sector in the device.
|
-# Choose to perform orphan file finding on FAT file systems. This can be a time intensive process because it will require that Autopsy look at each sector in the device.
|
||||||
|
|
||||||
|
|
||||||
\section ds_local Adding a Local Drive
|
\section ds_local Adding a Local Disk
|
||||||
|
|
||||||
Autopsy can analyze a local drive without needing to first make an image copy of it. This is most useful when analyzing a USB-attached device through a write blocker.
|
Autopsy can analyze a local disk without needing to first make an image copy of it. This is most useful when analyzing a USB-attached device through a write blocker.
|
||||||
|
|
||||||
Note that if you are analyzing a local drive that is being updated, then Autopsy will not see files that are added after you add it as a data source.
|
Note that if you are analyzing a local disk that is being updated, then Autopsy will not see files that are added after you add it as a data source.
|
||||||
|
|
||||||
You will need to be running Autopsy as an Administrator to view all devices.
|
You will need to be running Autopsy as an Administrator to view all devices.
|
||||||
|
|
||||||
|
There is an option to make a copy of the local disk as a VHD during analysis. This VHD can be loaded in Windows or analyzed through Autopsy. There is an additional option to update the image path in the case database to this newly created file. Enabling this option will allow you to browse the case data normally even after the local disk is removed. Note that at least one ingest module must successfully run in order to generate the complete image copy.
|
||||||
|
|
||||||
|
\image html local-disk-data-source.PNG
|
||||||
|
|
||||||
To add a local drive:
|
To add a local drive:
|
||||||
-# Choose "Local Drive" from the pull down.
|
-# Choose "Local Disk" from the data source types.
|
||||||
-# Choose the device from the pull down list.
|
-# Choose the device from the pull down list.
|
||||||
-# Choose to perform orphan file finding. See comment in \ref ds_img about this setting.
|
-# Choose to perform orphan file finding. See comment in \ref ds_img about this setting.
|
||||||
|
-# Choose whether to create a VHD copy of the local disk and whether to update the image path.
|
||||||
|
|
||||||
|
|
||||||
\section ds_log Adding a Logical File
|
\section ds_log Adding a Logical File
|
||||||
@ -84,7 +91,7 @@ Some things to note when doing this:
|
|||||||
\image html change_logical_file_set_display_name.PNG
|
\image html change_logical_file_set_display_name.PNG
|
||||||
|
|
||||||
To add logical files:
|
To add logical files:
|
||||||
-# Choose "Logical Files" from the pull down.
|
-# Choose "Logical Files" from the data source types.
|
||||||
-# Press the "Add" button and navigate to a folder or file to add. Choosing a folder will cause all of its contents (including sub-folders) to be added.
|
-# Press the "Add" button and navigate to a folder or file to add. Choosing a folder will cause all of its contents (including sub-folders) to be added.
|
||||||
-# Continue to press "Add" until all files and folders have been selected.
|
-# Continue to press "Add" until all files and folders have been selected.
|
||||||
|
|
||||||
@ -95,8 +102,8 @@ All of the files that you added in the panel will be grouped together into a sin
|
|||||||
\image html unallocated_space_options.PNG
|
\image html unallocated_space_options.PNG
|
||||||
|
|
||||||
To add unallocated space image files:
|
To add unallocated space image files:
|
||||||
-# Choose "Unallocated Space Image File" from the pull down
|
-# Choose "Unallocated Space Image File" from the data source types.
|
||||||
-# Browse to the file
|
-# Browse to the file.
|
||||||
-# Choose whether to break the image up into chunks. Breaking the image up will give better performance since the chunks can be processed in parallel, but there is a chance that keywords or carved files that span chunk boundaries will be missed.
|
-# Choose whether to break the image up into chunks. Breaking the image up will give better performance since the chunks can be processed in parallel, but there is a chance that keywords or carved files that span chunk boundaries will be missed.
|
||||||
|
|
||||||
*/
|
*/
|
@ -32,10 +32,12 @@ a data source. All user-defined and Tika rules are always applied.
|
|||||||
Seeing Results
|
Seeing Results
|
||||||
------
|
------
|
||||||
|
|
||||||
This module does not have obvious impacts in the user interface, though it is used by many other modules.
|
The results can be seen in the views area of the tree, under Views->File Types->By MIME Type.
|
||||||
|
|
||||||
|
\image html mime-type-tree.PNG
|
||||||
|
|
||||||
|
Note that only user-defined MIME types of the form (media type)/(media subtype) will be displayed in the tree.
|
||||||
|
|
||||||
To see the file type of an individual file, view the "Results" tab in the lower right when you navigate to the file. You should see a page in there that mentions the file type.
|
To see the file type of an individual file, view the "Results" tab in the lower right when you navigate to the file. You should see a page in there that mentions the file type.
|
||||||
|
|
||||||
The Views area of the tree does not take the results of this module into account. That part of the tree relies on extension. We will be updating it in the future to rely on extension when there is no output from this module for the file.
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 46 KiB |
BIN
docs/doxygen-user/images/ingest-file-filters.PNG
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
docs/doxygen-user/images/ingest-profile-create.PNG
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
docs/doxygen-user/images/ingest-profiles.PNG
Normal file
After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 55 KiB |
BIN
docs/doxygen-user/images/local-disk-data-source.PNG
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
docs/doxygen-user/images/mime-type-tree.PNG
Normal file
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 51 KiB |
BIN
docs/doxygen-user/images/profile-data-source-panel.PNG
Normal file
After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 28 KiB |
@ -29,16 +29,42 @@ Once ingest is started, you can review the currently running ingest tasks in the
|
|||||||
|
|
||||||
\section ingest_configure Configuring Ingest Modules
|
\section ingest_configure Configuring Ingest Modules
|
||||||
|
|
||||||
You will be presented with an interface to configure the ingest modules. From here, you can choose to enable or disable each module and some modules will have further configuration settings.
|
You will be presented with an interface to configure the ingest modules. From here, you can choose which type of files to analyze and enable or disable each module. Some modules will have further configuration settings.
|
||||||
|
|
||||||
\image html select-ingest-modules.PNG
|
\image html select-ingest-modules.PNG
|
||||||
|
|
||||||
|
The selection box at the top controls which files the ingest modules will run on. The two built-in options are "All files, directories, and unallocated space" and "All Files and Directories." The \ref file_filters section describes how to create custom file filters. The chosen filter applies to all ingest modules.
|
||||||
|
|
||||||
There are two places to configure ingest modules. When you select the module name, you may have some "run time" options to configure in the panel to the right. These are generally settings that you may want to change from image to image.
|
There are two places to configure ingest modules. When you select the module name, you may have some "run time" options to configure in the panel to the right. These are generally settings that you may want to change from image to image.
|
||||||
|
|
||||||
There may also be an "Advanced" button that is enabled in the lower corner. Pressing this button allows you to change global settings that are not specific to a single image. This advanced configuration panel can often be found in the "Tools", "Options" menu too.
|
There may also be an "Advanced" button that is enabled in the lower corner. Pressing this button allows you to change global settings that are not specific to a single image. This advanced configuration panel can often be found in the "Tools", "Options" menu too.
|
||||||
|
|
||||||
As an example, the hash lookup module will allow you to enable or disable hash databases in the "run time" options panel, but requires you to go to the "Advanced" dialog to add or remove hash databases from the Autopsy configuration.
|
As an example, the hash lookup module will allow you to enable or disable hash databases in the "run time" options panel, but requires you to go to the "Advanced" dialog to add or remove hash databases from the Autopsy configuration.
|
||||||
|
|
||||||
|
\section file_filters Custom File Filters
|
||||||
|
|
||||||
|
The file filters panel can be opened from the ingest module selection panel or through the Ingest tab on the main options panel. File filters allow ingest modules to be run on only a subset of the files. In the example below, a filter has been set up to only run on files with a "png" extension.
|
||||||
|
|
||||||
|
\image html ingest-file-filters.PNG
|
||||||
|
|
||||||
|
Each filter contains one or more rules for selecting files based on file name and/or path. All files will still be displayed in the tree view, but the ingest modules will only run on a subset. If we use the previous example and run the hash module, only files ending in .png will have their hash computed.
|
||||||
|
|
||||||
|
\section ingest_profiles Using Ingest Profiles
|
||||||
|
|
||||||
|
Ingest profiles allow you to quickly choose a defined set of ingest modules to run. This can be useful if you run different sets of ingest modules (or different configurations of those ingest modules) on different types of data. Ingest profiles can be configured through the Ingest tab on the options panel.
|
||||||
|
|
||||||
|
\image html ingest-profiles.PNG
|
||||||
|
|
||||||
|
Each profile can specify different per-run settings for each ingest module, and you can choose use either a predefined or custom file filter (see \ref file_filters).
|
||||||
|
|
||||||
|
\image html ingest-profile-create.PNG
|
||||||
|
|
||||||
|
If any custom profiles are present, there will be a new screen in the add data source wizard.
|
||||||
|
|
||||||
|
\image html profile-data-source-panel.PNG
|
||||||
|
|
||||||
|
If you choose custom settings it will bring up the normal ingest module selection panel. If you choose a user-defined profile the ingest module screen will be skipped entirely and the ingest modules from that profile will be run on the data source. The profile selection panel will also appear when running ingest by right-clicking on a data source from the tree.
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
\section ingest_already_run Notification of Ingest Already Run
|
\section ingest_already_run Notification of Ingest Already Run
|
||||||
If an ingest module has already been run for a particular data source, you will see a triangular yellow icon with an exclaimation point next to the module in the "Run Ingest Modules" dialog, as shown in the screenshot below.
|
If an ingest module has already been run for a particular data source, you will see a triangular yellow icon with an exclaimation point next to the module in the "Run Ingest Modules" dialog, as shown in the screenshot below.
|
||||||
|
@ -1,66 +0,0 @@
|
|||||||
/*! \page interesting_page Interesting Files Module
|
|
||||||
Overview
|
|
||||||
========
|
|
||||||
|
|
||||||
The Interesting Files module allows you to search for files or directories in a data source and generate alerts when they are found. You configure rules for the files that you want to find.
|
|
||||||
|
|
||||||
You would use this to be notified when certain things are found. There are examples later in this file to generate alerts when VMWare images are found or when iPhone backup files are found. This module is useful for file types that will frequently have a consistent name and that may not be part of the stanadrd checklist that you look for (or if you simply want to automated your checklist).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Rules
|
|
||||||
=======
|
|
||||||
|
|
||||||
Add rules using Tools -> Options -> Interesting Files.
|
|
||||||
|
|
||||||
All rules need to be part of a set. Sets need to have the following defined:
|
|
||||||
|
|
||||||
- Set Name (required)
|
|
||||||
- Set Description (optional)
|
|
||||||
|
|
||||||
Rules specify what to look for in a data source. Each rule specifies:
|
|
||||||
- Type: If the rule should be applied to only files, only directories, or both files and directories.
|
|
||||||
- Name Pattern: String to match the file name against.
|
|
||||||
- Name Pattern Type: Should the pattern be matched against the full file type or just the extension.
|
|
||||||
- Path Pattern: A substring of the parent path that must be matched. This allows you to restrict generic names to a specific structure (such as an application name). A substring match is performed.
|
|
||||||
- Rule Name: Additional details that are displayed in the UI when that rule is matched. Allows you to determine which rule in the set matched.
|
|
||||||
|
|
||||||
|
|
||||||
Example
|
|
||||||
=======
|
|
||||||
|
|
||||||
VMWare
|
|
||||||
--------
|
|
||||||
This set of rules is to detect VMWare Player or vmdk files. This would help to make sure you look into the virtual machines for additional evidence.
|
|
||||||
|
|
||||||
NOTE: This is not extensive and is simply a minimal example:
|
|
||||||
|
|
||||||
|
|
||||||
- Set Name: VMWare
|
|
||||||
- Rule 1:
|
|
||||||
- Type: Files
|
|
||||||
- Full Name: vmplayer.exe
|
|
||||||
- Name: Program EXE
|
|
||||||
- Rule 2:
|
|
||||||
- Type: Files
|
|
||||||
- Extension: vmdk
|
|
||||||
- Name: VMDK File
|
|
||||||
|
|
||||||
iPhone Backups
|
|
||||||
-------------
|
|
||||||
This set of rules is to detect a folder for iPhone Backups. These are typically in a folder such as "%AppData%\Roaming\Apple Computer\MobileSync\Backup" on Windows. Here is a rule that you could use for that.
|
|
||||||
|
|
||||||
- Set Name: iPhone Backups
|
|
||||||
- Rule 1:
|
|
||||||
- Type: Directory
|
|
||||||
- Name: Backup
|
|
||||||
- Path: Apple Computer/MobileSync
|
|
||||||
|
|
||||||
Using the Module
|
|
||||||
======
|
|
||||||
|
|
||||||
When you enable the Interesting Files module, you can choose what rule sets to enable. To add rules, use the "Advanced" button from the ingest module panel.
|
|
||||||
|
|
||||||
When files are found, they will be in the Interesting Files area of the tree. You shoudl see the set and rule names with the match.
|
|
||||||
|
|
||||||
*/
|
|
@ -12,11 +12,13 @@ Configuration
|
|||||||
|
|
||||||
Add rules using "Tools", "Options", "Interesting Files".
|
Add rules using "Tools", "Options", "Interesting Files".
|
||||||
|
|
||||||
All rules need to be part of a set. Sets need to have the following defined:
|
All rules need to be part of a set. Select "New set" on the left side panel to create a new set. Sets need to have the following defined:
|
||||||
|
|
||||||
- Set Name (required)
|
- Set Name (required)
|
||||||
- Set Description (optional)
|
- Set Description (optional)
|
||||||
|
|
||||||
|
Sets can be renamed, edited, copied, and imported and exported from the left side panel.
|
||||||
|
|
||||||
Rules specify what to look for in a data source. Each rule specifies:
|
Rules specify what to look for in a data source. Each rule specifies:
|
||||||
- Type: If the rule should be applied to only files, only directories, or both files and directories.
|
- Type: If the rule should be applied to only files, only directories, or both files and directories.
|
||||||
- Name Pattern: String to match the file name against.
|
- Name Pattern: String to match the file name against.
|
||||||
|
@ -16,7 +16,7 @@ Once files are placed in the Solr index, they can be searched quickly for specif
|
|||||||
|
|
||||||
\section keyword_search_configuration_dialog Keyword Search Configuration Dialog
|
\section keyword_search_configuration_dialog Keyword Search Configuration Dialog
|
||||||
|
|
||||||
The keyword search configuration dialog has three tabs, each with it's own purpose:
|
The keyword search configuration dialog has three tabs, each with its own purpose:
|
||||||
\li The Lists tab is used to add, remove, and modify keyword search lists.
|
\li The Lists tab is used to add, remove, and modify keyword search lists.
|
||||||
\li The String Extraction tab is used to enable language scripts and extraction type.
|
\li The String Extraction tab is used to enable language scripts and extraction type.
|
||||||
\li The General tab is used to configure the ingest timings and display information.
|
\li The General tab is used to configure the ingest timings and display information.
|
||||||
@ -26,7 +26,7 @@ To create a list, select the 'New List' button and choose a name for the new Key
|
|||||||
Regular expressions are supported using Lucene Regex Syntax which is documented here: https://lucene.apache.org/core/6_4_0/core/org/apache/lucene/util/automaton/RegExp.html. .* is automatically added to the beginning and end of the regular expressions to ensure all matches are found. Additionally, the resulting hits are split on common token separator boundaries (e.g. space, newline, colon, exclamation point etc.) to reduce false positives and to make the resulting keyword hit more amenable to highlighting. If you would prefer not to split on these common boundary characters, you can put .* at the start and/or end of the regex.
|
Regular expressions are supported using Lucene Regex Syntax which is documented here: https://lucene.apache.org/core/6_4_0/core/org/apache/lucene/util/automaton/RegExp.html. .* is automatically added to the beginning and end of the regular expressions to ensure all matches are found. Additionally, the resulting hits are split on common token separator boundaries (e.g. space, newline, colon, exclamation point etc.) to reduce false positives and to make the resulting keyword hit more amenable to highlighting. If you would prefer not to split on these common boundary characters, you can put .* at the start and/or end of the regex.
|
||||||
|
|
||||||
<b>List Import and Export</b> \n
|
<b>List Import and Export</b> \n
|
||||||
Autopsy supports importing Encase tab-delimited lists as well as lists created previously with Autopsy. For Encase lists, folder structure and hierarchy is currently ignored. This will be fixed in a future version. There is currently no way to export lists for use with Encase. This will also be added in future releases.
|
Autopsy supports importing Encase tab-delimited lists as well as lists created previously with Autopsy. For Encase lists, folder structure and hierarchy is ignored. There is currently no way to export lists for use with Encase, but lists can be exported to share between Autopsy users.
|
||||||
|
|
||||||
<b>Lists tab</b> \n
|
<b>Lists tab</b> \n
|
||||||
\image html keyword-search-configuration-dialog.PNG
|
\image html keyword-search-configuration-dialog.PNG
|
||||||
|
@ -6,7 +6,7 @@ After installing Autopsy, there are several hardware-based things that we sugges
|
|||||||
- Run Autopsy from the Start Menu or desktop
|
- Run Autopsy from the Start Menu or desktop
|
||||||
- When presented with the case creation splash screen, cancel/close the window
|
- When presented with the case creation splash screen, cancel/close the window
|
||||||
- Select "Tools", "Options"
|
- Select "Tools", "Options"
|
||||||
- On the "Autopsy" tab, there is a drop down for _Number of threads to use for file ingest_. We recommend you set this value 4. If you set this number too high, performance can degrade because the pipelines are fighting for the same physical resources. Individual testing should be done to find an optimal setting, but our testing reveals that for most systems and setups, after four threads, the machine is I/O bound anyway, and increasing this number beyond 4 may actually reduce performance.
|
- On the "Ingest" panel on the "Settings" tab, there is a drop down for _Number of threads to use for file ingest_. We recommend you set this value 4. If you set this number too high, performance can degrade because the pipelines are fighting for the same physical resources. Individual testing should be done to find an optimal setting, but our testing reveals that for most systems and setups, after four threads, the machine is I/O bound anyway, and increasing this number beyond 4 may actually reduce performance.
|
||||||
- After each change, restart Autopsy to let this setting take effect.
|
- After each change, restart Autopsy to let this setting take effect.
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
|