Autopsy  4.4
Graphical digital forensics platform for The Sleuth Kit and other tools.
SampleExecutableDataSourceIngestModule.java
Go to the documentation of this file.
1 /*
2  * Sample module in the public domain. Feel free to use this as a template
3  * for your modules.
4  *
5  * Contact: Brian Carrier [carrier <at> sleuthkit [dot] org]
6  *
7  * This is free and unencumbered software released into the public domain.
8  *
9  * Anyone is free to copy, modify, publish, use, compile, sell, or
10  * distribute this software, either in source code form or as a compiled
11  * binary, for any purpose, commercial or non-commercial, and by any
12  * means.
13  *
14  * In jurisdictions that recognize copyright laws, the author or authors
15  * of this software dedicate any and all copyright interest in the
16  * software to the public domain. We make this dedication for the benefit
17  * of the public at large and to the detriment of our heirs and
18  * successors. We intend this dedication to be an overt act of
19  * relinquishment in perpetuity of all present and future rights to this
20  * software under copyright law.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
26  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28  * OTHER DEALINGS IN THE SOFTWARE.
29  */
30 package org.sleuthkit.autopsy.examples;
31 
32 import java.io.File;
33 import java.io.FileOutputStream;
34 import java.io.IOException;
35 import java.util.ArrayList;
36 import java.util.List;
37 import java.util.logging.Level;
38 import javax.xml.parsers.DocumentBuilder;
39 import javax.xml.parsers.DocumentBuilderFactory;
40 import javax.xml.parsers.ParserConfigurationException;
41 import javax.xml.transform.Transformer;
42 import javax.xml.transform.TransformerConfigurationException;
43 import javax.xml.transform.TransformerException;
44 import javax.xml.transform.TransformerFactory;
45 import javax.xml.transform.dom.DOMSource;
46 import javax.xml.transform.stream.StreamResult;
61 import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
62 import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
63 import org.sleuthkit.datamodel.Content;
64 import org.sleuthkit.datamodel.Image;
65 import org.w3c.dom.Document;
66 import org.w3c.dom.Element;
67 
74 
76  private static final String moduleName = SampleExecutableIngestModuleFactory.getModuleName();
77  private final String fileInCaseDatabase = "/WINDOWS/system32/ntmsapi.dll"; // Probably
79  private String outputDirPath;
80  private String derivedFileInCaseDatabase;
81 
82  @Override
83  public void startUp(IngestJobContext context) throws IngestModuleException {
84  this.context = context;
85  if (refCounter.incrementAndGet(context.getJobId()) == 1) {
86  // Create an output directory for this job.
87  outputDirPath = Case.getCurrentCase().getModuleDirectory() + File.separator + moduleName; //NON-NLS
88  File outputDir = new File(outputDirPath);
89  if (outputDir.exists() == false) {
90  outputDir.mkdirs();
91  }
92  }
93  }
94 
95  @Override
96  public ProcessResult process(Content dataSource, DataSourceIngestModuleProgress progressBar) {
97  if (refCounter.get(context.getJobId()) == 1) {
98  try {
99  // There will be two tasks: data source analysis and import of
100  // the results of the analysis.
101  progressBar.switchToDeterminate(2);
102 
103  // Do the analysis. The following sample code could be used to
104  // run an executable. In this case the executable would take
105  // two command line arguments, the path to the data source to be
106  // analyzed and the path to a results file to be generated. The
107  // results file would be an an XML file (see org.sleuthkit.autopsy.externalresults.autopsy_external_results.xsd)
108  // with instructions for the import of blackboard artifacts,
109  // derived files, and reports generated by the analysis. In this
110  // sample ingest module, the generation of the analysis results is
111  // simulated.
112  String resultsFilePath = outputDirPath + File.separator + String.format("job_%d_results.xml", context.getJobId());
113  boolean haveRealExecutable = false;
114  if (haveRealExecutable) {
115  if (dataSource instanceof Image) {
116  Image image = (Image) dataSource;
117  String dataSourcePath = image.getPaths()[0];
118  List<String> commandLine = new ArrayList<>();
119  commandLine.add("some.exe");
120  commandLine.add(dataSourcePath);
121  commandLine.add(resultsFilePath);
122  ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
123  ExecUtil.execute(processBuilder, new DataSourceIngestModuleProcessTerminator(context));
124  } // not a disk image
125  else {
126  return ProcessResult.OK;
127  }
128  } else {
129  generateSimulatedResults(resultsFilePath);
130  }
131  progressBar.progress(1);
132 
133  // Import the results of the analysis.
134  ExternalResultsXMLParser resultsParser = new ExternalResultsXMLParser(dataSource, resultsFilePath);
135  ExternalResults results = resultsParser.parse();
136  List<ErrorInfo> errors = resultsParser.getErrorInfo();
138  errors.addAll(importer.importResults(results));
139  for (ErrorInfo errorInfo : errors) {
140  IngestServices.getInstance().postMessage(IngestMessage.createErrorMessage(moduleName, "External Results Import Error", errorInfo.getMessage()));
141  }
142  progressBar.progress(2);
143  } catch (ParserConfigurationException | TransformerException | IOException ex) {
144  Logger logger = IngestServices.getInstance().getLogger(moduleName);
145  logger.log(Level.SEVERE, "Failed to simulate analysis and results import", ex); //NON-NLS
146  return ProcessResult.ERROR;
147  }
148  }
149  return ProcessResult.OK;
150  }
151 
152  private void generateSimulatedResults(String resultsFilePath) throws ParserConfigurationException, IOException, TransformerConfigurationException, TransformerException {
153  List<String> derivedFilePaths = generateSimulatedDerivedFiles();
154  List<String> reportFilePaths = generateSimulatedReports();
155  generateSimulatedResultsFile(derivedFilePaths, reportFilePaths, resultsFilePath);
156  }
157 
158  private List<String> generateSimulatedDerivedFiles() throws IOException {
159  List<String> filePaths = new ArrayList<>();
160  String fileContents = "This is a simulated derived file.";
161  for (int i = 0; i < 2; ++i) {
162  String fileName = String.format("job_%d_derived_file_%d.txt", context.getJobId(), i);
163  filePaths.add(generateFile(fileName, fileContents.getBytes()));
164  if (i == 0) {
165  this.derivedFileInCaseDatabase = this.fileInCaseDatabase + "/" + fileName;
166  }
167  }
168  return filePaths;
169  }
170 
171  private List<String> generateSimulatedReports() throws IOException {
172  List<String> filePaths = new ArrayList<>();
173  String fileContents = "This is a simulated report.";
174  for (int i = 0; i < 2; ++i) {
175  String fileName = String.format("job_%d_report_%d.txt", context.getJobId(), i);
176  filePaths.add(generateFile(fileName, fileContents.getBytes()));
177  }
178  return filePaths;
179  }
180 
181  private String generateFile(String fileName, byte[] fileContents) throws IOException {
182  String filePath = outputDirPath + File.separator + fileName;
183  File file = new File(filePath);
184  if (!file.exists()) {
185  file.createNewFile();
186  }
187  try (FileOutputStream fileStream = new FileOutputStream(file)) {
188  fileStream.write(fileContents);
189  fileStream.flush();
190  }
191  return filePath;
192  }
193 
194  private void generateSimulatedResultsFile(List<String> derivedFilePaths, List<String> reportPaths, String resultsFilePath) throws ParserConfigurationException, TransformerConfigurationException, TransformerException {
195  // SAMPLE GENERATED BY THE CODE BELOW:
196  //
197  // <?xml version="1.0" encoding="UTF-8" standalone="no"?>
198  // <autopsy_results>
199  // <derived_files>
200  // <derived_file>
201  // <local_path>C:\cases\Small\ModuleOutput\Sample Executable Ingest Module\job_1_derived_file_0.txt</local_path>
202  // <parent_file>/WINDOWS/system32/ntmsapi.dll</parent_file>
203  // </derived_file>
204  // <derived_file>
205  // <local_path>C:\cases\Small\ModuleOutput\Sample Executable Ingest Module\job_1_derived_file_1.txt</local_path>
206  // <parent_file>/WINDOWS/system32/ntmsapi.dll/job_1_derived_file_0.txt</parent_file>
207  // </derived_file>
208  // </derived_files>
209  // <artifacts>
210  // <artifact type="TSK_INTERESTING_FILE_HIT">
211  // <source_file>/WINDOWS/system32/ntmsapi.dll</source_file>
212  // <attribute type="TSK_SET_NAME">
213  // <value>SampleInterestingFilesSet</value>
214  // <source_module>Sample Executable Ingest Module</source_module>
215  // </attribute>
216  // </artifact>
217  // <artifact type="SampleArtifactType">
218  // <source_file>/WINDOWS/system32/ntmsapi.dll/job_1_derived_file_0.txt</source_file>
219  // <attribute type="SampleArtifactAttributeType">
220  // <value type="text">One</value>
221  // </attribute>
222  // <attribute type="SampleArtifactAttributeType">
223  // <value type="int32">2</value>
224  // </attribute>
225  // <attribute type="SampleArtifactAttributeType">
226  // <value type="int64">3</value>
227  // </attribute>
228  // <attribute type="SampleArtifactAttributeType">
229  // <value type="double">4.0</value>
230  // </attribute>
231  // </artifact>
232  // </artifacts>
233  // <reports>
234  // <report>
235  // <local_path>C:\cases\Small\ModuleOutput\Sample Executable Ingest Module\job_1_report_0.txt</local_path>
236  // <source_module>Sample Executable Ingest Module</source_module>
237  // <report_name>Sample Report</report_name>
238  // </report>
239  // <report>
240  // <local_path>C:\cases\Small\ModuleOutput\Sample Executable Ingest Module\job_1_report_1.txt</local_path>
241  // <source_module>Sample Executable Ingest Module</source_module>
242  // </report>
243  // </reports>
244  // </autopsy_results>
245 
246  // Create the XML DOM document and the root element.
247  DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
248  DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
249  Document doc = docBuilder.newDocument();
250  Element rootElement = doc.createElement(ExternalResultsXMLParser.TagNames.ROOT_ELEM.toString());
251  doc.appendChild(rootElement);
252 
253  // Add a derived files list element to the root element.
254  Element derivedFilesListElement = doc.createElement(ExternalResultsXMLParser.TagNames.DERIVED_FILES_LIST_ELEM.toString());
255  rootElement.appendChild(derivedFilesListElement);
256 
257  // Add derived file elements to the derived files list element. Each
258  // file element gets required local path and parent file child elements.
259  // Note that the local path of the derived file must be to a location in
260  // the case directory or a subdirectory of the case directory and the
261  // parent file must be specified using the path format used in the case
262  // database, e.g., /WINDOWS/system32/ntmsapi.dll, where volume, file
263  // system, etc. are not in the path.
264  for (int i = 0; i < derivedFilePaths.size(); ++i) {
265  String filePath = derivedFilePaths.get(i);
266  Element derivedFileElement = doc.createElement(ExternalResultsXMLParser.TagNames.DERIVED_FILE_ELEM.toString());
267  derivedFilesListElement.appendChild(derivedFileElement);
268  Element localPathElement = doc.createElement(ExternalResultsXMLParser.TagNames.LOCAL_PATH_ELEM.toString());
269  localPathElement.setTextContent(filePath);
270  derivedFileElement.appendChild(localPathElement);
271  Element parentPathElement = doc.createElement(ExternalResultsXMLParser.TagNames.PARENT_FILE_ELEM.toString());
272  if (i == 0) {
273  parentPathElement.setTextContent(this.fileInCaseDatabase);
274  } else {
275  parentPathElement.setTextContent(this.derivedFileInCaseDatabase);
276  }
277  derivedFileElement.appendChild(parentPathElement);
278  }
279 
280  // Add an artifacts list element to the root element.
281  Element artifactsListElement = doc.createElement(ExternalResultsXMLParser.TagNames.ARTIFACTS_LIST_ELEM.toString());
282  rootElement.appendChild(artifactsListElement);
283 
284  // Add an artifact element to the artifacts list element with the required
285  // artifact type attribute. A standard artifact type is used as the type
286  // attribute of this artifact element.
287  Element artifactElement = doc.createElement(ExternalResultsXMLParser.TagNames.ARTIFACT_ELEM.toString());
288  artifactElement.setAttribute(ExternalResultsXMLParser.AttributeNames.TYPE_ATTR.toString(), ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getLabel());
289  artifactsListElement.appendChild(artifactElement);
290 
291  // Add the required source file element to the artifact element. Note
292  // that source file must be either the local path of a derived file or a
293  // file in the case database.
294  Element fileElement = doc.createElement(ExternalResultsXMLParser.TagNames.SOURCE_FILE_ELEM.toString());
295  fileElement.setTextContent(this.fileInCaseDatabase);
296  artifactElement.appendChild(fileElement);
297 
298  // Add an artifact attribute element to the artifact element. A standard
299  // artifact attribute type is used as the required type XML attribute of
300  // the artifact attribute element.
301  Element artifactAttrElement = doc.createElement(ExternalResultsXMLParser.TagNames.ATTRIBUTE_ELEM.toString());
302  artifactAttrElement.setAttribute(ExternalResultsXMLParser.AttributeNames.TYPE_ATTR.toString(), ATTRIBUTE_TYPE.TSK_SET_NAME.getLabel());
303  artifactElement.appendChild(artifactAttrElement);
304 
305  // Add the required value element to the artifact attribute element,
306  // with an optional type XML attribute of ExternalXML.VALUE_TYPE_TEXT,
307  // which is the default.
308  Element artifactAttributeValueElement = doc.createElement(ExternalResultsXMLParser.TagNames.VALUE_ELEM.toString());
309  artifactAttributeValueElement.setTextContent("SampleInterestingFilesSet");
310  artifactAttrElement.appendChild(artifactAttributeValueElement);
311 
312  // Add an optional source module element to the artifact attribute
313  // element.
314  Element artifactAttrSourceElement = doc.createElement(ExternalResultsXMLParser.TagNames.SOURCE_MODULE_ELEM.toString());
315  artifactAttrSourceElement.setTextContent(moduleName);
316  artifactAttrElement.appendChild(artifactAttrSourceElement);
317 
318  // Add an artifact element with a user-defined type.
319  artifactElement = doc.createElement(ExternalResultsXMLParser.TagNames.ARTIFACT_ELEM.toString());
320  artifactElement.setAttribute(ExternalResultsXMLParser.AttributeNames.TYPE_ATTR.toString(), "SampleArtifactType");
321  artifactsListElement.appendChild(artifactElement);
322 
323  // Add the required source file element.
324  fileElement = doc.createElement(ExternalResultsXMLParser.TagNames.SOURCE_FILE_ELEM.toString());
325  fileElement.setTextContent(this.derivedFileInCaseDatabase);
326  artifactElement.appendChild(fileElement);
327 
328  // Add artifact attribute elements with user-defined types to the
329  // artifact element, adding value elements of assorted types.
330  for (int i = 0; i < 5; ++i) {
331  artifactAttrElement = doc.createElement(ExternalResultsXMLParser.TagNames.ATTRIBUTE_ELEM.toString());
332  artifactAttrElement.setAttribute(ExternalResultsXMLParser.AttributeNames.TYPE_ATTR.toString(), "SampleArtifactAttributeType" + i);
333  artifactElement.appendChild(artifactAttrElement);
334  artifactAttributeValueElement = doc.createElement(ExternalResultsXMLParser.TagNames.VALUE_ELEM.toString());
335  switch (i) {
336  case 0:
337  artifactAttributeValueElement.setAttribute(ExternalResultsXMLParser.AttributeNames.TYPE_ATTR.toString(), ExternalResultsXMLParser.AttributeValues.VALUE_TYPE_TEXT.toString());
338  artifactAttributeValueElement.setTextContent("One");
339  break;
340  case 1:
341  artifactAttributeValueElement.setAttribute(ExternalResultsXMLParser.AttributeNames.TYPE_ATTR.toString(), ExternalResultsXMLParser.AttributeValues.VALUE_TYPE_INT32.toString());
342  artifactAttributeValueElement.setTextContent("2");
343  break;
344  case 2:
345  artifactAttributeValueElement.setAttribute(ExternalResultsXMLParser.AttributeNames.TYPE_ATTR.toString(), ExternalResultsXMLParser.AttributeValues.VALUE_TYPE_INT64.toString());
346  artifactAttributeValueElement.setTextContent("3");
347  break;
348  case 3:
349  artifactAttributeValueElement.setAttribute(ExternalResultsXMLParser.AttributeNames.TYPE_ATTR.toString(), ExternalResultsXMLParser.AttributeValues.VALUE_TYPE_DOUBLE.toString());
350  artifactAttributeValueElement.setTextContent("4.0");
351  break;
352  case 4:
353  artifactAttributeValueElement.setAttribute(ExternalResultsXMLParser.AttributeNames.TYPE_ATTR.toString(), ExternalResultsXMLParser.AttributeValues.VALUE_TYPE_DATETIME.toString());
354  artifactAttributeValueElement.setTextContent("7023372036854775839");
355  break;
356  }
357  artifactAttrElement.appendChild(artifactAttributeValueElement);
358  }
359 
360  // Add a reports list element to the root element.
361  Element reportsListElement = doc.createElement(ExternalResultsXMLParser.TagNames.REPORTS_LIST_ELEM.toString());
362  rootElement.appendChild(reportsListElement);
363 
364  // Add report elements to the reports list element. Each report element
365  // gets required local path and source module child elements. There is
366  // also an optional report name element. Note that the local path of the
367  // report must be to a location in the case directory or a subdirectory
368  // of the case directory and the parent file must be specified using the
369  // path format used in the case database, e.g., /WINDOWS/system32/ntmsapi.dll,
370  // where volume, file system, etc. are not in the path.
371  for (int i = 0; i < reportPaths.size(); ++i) {
372  String reportPath = reportPaths.get(i);
373  Element reportElement = doc.createElement(ExternalResultsXMLParser.TagNames.REPORT_ELEM.toString());
374  reportsListElement.appendChild(reportElement);
375  Element reportPathElement = doc.createElement(ExternalResultsXMLParser.TagNames.LOCAL_PATH_ELEM.toString());
376  reportPathElement.setTextContent(reportPath);
377  reportElement.appendChild(reportPathElement);
378  Element reportSourceModuleElement = doc.createElement(ExternalResultsXMLParser.TagNames.SOURCE_MODULE_ELEM.toString());
379  reportSourceModuleElement.setTextContent(moduleName);
380  reportElement.appendChild(reportSourceModuleElement);
381  if (i == 0) {
382  Element reportNameElement = doc.createElement(ExternalResultsXMLParser.TagNames.REPORT_NAME_ELEM.toString());
383  reportNameElement.setTextContent("Sample Report");
384  reportElement.appendChild(reportNameElement);
385  }
386  }
387 
388  TransformerFactory transformerFactory = TransformerFactory.newInstance();
389  Transformer transformer = transformerFactory.newTransformer();
390  DOMSource source = new DOMSource(doc);
391  StreamResult result = new StreamResult(new File(resultsFilePath));
392  transformer.transform(source, result);
393  }
394 }
static int execute(ProcessBuilder processBuilder)
Definition: ExecUtil.java:118
static IngestMessage createErrorMessage(String source, String subject, String detailsHtml)
void generateSimulatedResultsFile(List< String > derivedFilePaths, List< String > reportPaths, String resultsFilePath)
Logger getLogger(String moduleDisplayName)
void postMessage(final IngestMessage message)
ProcessResult process(Content dataSource, DataSourceIngestModuleProgress progressBar)
static synchronized IngestServices getInstance()

Copyright © 2012-2016 Basis Technology. Generated on: Tue Jun 13 2017
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.