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

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