Autopsy  4.11.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
ExtractRegistry.java
Go to the documentation of this file.
1 /*
2  *
3  * Autopsy Forensic Browser
4  *
5  * Copyright 2012-2019 Basis Technology Corp.
6  *
7  * Copyright 2012 42six Solutions.
8  * Contact: aebadirad <at> 42six <dot> com
9  * Project Contact/Architect: carrier <at> sleuthkit <dot> org
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  * http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  */
23 package org.sleuthkit.autopsy.recentactivity;
24 
25 import java.io.BufferedReader;
26 import java.io.File;
27 import java.io.FileInputStream;
28 import java.io.FileNotFoundException;
29 import java.io.FileReader;
30 import java.io.FileWriter;
31 import java.io.IOException;
32 import java.io.StringReader;
33 import java.text.ParseException;
34 import java.text.SimpleDateFormat;
35 import java.util.logging.Level;
36 import javax.xml.parsers.DocumentBuilder;
37 import javax.xml.parsers.DocumentBuilderFactory;
38 import javax.xml.parsers.ParserConfigurationException;
39 import org.openide.modules.InstalledFileLocator;
40 import org.openide.util.NbBundle;
48 import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
49 import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
50 import org.w3c.dom.Document;
51 import org.w3c.dom.Element;
52 import org.w3c.dom.Node;
53 import org.w3c.dom.NodeList;
54 import org.xml.sax.InputSource;
55 import org.xml.sax.SAXException;
56 import java.nio.file.Path;
57 import java.util.ArrayList;
58 import java.util.List;
59 import java.util.Collection;
60 import java.util.HashMap;
61 import java.util.Map;
62 import java.util.Scanner;
63 import java.util.Set;
64 import java.util.HashSet;
65 import static java.util.TimeZone.getTimeZone;
66 import org.openide.util.Lookup;
72 import org.sleuthkit.datamodel.AbstractFile;
73 import org.sleuthkit.datamodel.BlackboardArtifact;
74 import org.sleuthkit.datamodel.BlackboardAttribute;
75 import org.sleuthkit.datamodel.Content;
76 import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
77 import org.sleuthkit.datamodel.Report;
78 import org.sleuthkit.datamodel.TskCoreException;
79 
86 @NbBundle.Messages({
87  "RegRipperNotFound=Autopsy RegRipper executable not found.",
88  "RegRipperFullNotFound=Full version RegRipper executable not found.",
89  "Progress_Message_Analyze_Registry=Analyzing Registry Files"
90 })
91 class ExtractRegistry extends Extract {
92 
93  final private static UsbDeviceIdMapper USB_MAPPER = new UsbDeviceIdMapper();
94  final private static String RIP_EXE = "rip.exe";
95  final private static String RIP_PL = "rip.pl";
96  final private static int MS_IN_SEC = 1000;
97  final private static String NEVER_DATE = "Never";
98  final private static String SECTION_DIVIDER = "-------------------------";
99  final private static Logger logger = Logger.getLogger(ExtractRegistry.class.getName());
100  private final List<String> rrCmd = new ArrayList<>();
101  private final List<String> rrFullCmd = new ArrayList<>();
102  private final Path rrHome; // Path to the Autopsy version of RegRipper
103  private final Path rrFullHome; // Path to the full version of RegRipper
104  private Content dataSource;
105  private IngestJobContext context;
106 
107  ExtractRegistry() throws IngestModuleException {
108  moduleName = NbBundle.getMessage(ExtractIE.class, "ExtractRegistry.moduleName.text");
109 
110  final File rrRoot = InstalledFileLocator.getDefault().locate("rr", ExtractRegistry.class.getPackage().getName(), false); //NON-NLS
111  if (rrRoot == null) {
112  throw new IngestModuleException(Bundle.RegRipperNotFound());
113  }
114 
115  final File rrFullRoot = InstalledFileLocator.getDefault().locate("rr-full", ExtractRegistry.class.getPackage().getName(), false); //NON-NLS
116  if (rrFullRoot == null) {
117  throw new IngestModuleException(Bundle.RegRipperFullNotFound());
118  }
119 
120  String executableToRun = RIP_EXE;
121  if (!PlatformUtil.isWindowsOS()) {
122  executableToRun = RIP_PL;
123  }
124  rrHome = rrRoot.toPath();
125  String rrPath = rrHome.resolve(executableToRun).toString();
126  rrFullHome = rrFullRoot.toPath();
127 
128  if (!(new File(rrPath).exists())) {
129  throw new IngestModuleException(Bundle.RegRipperNotFound());
130  }
131  String rrFullPath = rrFullHome.resolve(executableToRun).toString();
132  if (!(new File(rrFullPath).exists())) {
133  throw new IngestModuleException(Bundle.RegRipperFullNotFound());
134  }
135  if (PlatformUtil.isWindowsOS()) {
136  rrCmd.add(rrPath);
137  rrFullCmd.add(rrFullPath);
138  } else {
139  String perl;
140  File usrBin = new File("/usr/bin/perl");
141  File usrLocalBin = new File("/usr/local/bin/perl");
142  if (usrBin.canExecute() && usrBin.exists() && !usrBin.isDirectory()) {
143  perl = "/usr/bin/perl";
144  } else if (usrLocalBin.canExecute() && usrLocalBin.exists() && !usrLocalBin.isDirectory()) {
145  perl = "/usr/local/bin/perl";
146  } else {
147  throw new IngestModuleException("perl not found in your system");
148  }
149  rrCmd.add(perl);
150  rrCmd.add(rrPath);
151  rrFullCmd.add(perl);
152  rrFullCmd.add(rrFullPath);
153  }
154  }
155 
159  private List<AbstractFile> findRegistryFiles() {
160  List<AbstractFile> allRegistryFiles = new ArrayList<>();
161  org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
162 
163  // find the user-specific ntuser-dat files
164  try {
165  allRegistryFiles.addAll(fileManager.findFiles(dataSource, "ntuser.dat")); //NON-NLS
166  } catch (TskCoreException ex) {
167  logger.log(Level.WARNING, "Error fetching 'ntuser.dat' file."); //NON-NLS
168  }
169 
170  // find the system hives'
171  String[] regFileNames = new String[]{"system", "software", "security", "sam"}; //NON-NLS
172  for (String regFileName : regFileNames) {
173  try {
174  allRegistryFiles.addAll(fileManager.findFiles(dataSource, regFileName, "/system32/config")); //NON-NLS
175  } catch (TskCoreException ex) {
176  String msg = NbBundle.getMessage(this.getClass(),
177  "ExtractRegistry.findRegFiles.errMsg.errReadingFile", regFileName);
178  logger.log(Level.WARNING, msg);
179  this.addErrorMessage(this.getName() + ": " + msg);
180  }
181  }
182  return allRegistryFiles;
183  }
184 
189  private void analyzeRegistryFiles() {
190  List<AbstractFile> allRegistryFiles = findRegistryFiles();
191 
192  // open the log file
193  FileWriter logFile = null;
194  try {
195  logFile = new FileWriter(RAImageIngestModule.getRAOutputPath(currentCase, "reg") + File.separator + "regripper-info.txt"); //NON-NLS
196  } catch (IOException ex) {
197  logger.log(Level.SEVERE, null, ex);
198  }
199 
200  for (AbstractFile regFile : allRegistryFiles) {
201  String regFileName = regFile.getName();
202  long regFileId = regFile.getId();
203  String regFileNameLocal = RAImageIngestModule.getRATempPath(currentCase, "reg") + File.separator + regFileName;
204  String outputPathBase = RAImageIngestModule.getRAOutputPath(currentCase, "reg") + File.separator + regFileName + "-regripper-" + Long.toString(regFileId); //NON-NLS
205  File regFileNameLocalFile = new File(regFileNameLocal);
206  try {
207  ContentUtils.writeToFile(regFile, regFileNameLocalFile, context::dataSourceIngestIsCancelled);
208  } catch (ReadContentInputStreamException ex) {
209  logger.log(Level.WARNING, String.format("Error reading registry file '%s' (id=%d).",
210  regFile.getName(), regFileId), ex); //NON-NLS
211  this.addErrorMessage(
212  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
213  this.getName(), regFileName));
214  continue;
215  } catch (IOException ex) {
216  logger.log(Level.SEVERE, String.format("Error writing temp registry file '%s' for registry file '%s' (id=%d).",
217  regFileNameLocal, regFile.getName(), regFileId), ex); //NON-NLS
218  this.addErrorMessage(
219  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
220  this.getName(), regFileName));
221  continue;
222  }
223 
224  if (context.dataSourceIngestIsCancelled()) {
225  break;
226  }
227 
228  try {
229  if (logFile != null) {
230  logFile.write(Long.toString(regFileId) + "\t" + regFile.getUniquePath() + "\n");
231  }
232  } catch (TskCoreException | IOException ex) {
233  logger.log(Level.SEVERE, null, ex);
234  }
235 
236  logger.log(Level.INFO, "{0}- Now getting registry information from {1}", new Object[]{moduleName, regFileNameLocal}); //NON-NLS
237  RegOutputFiles regOutputFiles = ripRegistryFile(regFileNameLocal, outputPathBase);
238  if (context.dataSourceIngestIsCancelled()) {
239  break;
240  }
241 
242  // parse the autopsy-specific output
243  if (regOutputFiles.autopsyPlugins.isEmpty() == false && parseAutopsyPluginOutput(regOutputFiles.autopsyPlugins, regFile) == false) {
244  this.addErrorMessage(
245  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.failedParsingResults",
246  this.getName(), regFileName));
247  }
248 
249  // create a report for the full output
250  if (!regOutputFiles.fullPlugins.isEmpty()) {
251  //parse the full regripper output from SAM hive files
252  if (regFileNameLocal.toLowerCase().contains("sam") && parseSamPluginOutput(regOutputFiles.fullPlugins, regFile) == false) {
253  this.addErrorMessage(
254  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.failedParsingResults",
255  this.getName(), regFileName));
256  }
257  try {
258  Report report = currentCase.addReport(regOutputFiles.fullPlugins,
259  NbBundle.getMessage(this.getClass(), "ExtractRegistry.parentModuleName.noSpace"),
260  "RegRipper " + regFile.getUniquePath(), regFile); //NON-NLS
261 
262  // Index the report content so that it will be available for keyword search.
263  KeywordSearchService searchService = Lookup.getDefault().lookup(KeywordSearchService.class);
264  if (null == searchService) {
265  logger.log(Level.WARNING, "Keyword search service not found. Report will not be indexed");
266  } else {
267  searchService.index(report);
268  report.close();
269  }
270  } catch (TskCoreException e) {
271  this.addErrorMessage("Error adding regripper output as Autopsy report: " + e.getLocalizedMessage()); //NON-NLS
272  }
273  }
274  // delete the hive
275  regFileNameLocalFile.delete();
276  }
277 
278  try {
279  if (logFile != null) {
280  logFile.close();
281  }
282  } catch (IOException ex) {
283  logger.log(Level.SEVERE, null, ex);
284  }
285  }
286 
294  private RegOutputFiles ripRegistryFile(String regFilePath, String outFilePathBase) {
295  String autopsyType = ""; // Type argument for rr for autopsy-specific modules
296  String fullType; // Type argument for rr for full set of modules
297 
298  RegOutputFiles regOutputFiles = new RegOutputFiles();
299 
300  if (regFilePath.toLowerCase().contains("system")) { //NON-NLS
301  autopsyType = "autopsysystem"; //NON-NLS
302  fullType = "system"; //NON-NLS
303  } else if (regFilePath.toLowerCase().contains("software")) { //NON-NLS
304  autopsyType = "autopsysoftware"; //NON-NLS
305  fullType = "software"; //NON-NLS
306  } else if (regFilePath.toLowerCase().contains("ntuser")) { //NON-NLS
307  autopsyType = "autopsyntuser"; //NON-NLS
308  fullType = "ntuser"; //NON-NLS
309  } else if (regFilePath.toLowerCase().contains("sam")) { //NON-NLS
310  //fullType sam output files are parsed for user information
311  fullType = "sam"; //NON-NLS
312  } else if (regFilePath.toLowerCase().contains("security")) { //NON-NLS
313  fullType = "security"; //NON-NLS
314  } else {
315  return regOutputFiles;
316  }
317 
318  // run the autopsy-specific set of modules
319  if (!autopsyType.isEmpty()) {
320  regOutputFiles.autopsyPlugins = outFilePathBase + "-autopsy.txt"; //NON-NLS
321  String errFilePath = outFilePathBase + "-autopsy.err.txt"; //NON-NLS
322  logger.log(Level.INFO, "Writing RegRipper results to: {0}", regOutputFiles.autopsyPlugins); //NON-NLS
323  executeRegRipper(rrCmd, rrHome, regFilePath, autopsyType, regOutputFiles.autopsyPlugins, errFilePath);
324  }
325  if (context.dataSourceIngestIsCancelled()) {
326  return regOutputFiles;
327  }
328 
329  // run the full set of rr modules
330  if (!fullType.isEmpty()) {
331  regOutputFiles.fullPlugins = outFilePathBase + "-full.txt"; //NON-NLS
332  String errFilePath = outFilePathBase + "-full.err.txt"; //NON-NLS
333  logger.log(Level.INFO, "Writing Full RegRipper results to: {0}", regOutputFiles.fullPlugins); //NON-NLS
334  executeRegRipper(rrFullCmd, rrFullHome, regFilePath, fullType, regOutputFiles.fullPlugins, errFilePath);
335  }
336  return regOutputFiles;
337  }
338 
339  private void executeRegRipper(List<String> regRipperPath, Path regRipperHomeDir, String hiveFilePath, String hiveFileType, String outputFile, String errFile) {
340  try {
341  List<String> commandLine = new ArrayList<>();
342  for (String cmd : regRipperPath) {
343  commandLine.add(cmd);
344  }
345  commandLine.add("-r"); //NON-NLS
346  commandLine.add(hiveFilePath);
347  commandLine.add("-f"); //NON-NLS
348  commandLine.add(hiveFileType);
349 
350  ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
351  processBuilder.directory(regRipperHomeDir.toFile()); // RegRipper 2.8 has to be run from its own directory
352  processBuilder.redirectOutput(new File(outputFile));
353  processBuilder.redirectError(new File(errFile));
354  ExecUtil.execute(processBuilder, new DataSourceIngestModuleProcessTerminator(context));
355  } catch (IOException ex) {
356  logger.log(Level.SEVERE, "Unable to run RegRipper", ex); //NON-NLS
357  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName()));
358  }
359  }
360 
361  // @@@ VERIFY that we are doing the right thing when we parse multiple NTUSER.DAT
370  private boolean parseAutopsyPluginOutput(String regFilePath, AbstractFile regFile) {
371  FileInputStream fstream = null;
372  try {
373  // Read the file in and create a Document and elements
374  File regfile = new File(regFilePath);
375  fstream = new FileInputStream(regfile);
376  String regString = new Scanner(fstream, "UTF-8").useDelimiter("\\Z").next(); //NON-NLS
377  String startdoc = "<?xml version=\"1.0\"?><document>"; //NON-NLS
378  String result = regString.replaceAll("----------------------------------------", "");
379  result = result.replaceAll("\\n", ""); //NON-NLS
380  result = result.replaceAll("\\r", ""); //NON-NLS
381  result = result.replaceAll("'", "&apos;"); //NON-NLS
382  result = result.replaceAll("&", "&amp;"); //NON-NLS
383  result = result.replace('\0', ' '); // NON-NLS
384  String enddoc = "</document>"; //NON-NLS
385  String stringdoc = startdoc + result + enddoc;
386  DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
387  Document doc = builder.parse(new InputSource(new StringReader(stringdoc)));
388 
389  // cycle through the elements in the doc
390  Element oroot = doc.getDocumentElement();
391  NodeList children = oroot.getChildNodes();
392  int len = children.getLength();
393  // Add all "usb" dataType nodes to collection of BlackboardArtifacts
394  // that we will submit in a ModuleDataEvent for additional processing.
395  Collection<BlackboardArtifact> usbBBartifacts = new ArrayList<>();
396  // Add all "ssid" dataType nodes to collection of BlackboardArtifacts
397  // that we will submit in a ModuleDataEvent for additional processing.
398  Collection<BlackboardArtifact> wifiBBartifacts = new ArrayList<>();
399  for (int i = 0; i < len; i++) {
400 
401  if (context.dataSourceIngestIsCancelled()) {
402  return false;
403  }
404 
405  Element tempnode = (Element) children.item(i);
406 
407  String dataType = tempnode.getNodeName();
408  NodeList timenodes = tempnode.getElementsByTagName("mtime"); //NON-NLS
409  Long mtime = null;
410  if (timenodes.getLength() > 0) {
411  Element timenode = (Element) timenodes.item(0);
412  String etime = timenode.getTextContent();
413  //sometimes etime will be an empty string and therefore can not be parsed into a date
414  if (etime != null && !etime.isEmpty()) {
415  try {
416  mtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(etime).getTime();
417  String Tempdate = mtime.toString();
418  mtime = Long.valueOf(Tempdate) / MS_IN_SEC;
419  } catch (ParseException ex) {
420  logger.log(Level.WARNING, "Failed to parse epoch time when parsing the registry.", ex); //NON-NLS
421  }
422  }
423  }
424 
425  NodeList artroots = tempnode.getElementsByTagName("artifacts"); //NON-NLS
426  if (artroots.getLength() == 0) {
427  // If there isn't an artifact node, skip this entry
428  continue;
429  }
430 
431  Element artroot = (Element) artroots.item(0);
432  NodeList myartlist = artroot.getChildNodes();
433  String parentModuleName = RecentActivityExtracterModuleFactory.getModuleName();
434 
435  // If all artifact nodes should really go under one Blackboard artifact, need to process it differently
436  switch (dataType) {
437  case "WinVersion": //NON-NLS
438  String version = "";
439  String systemRoot = "";
440  String productId = "";
441  String regOwner = "";
442  String regOrg = "";
443  Long installtime = null;
444  for (int j = 0; j < myartlist.getLength(); j++) {
445  Node artchild = myartlist.item(j);
446  // If it has attributes, then it is an Element (based off API)
447  if (artchild.hasAttributes()) {
448  Element artnode = (Element) artchild;
449 
450  String value = artnode.getTextContent();
451  if (value != null) {
452  value = value.trim();
453  }
454  String name = artnode.getAttribute("name"); //NON-NLS
455  if (name == null) {
456  continue;
457  }
458  switch (name) {
459  case "ProductName": // NON-NLS
460  version = value;
461  break;
462  case "CSDVersion": // NON-NLS
463  // This is dependant on the fact that ProductName shows up first in the module output
464  version = version + " " + value;
465  break;
466  case "SystemRoot": //NON-NLS
467  systemRoot = value;
468  break;
469  case "ProductId": //NON-NLS
470  productId = value;
471  break;
472  case "RegisteredOwner": //NON-NLS
473  regOwner = value;
474  break;
475  case "RegisteredOrganization": //NON-NLS
476  regOrg = value;
477  break;
478  case "InstallDate": //NON-NLS
479  if (value != null && !value.isEmpty()) {
480  try {
481  installtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(value).getTime();
482  String Tempdate = installtime.toString();
483  installtime = Long.valueOf(Tempdate) / MS_IN_SEC;
484  } catch (ParseException e) {
485  logger.log(Level.SEVERE, "RegRipper::Conversion on DateTime -> ", e); //NON-NLS
486  }
487  }
488  break;
489  default:
490  break;
491  }
492  }
493  }
494  try {
495  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
496  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, version));
497  if (installtime != null) {
498  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, installtime));
499  }
500  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, systemRoot));
501  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PRODUCT_ID, parentModuleName, productId));
502  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_OWNER, parentModuleName, regOwner));
503  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ORGANIZATION, parentModuleName, regOrg));
504 
505  // Check if there is already an OS_INFO artifact for this file, and add to that if possible.
506  ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
507  if (results.isEmpty()) {
508  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
509  bbart.addAttributes(bbattributes);
510 
511  // index the artifact for keyword search
512  this.indexArtifact(bbart);
513  } else {
514  results.get(0).addAttributes(bbattributes);
515  }
516 
517  } catch (TskCoreException ex) {
518  logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard."); //NON-NLS
519  }
520  break;
521  case "Profiler": // NON-NLS
522  String os = "";
523  String procArch = "";
524  String tempDir = "";
525  for (int j = 0; j < myartlist.getLength(); j++) {
526  Node artchild = myartlist.item(j);
527  // If it has attributes, then it is an Element (based off API)
528  if (artchild.hasAttributes()) {
529  Element artnode = (Element) artchild;
530 
531  String value = artnode.getTextContent().trim();
532  String name = artnode.getAttribute("name"); //NON-NLS
533  switch (name) {
534  case "OS": // NON-NLS
535  os = value;
536  break;
537  case "PROCESSOR_ARCHITECTURE": // NON-NLS
538  procArch = value;
539  break;
540  case "PROCESSOR_IDENTIFIER": //NON-NLS
541  break;
542  case "TEMP": //NON-NLS
543  tempDir = value;
544  break;
545  default:
546  break;
547  }
548  }
549  }
550  try {
551  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
552  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VERSION, parentModuleName, os));
553  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE, parentModuleName, procArch));
554  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEMP_DIR, parentModuleName, tempDir));
555 
556  // Check if there is already an OS_INFO artifact for this file and add to that if possible
557  ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
558  if (results.isEmpty()) {
559  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
560  bbart.addAttributes(bbattributes);
561 
562  // index the artifact for keyword search
563  this.indexArtifact(bbart);
564  } else {
565  results.get(0).addAttributes(bbattributes);
566  }
567  } catch (TskCoreException ex) {
568  logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS
569  }
570  break;
571  case "CompName": // NON-NLS
572  String compName = "";
573  String domain = "";
574  for (int j = 0; j < myartlist.getLength(); j++) {
575  Node artchild = myartlist.item(j);
576  // If it has attributes, then it is an Element (based off API)
577  if (artchild.hasAttributes()) {
578  Element artnode = (Element) artchild;
579 
580  String value = artnode.getTextContent().trim();
581  String name = artnode.getAttribute("name"); //NON-NLS
582 
583  if (name.equals("ComputerName")) { // NON-NLS
584  compName = value;
585  } else if (name.equals("Domain")) { // NON-NLS
586  domain = value;
587  }
588  }
589  }
590  try {
591  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
592  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, compName));
593  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, parentModuleName, domain));
594 
595  // Check if there is already an OS_INFO artifact for this file and add to that if possible
596  ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
597  if (results.isEmpty()) {
598  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
599  bbart.addAttributes(bbattributes);
600 
601  // index the artifact for keyword search
602  this.indexArtifact(bbart);
603  } else {
604  results.get(0).addAttributes(bbattributes);
605  }
606  } catch (TskCoreException ex) {
607  logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS
608  }
609  break;
610  default:
611  for (int j = 0; j < myartlist.getLength(); j++) {
612  Node artchild = myartlist.item(j);
613  // If it has attributes, then it is an Element (based off API)
614  if (artchild.hasAttributes()) {
615  Element artnode = (Element) artchild;
616 
617  String value = artnode.getTextContent().trim();
618  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
619 
620  switch (dataType) {
621  case "recentdocs": //NON-NLS
622  // BlackboardArtifact bbart = tskCase.getContentById(orgId).newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
623  // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", dataType, mtime));
624  // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity", dataType, mtimeItem));
625  // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), "RecentActivity", dataType, value));
626  // bbart.addAttributes(bbattributes);
627  // @@@ BC: Why are we ignoring this...
628  break;
629  case "usb": //NON-NLS
630  try {
631  Long usbMtime = Long.parseLong(artnode.getAttribute("mtime")); //NON-NLS
632  usbMtime = Long.valueOf(usbMtime.toString());
633 
634  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
635  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime));
636  String dev = artnode.getAttribute("dev"); //NON-NLS
637  String make = "";
638  String model = dev;
639  if (dev.toLowerCase().contains("vid")) { //NON-NLS
640  USBInfo info = USB_MAPPER.parseAndLookup(dev);
641  if (info.getVendor() != null) {
642  make = info.getVendor();
643  }
644  if (info.getProduct() != null) {
645  model = info.getProduct();
646  }
647  }
648  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make));
649  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model));
650  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value));
651  bbart.addAttributes(bbattributes);
652 
653  // index the artifact for keyword search
654  this.indexArtifact(bbart);
655  // add to collection for ModuleDataEvent
656  usbBBartifacts.add(bbart);
657  } catch (TskCoreException ex) {
658  logger.log(Level.SEVERE, "Error adding device attached artifact to blackboard."); //NON-NLS
659  }
660  break;
661  case "uninstall": //NON-NLS
662  Long itemMtime = null;
663  try {
664  String mTimeAttr = artnode.getAttribute("mtime");
665  if (mTimeAttr != null && !mTimeAttr.isEmpty()) {
666  itemMtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(mTimeAttr).getTime(); //NON-NLS
667  itemMtime /= MS_IN_SEC;
668  }
669  } catch (ParseException e) {
670  logger.log(Level.WARNING, "Failed to parse epoch time for installed program artifact."); //NON-NLS
671  }
672 
673  try {
674  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, value));
675  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, itemMtime));
676  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG);
677  bbart.addAttributes(bbattributes);
678 
679  // index the artifact for keyword search
680  this.indexArtifact(bbart);
681  } catch (TskCoreException ex) {
682  logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard."); //NON-NLS
683  }
684  break;
685  case "office": //NON-NLS
686  String officeName = artnode.getAttribute("name"); //NON-NLS
687 
688  try {
689  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
690  // @@@ BC: Consider removing this after some more testing. It looks like an Mtime associated with the root key and not the individual item
691  if (mtime != null) {
692  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, parentModuleName, mtime));
693  }
694  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, officeName));
695  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, parentModuleName, value));
696  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, artnode.getNodeName()));
697  bbart.addAttributes(bbattributes);
698 
699  // index the artifact for keyword search
700  this.indexArtifact(bbart);
701  } catch (TskCoreException ex) {
702  logger.log(Level.SEVERE, "Error adding recent object artifact to blackboard."); //NON-NLS
703  }
704  break;
705 
706  case "ProcessorArchitecture": //NON-NLS
707  // Architecture is now included under Profiler
708  //try {
709  // String processorArchitecture = value;
710  // if (processorArchitecture.equals("AMD64"))
711  // processorArchitecture = "x86-64";
712 
713  // BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
714  // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE.getTypeID(), parentModuleName, processorArchitecture));
715  // bbart.addAttributes(bbattributes);
716  //} catch (TskCoreException ex) {
717  // logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS
718  //}
719  break;
720 
721  case "ProfileList": //NON-NLS
722  try {
723  String homeDir = value;
724  String sid = artnode.getAttribute("sid"); //NON-NLS
725  String username = artnode.getAttribute("username"); //NON-NLS
726  BlackboardArtifact bbart = null;
727  try {
728  //check if any of the existing artifacts match this username
729  ArrayList<BlackboardArtifact> existingArtifacts = currentCase.getSleuthkitCase().getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
730  for (BlackboardArtifact artifact : existingArtifacts) {
731  if (artifact.getDataSource().getId() == regFile.getDataSourceObjectId()) {
732  BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID));
733  if (attribute != null && attribute.getValueString().equals(sid)) {
734  bbart = artifact;
735  break;
736  }
737  }
738  }
739  } catch (TskCoreException ex) {
740  logger.log(Level.WARNING, "Error getting existing os account artifact", ex);
741  }
742  if (bbart == null) {
743  //create new artifact
744  bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
745  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
746  parentModuleName, username));
747  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID,
748  parentModuleName, sid));
749  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
750  parentModuleName, homeDir));
751  } else {
752  //add attributes to existing artifact
753  BlackboardAttribute bbattr = bbart.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_NAME));
754 
755  if (bbattr == null) {
756  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
757  parentModuleName, username));
758  }
759  bbattr = bbart.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH));
760  if (bbattr == null) {
761  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
762  parentModuleName, homeDir));
763  }
764  }
765  bbart.addAttributes(bbattributes);
766  // index the artifact for keyword search
767  this.indexArtifact(bbart);
768  } catch (TskCoreException ex) {
769  logger.log(Level.SEVERE, "Error adding account artifact to blackboard."); //NON-NLS
770  }
771  break;
772 
773  case "NtuserNetwork": // NON-NLS
774  try {
775  String localPath = artnode.getAttribute("localPath"); //NON-NLS
776  String remoteName = value;
777  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_REMOTE_DRIVE);
778  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH,
779  parentModuleName, localPath));
780  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH,
781  parentModuleName, remoteName));
782  bbart.addAttributes(bbattributes);
783  // index the artifact for keyword search
784  this.indexArtifact(bbart);
785  } catch (TskCoreException ex) {
786  logger.log(Level.SEVERE, "Error adding network artifact to blackboard."); //NON-NLS
787  }
788  break;
789  case "SSID": // NON-NLS
790  String adapter = artnode.getAttribute("adapter"); //NON-NLS
791  try {
792  Long lastWriteTime = Long.parseLong(artnode.getAttribute("writeTime")); //NON-NLS
793  lastWriteTime = Long.valueOf(lastWriteTime.toString());
794  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SSID, parentModuleName, value));
795  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, lastWriteTime));
796  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, adapter));
797  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_WIFI_NETWORK);
798  bbart.addAttributes(bbattributes);
799  // index the artifact for keyword search
800  this.indexArtifact(bbart);
801  wifiBBartifacts.add(bbart);
802  } catch (TskCoreException ex) {
803  logger.log(Level.SEVERE, "Error adding SSID artifact to blackboard."); //NON-NLS
804  }
805  break;
806  case "shellfolders": // NON-NLS
807  // The User Shell Folders subkey stores the paths to Windows Explorer folders for the current user of the computer
808  // (https://technet.microsoft.com/en-us/library/Cc962613.aspx).
809  // No useful information. Skip.
810  break;
811 
812  default:
813  logger.log(Level.WARNING, "Unrecognized node name: {0}", dataType); //NON-NLS
814  break;
815  }
816  }
817  }
818  break;
819  }
820  } // for
821  if (!usbBBartifacts.isEmpty()) {
822  IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_DEVICE_ATTACHED, usbBBartifacts));
823  }
824  if (!wifiBBartifacts.isEmpty()) {
825  IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_WIFI_NETWORK, wifiBBartifacts));
826  }
827  return true;
828  } catch (FileNotFoundException ex) {
829  logger.log(Level.SEVERE, "Error finding the registry file.", ex); //NON-NLS
830  } catch (SAXException ex) {
831  logger.log(Level.SEVERE, "Error parsing the registry XML.", ex); //NON-NLS
832  } catch (IOException ex) {
833  logger.log(Level.SEVERE, "Error building the document parser.", ex); //NON-NLS
834  } catch (ParserConfigurationException ex) {
835  logger.log(Level.SEVERE, "Error configuring the registry parser.", ex); //NON-NLS
836  } finally {
837  try {
838  if (fstream != null) {
839  fstream.close();
840  }
841  } catch (IOException ex) {
842  }
843  }
844  return false;
845  }
846 
856  private boolean parseSamPluginOutput(String regFilePath, AbstractFile regAbstractFile) {
857  File regfile = new File(regFilePath);
858  String parentModuleName = RecentActivityExtracterModuleFactory.getModuleName();
859  SimpleDateFormat regRipperTimeFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy 'Z'");
860  regRipperTimeFormat.setTimeZone(getTimeZone("GMT"));
861  try (BufferedReader bufferedReader = new BufferedReader(new FileReader(regfile))) {
862  // Read the file in and create a Document and elements
863  String userInfoSection = "User Information";
864  String previousLine = null;
865  String line = bufferedReader.readLine();
866  Set<UserInfo> userSet = new HashSet<>();
867  while (line != null) {
868  if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains(userInfoSection)) {
869  readUsers(bufferedReader, userSet);
870 
871  }
872  previousLine = line;
873  line = bufferedReader.readLine();
874  }
875  Map<String, UserInfo> userInfoMap = new HashMap<>();
876  //load all the user info which was read into a map
877  for (UserInfo userInfo : userSet) {
878  userInfoMap.put(userInfo.getUserSid(), userInfo);
879  }
880  //get all existing OS account artifacts
881  List<BlackboardArtifact> existingOsAccounts = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
882  for (BlackboardArtifact osAccount : existingOsAccounts) {
883  //if the OS Account artifact was from the same data source check the user id
884  if (osAccount.getDataSource().getId() == regAbstractFile.getDataSourceObjectId()) {
885  BlackboardAttribute existingUserId = osAccount.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID));
886  if (existingUserId != null) {
887  UserInfo userInfo = userInfoMap.remove(existingUserId.getValueString().trim());
888  //if the existing user id matches a user id which we parsed information for check if that information exists and if it doesn't add it
889  if (userInfo != null) {
890  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
891  if (userInfo.getAccountCreatedDate() != null && !userInfo.getAccountCreatedDate().equals(NEVER_DATE)) {
892  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
893  parentModuleName, regRipperTimeFormat.parse(userInfo.getAccountCreatedDate()).getTime() / MS_IN_SEC));
894  }
895  if (userInfo.getLastLoginDate() != null && !userInfo.getLastLoginDate().equals(NEVER_DATE)) {
896  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
897  parentModuleName, regRipperTimeFormat.parse(userInfo.getLastLoginDate()).getTime() / MS_IN_SEC));
898  }
899  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
900  parentModuleName, userInfo.getLoginCount()));
901  osAccount.addAttributes(bbattributes);
902  }
903  }
904  }
905  }
906  //add remaining userinfos as accounts;
907  for (String userId : userInfoMap.keySet()) {
908  UserInfo userInfo = userInfoMap.get(userId);
909  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
910  BlackboardArtifact bbart = regAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
911  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
912  parentModuleName, userInfo.getUserName()));
913  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID,
914  parentModuleName, userId));
915  if (userInfo.getAccountCreatedDate() != null && !userInfo.getAccountCreatedDate().equals(NEVER_DATE)) {
916  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
917  parentModuleName, regRipperTimeFormat.parse(userInfo.getAccountCreatedDate()).getTime() / MS_IN_SEC));
918  }
919  if (userInfo.getLastLoginDate() != null && !userInfo.getLastLoginDate().equals(NEVER_DATE)) {
920  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
921  parentModuleName, regRipperTimeFormat.parse(userInfo.getLastLoginDate()).getTime() / MS_IN_SEC));
922  }
923  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
924  parentModuleName, userInfo.getLoginCount()));
925  bbart.addAttributes(bbattributes);
926  // index the artifact for keyword search
927  this.indexArtifact(bbart);
928  }
929  //store set of attributes to make artifact for later in collection of artifact like objects
930  return true;
931  } catch (FileNotFoundException ex) {
932  logger.log(Level.SEVERE, "Error finding the registry file.", ex); //NON-NLS
933  } catch (IOException ex) {
934  logger.log(Level.SEVERE, "Error building the document parser: {0}", ex); //NON-NLS
935  } catch (ParseException ex) {
936  logger.log(Level.SEVERE, "Error parsing the the date from the registry file", ex); //NON-NLS
937  } catch (TskCoreException ex) {
938  logger.log(Level.SEVERE, "Error updating TSK_OS_ACCOUNT artifacts to include newly parsed data.", ex); //NON-NLS
939  }
940  return false;
941  }
942 
954  private void readUsers(BufferedReader bufferedReader, Set<UserInfo> users) throws IOException {
955  String userNameLabel = "Username :";
956  String sidLabel = "SID :";
957  String accountCreatedLabel = "Account Created :";
958  String loginCountLabel = "Login Count :";
959  String lastLoginLabel = "Last Login Date :";
960  String line = bufferedReader.readLine();
961  //read until end of file or next section divider
962  String userName = "";
963  while (line != null && !line.contains(SECTION_DIVIDER)) {
964  //when a user name field exists read the name and id number
965  if (line.contains(userNameLabel)) {
966  String userNameAndIdString = line.replace(userNameLabel, "");
967  userName = userNameAndIdString.substring(0, userNameAndIdString.lastIndexOf('[')).trim();
968  } else if (line.contains(sidLabel) && !userName.isEmpty()) {
969  String sid = line.replace(sidLabel, "").trim();
970  UserInfo userInfo = new UserInfo(userName, sid);
971  //continue reading this users information until end of file or a blank line between users
972  line = bufferedReader.readLine();
973  while (line != null && !line.isEmpty()) {
974  if (line.contains(accountCreatedLabel)) {
975  userInfo.setAccountCreatedDate(line.replace(accountCreatedLabel, "").trim());
976  } else if (line.contains(loginCountLabel)) {
977  userInfo.setLoginCount(Integer.parseInt(line.replace(loginCountLabel, "").trim()));
978  } else if (line.contains(lastLoginLabel)) {
979  userInfo.setLastLoginDate(line.replace(lastLoginLabel, "").trim());
980  }
981  line = bufferedReader.readLine();
982  }
983  users.add(userInfo);
984  userName = "";
985  }
986  line = bufferedReader.readLine();
987  }
988  }
989 
990  @Override
991  public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
992  this.dataSource = dataSource;
993  this.context = context;
994 
995  progressBar.progress(Bundle.Progress_Message_Analyze_Registry());
996  analyzeRegistryFiles();
997 
998  }
999 
1003  private class RegOutputFiles {
1004 
1005  public String autopsyPlugins = "";
1006  public String fullPlugins = "";
1007  }
1008 
1013  private class UserInfo {
1014 
1015  private final String userName;
1016  private final String userSid;
1017  private String lastLoginDate;
1018  private String accountCreatedDate;
1019  private int loginCount = 0;
1020 
1027  private UserInfo(String name, String userSidString) {
1028  userName = name;
1029  userSid = userSidString;
1030  }
1031 
1037  String getUserName() {
1038  return userName;
1039  }
1040 
1046  String getUserSid() {
1047  return userSid;
1048  }
1049 
1055  String getLastLoginDate() {
1056  return lastLoginDate;
1057  }
1058 
1064  void setLastLoginDate(String lastLoginDate) {
1065  this.lastLoginDate = lastLoginDate;
1066  }
1067 
1073  String getAccountCreatedDate() {
1074  return accountCreatedDate;
1075  }
1076 
1082  void setAccountCreatedDate(String accountCreatedDate) {
1083  this.accountCreatedDate = accountCreatedDate;
1084  }
1085 
1091  int getLoginCount() {
1092  return loginCount;
1093  }
1094 
1100  void setLoginCount(int loginCount) {
1101  this.loginCount = loginCount;
1102  }
1103 
1104  }
1105 }

Copyright © 2012-2018 Basis Technology. Generated on: Fri Jun 21 2019
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.