Merge branch 'custom-release-may-2018' of github.com:sleuthkit/autopsy into 3734_ingest_progress
@@ -84,7 +84,7 @@
|
||||
|
||||
<target name="getTestDataFiles">
|
||||
<mkdir dir="${basedir}/test/qa-functional/data"/>
|
||||
<get src="https://drive.google.com/uc?id=1dLYGctuvRQMmnzfXPppTM_9gB49eLc_g" dest="${test-input}/embedded.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1dLYGctuvRQMmnzfXPppTM_9gB49eLc_g" dest="${test-input}/embedded.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1JACMDyH4y54ypGzFWl82ZzMQf3qbrioP" dest="${test-input}/encryption_detection_bitlocker_test.vhd" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=0BxdBkzm5VKGNT0dGY0dqcHVsU3M" dest="${test-input}/filter_test1.img" skipexisting="true"/>
|
||||
<get src="https://drive.google.com/uc?id=1bghoSm7z7nhmGIxlllyY1MMlbLntxm7n" dest="${test-input}/local_files_test.zip" skipexisting="true"/>
|
||||
|
||||
@@ -63,7 +63,7 @@ public interface DataResult {
|
||||
* Sets the descriptive text about the source of the nodes displayed in this
|
||||
* result view component.
|
||||
*
|
||||
* @param description The text to display.
|
||||
* @param pathText The text to display.
|
||||
*/
|
||||
public void setPath(String pathText);
|
||||
|
||||
|
||||
@@ -734,7 +734,7 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C
|
||||
*
|
||||
* @return True or false.
|
||||
*
|
||||
* @Deprecated This method has no valid use case.
|
||||
* @deprecated This method has no valid use case.
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
|
||||
@@ -28,7 +28,7 @@ public interface AutopsyVisitableItem {
|
||||
/**
|
||||
* visitor pattern support
|
||||
*
|
||||
* @param v visitor
|
||||
* @param visitor visitor
|
||||
*
|
||||
* @return visitor return value
|
||||
*/
|
||||
|
||||
@@ -40,7 +40,7 @@ abstract class ContentNode extends DisplayableItemNode {
|
||||
/**
|
||||
* Visitor pattern support.
|
||||
*
|
||||
* @param v visitor
|
||||
* @param visitor visitor
|
||||
*
|
||||
* @return visitor's visit return value
|
||||
*/
|
||||
|
||||
@@ -65,6 +65,8 @@ public class HealthMonitorDashboard {
|
||||
private JComboBox<String> dateComboBox = null;
|
||||
private JComboBox<String> hostComboBox = null;
|
||||
private JCheckBox hostCheckBox = null;
|
||||
private JCheckBox showTrendLineCheckBox = null;
|
||||
private JCheckBox skipOutliersCheckBox = null;
|
||||
private JPanel graphPanel = null;
|
||||
private JDialog dialog = null;
|
||||
private final Container parentWindow;
|
||||
@@ -201,7 +203,9 @@ public class HealthMonitorDashboard {
|
||||
* @return the control panel
|
||||
*/
|
||||
@NbBundle.Messages({"HealthMonitorDashboard.createTimingControlPanel.filterByHost=Filter by host",
|
||||
"HealthMonitorDashboard.createTimingControlPanel.maxDays=Max days to display"})
|
||||
"HealthMonitorDashboard.createTimingControlPanel.maxDays=Max days to display",
|
||||
"HealthMonitorDashboard.createTimingControlPanel.skipOutliers=Do not plot outliers",
|
||||
"HealthMonitorDashboard.createTimingControlPanel.showTrendLine=Show trend line"})
|
||||
private JPanel createTimingControlPanel() {
|
||||
JPanel timingControlPanel = new JPanel();
|
||||
|
||||
@@ -252,7 +256,7 @@ public class HealthMonitorDashboard {
|
||||
}
|
||||
});
|
||||
|
||||
// Create the checkbox
|
||||
// Create the host checkbox
|
||||
hostCheckBox = new JCheckBox(Bundle.HealthMonitorDashboard_createTimingControlPanel_filterByHost());
|
||||
hostCheckBox.setSelected(false);
|
||||
hostComboBox.setEnabled(false);
|
||||
@@ -270,6 +274,38 @@ public class HealthMonitorDashboard {
|
||||
}
|
||||
});
|
||||
|
||||
// Create the checkbox for showing the trend line
|
||||
showTrendLineCheckBox = new JCheckBox(Bundle.HealthMonitorDashboard_createTimingControlPanel_showTrendLine());
|
||||
showTrendLineCheckBox.setSelected(true);
|
||||
|
||||
// Set up the listener on the checkbox
|
||||
showTrendLineCheckBox.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
try {
|
||||
updateTimingMetricGraphs();
|
||||
} catch (HealthMonitorException ex) {
|
||||
logger.log(Level.SEVERE, "Error populating timing metric panel", ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Create the checkbox for omitting outliers
|
||||
skipOutliersCheckBox = new JCheckBox(Bundle.HealthMonitorDashboard_createTimingControlPanel_skipOutliers());
|
||||
skipOutliersCheckBox.setSelected(false);
|
||||
|
||||
// Set up the listener on the checkbox
|
||||
skipOutliersCheckBox.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
try {
|
||||
updateTimingMetricGraphs();
|
||||
} catch (HealthMonitorException ex) {
|
||||
logger.log(Level.SEVERE, "Error populating timing metric panel", ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Add the date range combo box and label to the panel
|
||||
timingControlPanel.add(new JLabel(Bundle.HealthMonitorDashboard_createTimingControlPanel_maxDays()));
|
||||
timingControlPanel.add(dateComboBox);
|
||||
@@ -281,6 +317,18 @@ public class HealthMonitorDashboard {
|
||||
timingControlPanel.add(hostCheckBox);
|
||||
timingControlPanel.add(hostComboBox);
|
||||
|
||||
// Put some space between the elements
|
||||
timingControlPanel.add(Box.createHorizontalStrut(100));
|
||||
|
||||
// Add the skip outliers checkbox
|
||||
timingControlPanel.add(this.showTrendLineCheckBox);
|
||||
|
||||
// Put some space between the elements
|
||||
timingControlPanel.add(Box.createHorizontalStrut(100));
|
||||
|
||||
// Add the skip outliers checkbox
|
||||
timingControlPanel.add(this.skipOutliersCheckBox);
|
||||
|
||||
return timingControlPanel;
|
||||
}
|
||||
|
||||
@@ -324,7 +372,7 @@ public class HealthMonitorDashboard {
|
||||
|
||||
// Generate the graph
|
||||
TimingMetricGraphPanel singleTimingGraphPanel = new TimingMetricGraphPanel(intermediateTimingDataForDisplay,
|
||||
TimingMetricGraphPanel.TimingMetricType.AVERAGE, hostToDisplay, true, metricName);
|
||||
hostToDisplay, true, metricName, skipOutliersCheckBox.isSelected(), showTrendLineCheckBox.isSelected());
|
||||
singleTimingGraphPanel.setPreferredSize(new Dimension(700,200));
|
||||
|
||||
graphPanel.add(singleTimingGraphPanel);
|
||||
|
||||
@@ -58,9 +58,10 @@ class TimingMetricGraphPanel extends JPanel {
|
||||
private final int pointWidth = 4;
|
||||
private final int numberYDivisions = 10;
|
||||
private List<DatabaseTimingResult> timingResults;
|
||||
private final TimingMetricType timingMetricType;
|
||||
private final String metricName;
|
||||
private final boolean doLineGraph;
|
||||
private final boolean skipOutliers;
|
||||
private final boolean showTrendLine;
|
||||
private String yUnitString;
|
||||
private TrendLine trendLine;
|
||||
private final long MILLISECONDS_PER_DAY = 1000 * 60 * 60 * 24;
|
||||
@@ -70,11 +71,12 @@ class TimingMetricGraphPanel extends JPanel {
|
||||
private double maxMetricTime;
|
||||
private double minMetricTime;
|
||||
|
||||
TimingMetricGraphPanel(List<DatabaseTimingResult> timingResultsFull, TimingMetricType timingMetricType,
|
||||
String hostName, boolean doLineGraph, String metricName) {
|
||||
TimingMetricGraphPanel(List<DatabaseTimingResult> timingResultsFull,
|
||||
String hostName, boolean doLineGraph, String metricName, boolean skipOutliers, boolean showTrendLine) {
|
||||
|
||||
this.timingMetricType = timingMetricType;
|
||||
this.doLineGraph = doLineGraph;
|
||||
this.skipOutliers = skipOutliers;
|
||||
this.showTrendLine = showTrendLine;
|
||||
this.metricName = metricName;
|
||||
if(hostName == null || hostName.isEmpty()) {
|
||||
timingResults = timingResultsFull;
|
||||
@@ -84,85 +86,46 @@ class TimingMetricGraphPanel extends JPanel {
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
try {
|
||||
trendLine = new TrendLine(timingResults, timingMetricType);
|
||||
} catch (HealthMonitorException ex) {
|
||||
// Log it, set trendLine to null and continue on
|
||||
logger.log(Level.WARNING, "Can not generate a trend line on empty data set");
|
||||
trendLine = null;
|
||||
if(showTrendLine) {
|
||||
try {
|
||||
trendLine = new TrendLine(timingResults);
|
||||
} catch (HealthMonitorException ex) {
|
||||
// Log it, set trendLine to null and continue on
|
||||
logger.log(Level.WARNING, "Can not generate a trend line on empty data set");
|
||||
trendLine = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate these using the full data set, to make it easier to compare the results for
|
||||
// individual hosts
|
||||
calcMaxTimestamp(timingResultsFull);
|
||||
calcMinTimestamp(timingResultsFull);
|
||||
calcMaxMetricTime(timingResultsFull);
|
||||
calcMinMetricTime(timingResultsFull);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the highest metric time for the given type
|
||||
*/
|
||||
private void calcMaxMetricTime(List<DatabaseTimingResult> timingResultsFull) {
|
||||
// Find the highest of the values being graphed
|
||||
// individual hosts. Calculate the average at the same time.
|
||||
maxMetricTime = Double.MIN_VALUE;
|
||||
for (DatabaseTimingResult score : timingResultsFull) {
|
||||
// Use only the data we're graphing to determing the max
|
||||
switch (timingMetricType) {
|
||||
case MAX:
|
||||
maxMetricTime = Math.max(maxMetricTime, score.getMax());
|
||||
break;
|
||||
case MIN:
|
||||
maxMetricTime = Math.max(maxMetricTime, score.getMin());
|
||||
break;
|
||||
case AVERAGE:
|
||||
default:
|
||||
maxMetricTime = Math.max(maxMetricTime, score.getAverage());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the lowest metric time for the given type
|
||||
*/
|
||||
private void calcMinMetricTime(List<DatabaseTimingResult> timingResultsFull) {
|
||||
// Find the lowest of the values being graphed
|
||||
minMetricTime = Double.MAX_VALUE;
|
||||
for (DatabaseTimingResult result : timingResultsFull) {
|
||||
// Use only the data we're graphing to determing the min
|
||||
switch (timingMetricType) {
|
||||
case MAX:
|
||||
minMetricTime = Math.min(minMetricTime, result.getMax());
|
||||
break;
|
||||
case MIN:
|
||||
minMetricTime = Math.min(minMetricTime, result.getMin());
|
||||
break;
|
||||
case AVERAGE:
|
||||
default:
|
||||
minMetricTime = Math.min(minMetricTime, result.getAverage());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the largest timestamp in the data collection
|
||||
*/
|
||||
private void calcMaxTimestamp(List<DatabaseTimingResult> timingResultsFull) {
|
||||
maxTimestamp = Long.MIN_VALUE;
|
||||
for (DatabaseTimingResult score : timingResultsFull) {
|
||||
maxTimestamp = Math.max(maxTimestamp, score.getTimestamp());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the smallest timestamp in the data collection
|
||||
*/
|
||||
private void calcMinTimestamp(List<DatabaseTimingResult> timingResultsFull) {
|
||||
minTimestamp = Long.MAX_VALUE;
|
||||
for (DatabaseTimingResult score : timingResultsFull) {
|
||||
minTimestamp = Math.min(minTimestamp, score.getTimestamp());
|
||||
double averageMetricTime = 0.0;
|
||||
for (DatabaseTimingResult result : timingResultsFull) {
|
||||
|
||||
maxMetricTime = Math.max(maxMetricTime, result.getAverage());
|
||||
minMetricTime = Math.min(minMetricTime, result.getAverage());
|
||||
|
||||
maxTimestamp = Math.max(maxTimestamp, result.getTimestamp());
|
||||
minTimestamp = Math.min(minTimestamp, result.getTimestamp());
|
||||
|
||||
averageMetricTime += result.getAverage();
|
||||
}
|
||||
averageMetricTime = averageMetricTime / timingResultsFull.size();
|
||||
|
||||
// If we're omitting outliers, we may use a different maxMetricTime.
|
||||
// If the max time is reasonably close to the average, do nothing
|
||||
if (this.skipOutliers && (maxMetricTime > (averageMetricTime * 5))) {
|
||||
// Calculate the standard deviation
|
||||
double intermediateValue = 0.0;
|
||||
for (DatabaseTimingResult result : timingResultsFull) {
|
||||
double diff = result.getAverage() - averageMetricTime;
|
||||
intermediateValue += diff * diff;
|
||||
}
|
||||
double standardDeviation = Math.sqrt(intermediateValue / timingResultsFull.size());
|
||||
maxMetricTime = averageMetricTime + standardDeviation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,6 +221,7 @@ class TimingMetricGraphPanel extends JPanel {
|
||||
|
||||
// Create hatch marks and grid lines for y axis.
|
||||
int labelWidth;
|
||||
int positionForMetricNameLabel = 0;
|
||||
for (int i = 0; i < numberYDivisions + 1; i++) {
|
||||
int x0 = leftGraphPadding;
|
||||
int x1 = pointWidth + leftGraphPadding;
|
||||
@@ -278,13 +242,9 @@ class TimingMetricGraphPanel extends JPanel {
|
||||
g2.drawString(yLabel, x0 - labelWidth - 5, y0 + (fontMetrics.getHeight() / 2) - 3);
|
||||
|
||||
// The nicest looking alignment for this label seems to be left-aligned with the top
|
||||
// y-axis label
|
||||
// y-axis label. Save this position to be used to write the label later.
|
||||
if (i == numberYDivisions) {
|
||||
// Write the scale
|
||||
g2.setColor(Color.BLACK);
|
||||
String scaleStr = Bundle.TimingMetricGraphPanel_paintComponent_displayingTime() + yUnitString;
|
||||
String titleStr = metricName + " - " + scaleStr;
|
||||
g2.drawString(titleStr, x0 - labelWidth - 5, padding);
|
||||
positionForMetricNameLabel = x0 - labelWidth - 5;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,20 +314,7 @@ class TimingMetricGraphPanel extends JPanel {
|
||||
// Create the points to plot
|
||||
List<Point> graphPoints = new ArrayList<>();
|
||||
for (int i = 0; i < timingResults.size(); i++) {
|
||||
double metricTime;
|
||||
switch (timingMetricType) {
|
||||
case MAX:
|
||||
metricTime = timingResults.get(i).getMax();
|
||||
break;
|
||||
case MIN:
|
||||
metricTime = timingResults.get(i).getMin();
|
||||
break;
|
||||
case AVERAGE:
|
||||
default:
|
||||
metricTime = timingResults.get(i).getAverage();
|
||||
break;
|
||||
|
||||
}
|
||||
double metricTime = timingResults.get(i).getAverage();
|
||||
|
||||
int x1 = (int) ((timingResults.get(i).getTimestamp() - minValueOnXAxis) * xScale + leftGraphPadding);
|
||||
int y1 = (int) ((maxValueOnYAxis - metricTime) * yScale + topGraphPadding);
|
||||
@@ -411,7 +358,7 @@ class TimingMetricGraphPanel extends JPanel {
|
||||
|
||||
// Draw the trend line.
|
||||
// Don't draw anything if we don't have at least two data points.
|
||||
if(trendLine != null && (timingResults.size() > 1)) {
|
||||
if(showTrendLine && (trendLine != null) && (timingResults.size() > 1)) {
|
||||
double x0value = minValueOnXAxis;
|
||||
double y0value = trendLine.getExpectedValueAt(x0value);
|
||||
if (y0value < minValueOnYAxis) {
|
||||
@@ -470,15 +417,17 @@ class TimingMetricGraphPanel extends JPanel {
|
||||
g2.setColor(trendLineColor);
|
||||
g2.drawLine(x0, y0, x1, y1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The metric field we want to graph
|
||||
*/
|
||||
enum TimingMetricType {
|
||||
AVERAGE,
|
||||
MAX,
|
||||
MIN;
|
||||
|
||||
// The graph lines may have extended up past the bounds of the graph. Overwrite that
|
||||
// area with the original background color.
|
||||
g2.setColor(this.getBackground());
|
||||
g2.fillRect(leftGraphPadding, 0, graphWidth, topGraphPadding);
|
||||
|
||||
// Write the scale. Do this after we erase the top block of the graph.
|
||||
g2.setColor(Color.BLACK);
|
||||
String scaleStr = Bundle.TimingMetricGraphPanel_paintComponent_displayingTime() + yUnitString;
|
||||
String titleStr = metricName + " - " + scaleStr;
|
||||
g2.drawString(titleStr, positionForMetricNameLabel, padding);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -497,7 +446,7 @@ class TimingMetricGraphPanel extends JPanel {
|
||||
double slope;
|
||||
double yInt;
|
||||
|
||||
TrendLine(List<DatabaseTimingResult> timingResults, TimingMetricGraphPanel.TimingMetricType timingMetricType) throws HealthMonitorException {
|
||||
TrendLine(List<DatabaseTimingResult> timingResults) throws HealthMonitorException {
|
||||
|
||||
if((timingResults == null) || timingResults.isEmpty()) {
|
||||
throw new HealthMonitorException("Can not generate trend line for empty/null data set");
|
||||
@@ -511,19 +460,7 @@ class TimingMetricGraphPanel extends JPanel {
|
||||
double sumXsquared = 0;
|
||||
for(int i = 0;i < n;i++) {
|
||||
double x = timingResults.get(i).getTimestamp();
|
||||
double y;
|
||||
switch (timingMetricType) {
|
||||
case MAX:
|
||||
y = timingResults.get(i).getMax();
|
||||
break;
|
||||
case MIN:
|
||||
y = timingResults.get(i).getMin();
|
||||
break;
|
||||
case AVERAGE:
|
||||
default:
|
||||
y = timingResults.get(i).getAverage();
|
||||
break;
|
||||
}
|
||||
double y = timingResults.get(i).getAverage();
|
||||
|
||||
sumX += x;
|
||||
sumY += y;
|
||||
|
||||
@@ -62,7 +62,7 @@ public class EmbeddedFileTest extends NbTestCase {
|
||||
|
||||
@Override
|
||||
public void setUp() {
|
||||
CaseUtils.createCase(CASE_DIRECTORY_PATH, CASE_NAME);
|
||||
CaseUtils.createCase(CASE_NAME);
|
||||
ImageDSProcessor dataSourceProcessor = new ImageDSProcessor();
|
||||
IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH);
|
||||
|
||||
@@ -92,7 +92,6 @@ public class EmbeddedFileTest extends NbTestCase {
|
||||
@Override
|
||||
public void tearDown() {
|
||||
CaseUtils.closeCase();
|
||||
CaseUtils.deleteCaseDir(CASE_DIRECTORY_PATH);
|
||||
}
|
||||
|
||||
public void testEncryption() {
|
||||
|
||||
@@ -72,8 +72,7 @@ public class IngestFileFiltersTest extends NbTestCase {
|
||||
}
|
||||
|
||||
public void testBasicDir() {
|
||||
Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testBasicDir");
|
||||
CaseUtils.createCase(casePath, "testBasicDir");
|
||||
CaseUtils.createCase("testBasicDir");
|
||||
ImageDSProcessor dataSourceProcessor = new ImageDSProcessor();
|
||||
IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH);
|
||||
|
||||
@@ -115,8 +114,7 @@ public class IngestFileFiltersTest extends NbTestCase {
|
||||
}
|
||||
|
||||
public void testExtAndDirWithOneRule() {
|
||||
Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testExtAndDirWithOneRule");
|
||||
CaseUtils.createCase(casePath, "testExtAndDirWithOneRule");
|
||||
CaseUtils.createCase("testExtAndDirWithOneRule");
|
||||
ImageDSProcessor dataSourceProcessor = new ImageDSProcessor();
|
||||
IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH);
|
||||
|
||||
@@ -151,8 +149,7 @@ public class IngestFileFiltersTest extends NbTestCase {
|
||||
}
|
||||
|
||||
public void testExtAndDirWithTwoRules() {
|
||||
Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testExtAndDirWithTwoRules");
|
||||
CaseUtils.createCase(casePath, "testExtAndDirWithTwoRules");
|
||||
CaseUtils.createCase("testExtAndDirWithTwoRules");
|
||||
ImageDSProcessor dataSourceProcessor = new ImageDSProcessor();
|
||||
IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH);
|
||||
|
||||
@@ -196,8 +193,7 @@ public class IngestFileFiltersTest extends NbTestCase {
|
||||
}
|
||||
|
||||
public void testFullFileNameRule() {
|
||||
Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testFullFileNameRule");
|
||||
CaseUtils.createCase(casePath, "testFullFileNameRule");
|
||||
CaseUtils.createCase("testFullFileNameRule");
|
||||
ImageDSProcessor dataSourceProcessor = new ImageDSProcessor();
|
||||
IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH);
|
||||
|
||||
@@ -232,8 +228,7 @@ public class IngestFileFiltersTest extends NbTestCase {
|
||||
}
|
||||
|
||||
public void testCarvingWithExtRuleAndUnallocSpace() {
|
||||
Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testCarvingWithExtRuleAndUnallocSpace");
|
||||
CaseUtils.createCase(casePath, "testCarvingWithExtRuleAndUnallocSpace");
|
||||
CaseUtils.createCase("testCarvingWithExtRuleAndUnallocSpace");
|
||||
ImageDSProcessor dataSourceProcessor = new ImageDSProcessor();
|
||||
IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH);
|
||||
|
||||
@@ -281,8 +276,7 @@ public class IngestFileFiltersTest extends NbTestCase {
|
||||
}
|
||||
|
||||
public void testCarvingNoUnallocatedSpace() {
|
||||
Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testCarvingNoUnallocatedSpace");
|
||||
CaseUtils.createCase(casePath, "testCarvingNoUnallocatedSpace");
|
||||
CaseUtils.createCase("testCarvingNoUnallocatedSpace");
|
||||
ImageDSProcessor dataSourceProcessor = new ImageDSProcessor();
|
||||
IngestUtils.addDataSource(dataSourceProcessor, IMAGE_PATH);
|
||||
|
||||
@@ -315,8 +309,7 @@ public class IngestFileFiltersTest extends NbTestCase {
|
||||
}
|
||||
|
||||
public void testEmbeddedModule() {
|
||||
Path casePath = Paths.get(System.getProperty("java.io.tmpdir"), "testEmbeddedModule");
|
||||
CaseUtils.createCase(casePath, "testEmbeddedModule");
|
||||
CaseUtils.createCase("testEmbeddedModule");
|
||||
LocalFilesDSProcessor dataSourceProcessor = new LocalFilesDSProcessor();
|
||||
IngestUtils.addDataSource(dataSourceProcessor, ZIPFILE_PATH);
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@ import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
|
||||
import org.sleuthkit.autopsy.casemodule.services.FileManager;
|
||||
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
|
||||
import org.sleuthkit.autopsy.ingest.IngestJobSettings.IngestType;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleFactory;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
|
||||
import org.sleuthkit.autopsy.ingest.IngestModuleTemplate;
|
||||
import org.sleuthkit.autopsy.testutils.CaseUtils;
|
||||
import org.sleuthkit.autopsy.testutils.IngestUtils;
|
||||
@@ -49,18 +51,10 @@ import org.sleuthkit.datamodel.VolumeSystem;
|
||||
public class EncryptionDetectionTest extends NbTestCase {
|
||||
|
||||
private static final String BITLOCKER_CASE_NAME = "testBitlockerEncryption";
|
||||
private static final String PASSWORD_CASE_NAME = "testPasswordProtection";
|
||||
|
||||
private static final Path BITLOCKER_CASE_DIRECTORY_PATH = Paths.get(System.getProperty("java.io.tmpdir"), BITLOCKER_CASE_NAME);
|
||||
private static final Path PASSWORD_CASE_DIRECTORY_PATH = Paths.get(System.getProperty("java.io.tmpdir"), PASSWORD_CASE_NAME);
|
||||
|
||||
private final Path BITLOCKER_IMAGE_PATH = Paths.get(this.getDataDir().toString(), "encryption_detection_bitlocker_test.vhd");
|
||||
private final Path PASSWORD_IMAGE_PATH = Paths.get(this.getDataDir().toString(), "password_detection_test.img");
|
||||
|
||||
private static final String PASSWORD_DETECTION_CASE_NAME = "PasswordDetectionTest";
|
||||
private static final String VERACRYPT_DETECTION_CASE_NAME = "VeraCryptDetectionTest";
|
||||
|
||||
private final Path PASSWORD_DETECTION_IMAGE_PATH = Paths.get(this.getDataDir().toString(), "password_detection_test.img");
|
||||
private static final String VERACRYPT_DETECTION_CASE_NAME = "VeraCryptDetectionTest";
|
||||
private final Path VERACRYPT_DETECTION_IMAGE_PATH = Paths.get(this.getDataDir().toString(), "veracrypt_detection_test.vhd");
|
||||
|
||||
public static Test suite() {
|
||||
@@ -84,7 +78,7 @@ public class EncryptionDetectionTest extends NbTestCase {
|
||||
*/
|
||||
public void testBitlockerEncryption() {
|
||||
try {
|
||||
CaseUtils.createCase(BITLOCKER_CASE_DIRECTORY_PATH, BITLOCKER_CASE_NAME);
|
||||
CaseUtils.createCase(BITLOCKER_CASE_NAME);
|
||||
ImageDSProcessor dataSourceProcessor = new ImageDSProcessor();
|
||||
IngestUtils.addDataSource(dataSourceProcessor, BITLOCKER_IMAGE_PATH);
|
||||
Case openCase = Case.getCurrentCaseThrows();
|
||||
|
||||
@@ -37,13 +37,6 @@ import org.sleuthkit.autopsy.casemodule.CaseDetails;
|
||||
*/
|
||||
public final class CaseUtils {
|
||||
|
||||
/**
|
||||
* CaseUtils constructor. Since this class is not meant to allow for
|
||||
* instantiation, this constructor is 'private'.
|
||||
*/
|
||||
private CaseUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a case case directory and case for the given case name.
|
||||
*
|
||||
@@ -105,10 +98,13 @@ public final class CaseUtils {
|
||||
if (!caseDirectory.exists()) {
|
||||
return;
|
||||
}
|
||||
//We should determine whether the test fails or passes where this is called
|
||||
//It will usually be a test failure when the case can not be deleted
|
||||
//but sometimes we might be alright if we are unable to delete it.
|
||||
FileUtils.deleteDirectory(caseDirectory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor to prevent utility class instantiation.
|
||||
*/
|
||||
private CaseUtils() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*! \page embedded_file_extractor_page Embedded File Extraction Module
|
||||
|
||||
What Does It Do
|
||||
========
|
||||
\section embedded_files_overview What Does It Do
|
||||
|
||||
|
||||
The Embedded File Extractor module opens ZIP, RAR, other archive formats, Doc, Docx, PPT, PPTX, XLS, and XLSX and sends the derived files from those files back through the ingest pipeline for analysis.
|
||||
|
||||
@@ -9,21 +9,17 @@ This module expands archive files to enable Autopsy to analyze all files on the
|
||||
|
||||
NOTE: Certain media content embedded inside Doc, Docx, PPT, PPTX, XLS, and XLSX might not be extracted.
|
||||
|
||||
Configuration
|
||||
=======
|
||||
\section embedded_files_config Configuration
|
||||
|
||||
There is no configuration required.
|
||||
|
||||
Using the Module
|
||||
======
|
||||
\section embedded_files_usage Using the Module
|
||||
Select the checkbox in the Ingest Modules settings screen to enable the Archive Extractor.
|
||||
|
||||
Ingest Settings
|
||||
------
|
||||
\subsection embedded_files_settings Ingest Settings
|
||||
There are no runtime ingest settings required.
|
||||
|
||||
Seeing Results
|
||||
------
|
||||
\subsection embedded_files_results Seeing Results
|
||||
Each file extracted shows up in the data source tree view as a child of the archive containing it,
|
||||
|
||||
\image html zipped_children_1.PNG
|
||||
@@ -32,4 +28,18 @@ Each file extracted shows up in the data source tree view as a child of the arch
|
||||
and as an archive under "Views", "File Types", "Archives".
|
||||
\image html zipped_children_2.PNG
|
||||
|
||||
\subsection embedded_files_encryption Encrypted Archives
|
||||
|
||||
When the Embedded File Extractor module encounters an encrypted archive, it will generate a warning bubble in the bottom right of the main screen:
|
||||
|
||||
\image html zipped_encryption_detected.png
|
||||
|
||||
After ingest, you can attempt to decrypt these archives if you know the password. Find the archive (either in the \ref tree_viewer_page "tree view" or \ref result_viewer_page "result view") and right-click on it, then select "Unzip contents with password".
|
||||
|
||||
\image html zipped_context_menu.png
|
||||
|
||||
After entering the password, you can select which ingest modules to run on the newly extracted files. When finished, you can browse to the encrypted archive in the tree view to see the newly extracted files. If the archive was already open in the tree, you may have to close and open the case in order to see the new data.
|
||||
|
||||
\image html zipped_tree.png
|
||||
|
||||
*/
|
||||
|
||||
@@ -20,8 +20,30 @@ The middle column displays each account, its device and type, and the number of
|
||||
|
||||
Selecting an account in the middle column will bring up the messages for that account in the right hand column. Here data about each message is displayed in the top section, and the messages itself can be seen in the bottom section (if applicable).
|
||||
|
||||
The middle column and the right hand column both have a \ref ui_quick_search feature which can be used to quickly find a visible item in their section's table.
|
||||
|
||||
\image html cvt_messages.png
|
||||
|
||||
The middle column and the right hand column both have a \ref ui_quick_search feature which can be used to quickly find a visible item in their section's table.
|
||||
|
||||
\section cvt_viz Visualization
|
||||
|
||||
The Visualize tab in the middle panel will show a graph of one or more accounts selected in the Browse tab.
|
||||
|
||||
To start, right click the first account you want to view.
|
||||
|
||||
\image html cvt_select_account.png
|
||||
|
||||
There are two options, which are equivalent when no accounts have previously been selected:
|
||||
<ul>
|
||||
<li>Add Selected Account to Visualization - Adds this account and its connections to the graph
|
||||
<li>Visualize Only Selected Account - Clears the graph and only displays the connections for this account
|
||||
</ul>
|
||||
|
||||
After selecting either option, the middle tab will switch to the Visualize view and the graph will be displayed.
|
||||
|
||||
\image html cvt_visualize.png
|
||||
|
||||
The options at the top allow you to clear the graph, try different graph layouts, and resize the graph. The nodes in the graph can be dragged around and nodes and edges can be selected to display their messages or relationships in the right side tab. For example, in the image below the link between two email addresses has been selected so the Messages viewer is displaying the single email between those two email addresses.
|
||||
|
||||
\image html cvt_links.png
|
||||
|
||||
*/
|
||||
|
After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 112 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 120 KiB |