Autopsy  4.14.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-2020 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.apache.commons.io.FilenameUtils;
40 import org.openide.modules.InstalledFileLocator;
41 import org.openide.util.NbBundle;
49 import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
50 import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
51 import org.w3c.dom.Document;
52 import org.w3c.dom.Element;
53 import org.w3c.dom.Node;
54 import org.w3c.dom.NodeList;
55 import org.xml.sax.InputSource;
56 import org.xml.sax.SAXException;
57 import java.nio.file.Path;
58 import java.util.AbstractMap;
59 import java.util.ArrayList;
60 import java.util.Arrays;
61 import java.util.List;
62 import java.util.Collection;
63 import java.util.Date;
64 import java.util.HashMap;
65 import java.util.Map;
66 import java.util.Scanner;
67 import java.util.Set;
68 import java.util.HashSet;
69 import static java.util.Locale.US;
70 import static java.util.TimeZone.getTimeZone;
71 import org.openide.util.Lookup;
78 import org.sleuthkit.datamodel.AbstractFile;
79 import org.sleuthkit.datamodel.Account;
80 import org.sleuthkit.datamodel.BlackboardArtifact;
81 import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT;
82 import org.sleuthkit.datamodel.BlackboardAttribute;
83 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT;
84 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT;
85 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED;
86 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED;
87 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED;
88 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH;
89 import org.sleuthkit.datamodel.Content;
90 import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
91 import org.sleuthkit.datamodel.Report;
92 import org.sleuthkit.datamodel.TskCoreException;
93 import org.sleuthkit.datamodel.TskDataException;
94 
101 @NbBundle.Messages({
102  "RegRipperNotFound=Autopsy RegRipper executable not found.",
103  "RegRipperFullNotFound=Full version RegRipper executable not found.",
104  "Progress_Message_Analyze_Registry=Analyzing Registry Files",
105  "Shellbag_Artifact_Display_Name=Shell Bags",
106  "Shellbag_Key_Attribute_Display_Name=Key",
107  "Shellbag_Last_Write_Attribute_Display_Name=Last Write",
108  "Recently_Used_Artifacts_Office_Trustrecords=Stored in TrustRecords because Office security exception was granted",
109  "Recently_Used_Artifacts_ArcHistory=Recently opened by 7Zip",
110  "Recently_Used_Artifacts_Applets=Recently opened according to Applets registry key",
111  "Recently_Used_Artifacts_Mmc=Recently opened according to Windows Management Console MRU",
112  "Recently_Used_Artifacts_Winrar=Recently opened according to WinRAR MRU",
113  "Recently_Used_Artifacts_Officedocs=Recently opened according to Office MRU",
114  "Recently_Used_Artifacts_Adobe=Recently opened according to Adobe MRU",
115  "Recently_Used_Artifacts_Mediaplayer=Recently opened according to Media Player MRU"
116 })
117 class ExtractRegistry extends Extract {
118 
119  private static final String USERNAME_KEY = "Username"; //NON-NLS
120  private static final String SID_KEY = "SID"; //NON-NLS
121  private static final String RID_KEY = "RID"; //NON-NLS
122  private static final String ACCOUNT_CREATED_KEY = "Account Created"; //NON-NLS
123  private static final String LAST_LOGIN_KEY = "Last Login Date"; //NON-NLS
124  private static final String LOGIN_COUNT_KEY = "Login Count"; //NON-NLS
125  private static final String FULL_NAME_KEY = "Full Name"; //NON-NLS
126  private static final String USER_COMMENT_KEY = "User Comment"; //NON-NLS
127  private static final String ACCOUNT_TYPE_KEY = "Account Type"; //NON-NLS
128  private static final String NAME_KEY = "Name"; //NON-NLS
129  private static final String PWD_RESET_KEY = "Pwd Rest Date"; //NON-NLS
130  private static final String PWD_FAILE_KEY = "Pwd Fail Date"; //NON-NLS
131  private static final String INTERNET_NAME_KEY = "InternetName"; //NON-NLS
132  private static final String PWD_DOES_NOT_EXPIRE_KEY = "Password does not expire"; //NON-NLS
133  private static final String ACCOUNT_DISABLED_KEY = "Account Disabled"; //NON-NLS
134  private static final String PWD_NOT_REQUIRED_KEY = "Password not required"; //NON-NLS
135  private static final String NORMAL_ACCOUNT_KEY = "Normal user account"; //NON-NLS
136  private static final String HOME_DIRECTORY_REQUIRED_KEY = "Home directory required";
137  private static final String TEMPORARY_DUPLICATE_ACCOUNT = "Temporary duplicate account";
138  private static final String MNS_LOGON_ACCOUNT_KEY = "MNS logon user account";
139  private static final String INTERDOMAIN_TRUST_ACCOUNT_KEY = "Interdomain trust account";
140  private static final String WORKSTATION_TRUST_ACCOUNT = "Workstation trust account";
141  private static final String SERVER_TRUST_ACCOUNT = "Server trust account";
142  private static final String ACCOUNT_AUTO_LOCKED = "Account auto locked";
143  private static final String PASSWORD_HINT = "Password Hint";
144 
145  private static final String[] PASSWORD_SETTINGS_FLAGS = {PWD_DOES_NOT_EXPIRE_KEY, PWD_NOT_REQUIRED_KEY};
146  private static final String[] ACCOUNT_SETTINGS_FLAGS = {ACCOUNT_AUTO_LOCKED, HOME_DIRECTORY_REQUIRED_KEY, ACCOUNT_DISABLED_KEY};
147  private static final String[] ACCOUNT_TYPE_FLAGS = {NORMAL_ACCOUNT_KEY, SERVER_TRUST_ACCOUNT, WORKSTATION_TRUST_ACCOUNT, INTERDOMAIN_TRUST_ACCOUNT_KEY, MNS_LOGON_ACCOUNT_KEY, TEMPORARY_DUPLICATE_ACCOUNT};
148 
149  final private static UsbDeviceIdMapper USB_MAPPER = new UsbDeviceIdMapper();
150  final private static String RIP_EXE = "rip.exe";
151  final private static String RIP_PL = "rip.pl";
152  final private static String RIP_PL_INCLUDE_FLAG = "-I";
153  final private static int MS_IN_SEC = 1000;
154  final private static String NEVER_DATE = "Never";
155  final private static String SECTION_DIVIDER = "-------------------------";
156  final private static Logger logger = Logger.getLogger(ExtractRegistry.class.getName());
157  private final List<String> rrCmd = new ArrayList<>();
158  private final List<String> rrFullCmd = new ArrayList<>();
159  private final Path rrHome; // Path to the Autopsy version of RegRipper
160  private final Path rrFullHome; // Path to the full version of RegRipper
161  private Content dataSource;
162  private IngestJobContext context;
163 
164  private static final String SHELLBAG_ARTIFACT_NAME = "RA_SHELL_BAG"; //NON-NLS
165  private static final String SHELLBAG_ATTRIBUTE_LAST_WRITE = "RA_SHELL_BAG_LAST_WRITE"; //NON-NLS
166  private static final String SHELLBAG_ATTRIBUTE_KEY= "RA_SHELL_BAG_KEY"; //NON-NLS
167 
168  BlackboardArtifact.Type shellBagArtifactType = null;
169  BlackboardAttribute.Type shellBagKeyAttributeType = null;
170  BlackboardAttribute.Type shellBagLastWriteAttributeType = null;
171 
172  ExtractRegistry() throws IngestModuleException {
173  moduleName = NbBundle.getMessage(ExtractIE.class, "ExtractRegistry.moduleName.text");
174 
175  final File rrRoot = InstalledFileLocator.getDefault().locate("rr", ExtractRegistry.class.getPackage().getName(), false); //NON-NLS
176  if (rrRoot == null) {
177  throw new IngestModuleException(Bundle.RegRipperNotFound());
178  }
179 
180  final File rrFullRoot = InstalledFileLocator.getDefault().locate("rr-full", ExtractRegistry.class.getPackage().getName(), false); //NON-NLS
181  if (rrFullRoot == null) {
182  throw new IngestModuleException(Bundle.RegRipperFullNotFound());
183  }
184 
185  String executableToRun = RIP_EXE;
186  if (!PlatformUtil.isWindowsOS()) {
187  executableToRun = RIP_PL;
188  }
189  rrHome = rrRoot.toPath();
190  String rrPath = rrHome.resolve(executableToRun).toString();
191  rrFullHome = rrFullRoot.toPath();
192 
193  if (!(new File(rrPath).exists())) {
194  throw new IngestModuleException(Bundle.RegRipperNotFound());
195  }
196  String rrFullPath = rrFullHome.resolve(executableToRun).toString();
197  if (!(new File(rrFullPath).exists())) {
198  throw new IngestModuleException(Bundle.RegRipperFullNotFound());
199  }
200  if (PlatformUtil.isWindowsOS()) {
201  rrCmd.add(rrPath);
202  rrFullCmd.add(rrFullPath);
203  } else {
204  String perl;
205  File usrBin = new File("/usr/bin/perl");
206  File usrLocalBin = new File("/usr/local/bin/perl");
207  if (usrBin.canExecute() && usrBin.exists() && !usrBin.isDirectory()) {
208  perl = "/usr/bin/perl";
209  } else if (usrLocalBin.canExecute() && usrLocalBin.exists() && !usrLocalBin.isDirectory()) {
210  perl = "/usr/local/bin/perl";
211  } else {
212  throw new IngestModuleException("perl not found in your system");
213  }
214  rrCmd.add(perl);
215  rrCmd.add(RIP_PL_INCLUDE_FLAG);
216  rrCmd.add(rrHome.toString());
217  rrCmd.add(rrPath);
218  rrFullCmd.add(perl);
219  rrFullCmd.add(RIP_PL_INCLUDE_FLAG);
220  rrFullCmd.add(rrFullHome.toString());
221  rrFullCmd.add(rrFullPath);
222  }
223  }
224 
228  private List<AbstractFile> findRegistryFiles() {
229  List<AbstractFile> allRegistryFiles = new ArrayList<>();
230  org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
231 
232  // find the user-specific ntuser-dat files
233  try {
234  allRegistryFiles.addAll(fileManager.findFiles(dataSource, "ntuser.dat")); //NON-NLS
235  } catch (TskCoreException ex) {
236  logger.log(Level.WARNING, "Error fetching 'ntuser.dat' file."); //NON-NLS
237  }
238 
239  // find the user-specific ntuser-dat files
240  try {
241  allRegistryFiles.addAll(fileManager.findFiles(dataSource, "usrclass.dat")); //NON-NLS
242  } catch (TskCoreException ex) {
243  logger.log(Level.WARNING, String.format("Error finding 'usrclass.dat' files."), ex); //NON-NLS
244  }
245 
246  // find the system hives'
247  String[] regFileNames = new String[]{"system", "software", "security", "sam"}; //NON-NLS
248  for (String regFileName : regFileNames) {
249  try {
250  allRegistryFiles.addAll(fileManager.findFiles(dataSource, regFileName, "/system32/config")); //NON-NLS
251  } catch (TskCoreException ex) {
252  String msg = NbBundle.getMessage(this.getClass(),
253  "ExtractRegistry.findRegFiles.errMsg.errReadingFile", regFileName);
254  logger.log(Level.WARNING, msg, ex);
255  this.addErrorMessage(this.getName() + ": " + msg);
256  }
257  }
258  return allRegistryFiles;
259  }
260 
265  private void analyzeRegistryFiles() {
266  List<AbstractFile> allRegistryFiles = findRegistryFiles();
267 
268  // open the log file
269  FileWriter logFile = null;
270  try {
271  logFile = new FileWriter(RAImageIngestModule.getRAOutputPath(currentCase, "reg") + File.separator + "regripper-info.txt"); //NON-NLS
272  } catch (IOException ex) {
273  logger.log(Level.SEVERE, null, ex);
274  }
275 
276  for (AbstractFile regFile : allRegistryFiles) {
277  String regFileName = regFile.getName();
278  long regFileId = regFile.getId();
279  String regFileNameLocal = RAImageIngestModule.getRATempPath(currentCase, "reg") + File.separator + regFileName;
280  String outputPathBase = RAImageIngestModule.getRAOutputPath(currentCase, "reg") + File.separator + regFileName + "-regripper-" + Long.toString(regFileId); //NON-NLS
281  File regFileNameLocalFile = new File(regFileNameLocal);
282  try {
283  ContentUtils.writeToFile(regFile, regFileNameLocalFile, context::dataSourceIngestIsCancelled);
284  } catch (ReadContentInputStreamException ex) {
285  logger.log(Level.WARNING, String.format("Error reading registry file '%s' (id=%d).",
286  regFile.getName(), regFileId), ex); //NON-NLS
287  this.addErrorMessage(
288  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
289  this.getName(), regFileName));
290  continue;
291  } catch (IOException ex) {
292  logger.log(Level.SEVERE, String.format("Error writing temp registry file '%s' for registry file '%s' (id=%d).",
293  regFileNameLocal, regFile.getName(), regFileId), ex); //NON-NLS
294  this.addErrorMessage(
295  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
296  this.getName(), regFileName));
297  continue;
298  }
299 
300  if (context.dataSourceIngestIsCancelled()) {
301  break;
302  }
303 
304  try {
305  if (logFile != null) {
306  logFile.write(Long.toString(regFileId) + "\t" + regFile.getUniquePath() + "\n");
307  }
308  } catch (TskCoreException | IOException ex) {
309  logger.log(Level.SEVERE, null, ex);
310  }
311 
312  logger.log(Level.INFO, "{0}- Now getting registry information from {1}", new Object[]{moduleName, regFileNameLocal}); //NON-NLS
313  RegOutputFiles regOutputFiles = ripRegistryFile(regFileNameLocal, outputPathBase);
314  if (context.dataSourceIngestIsCancelled()) {
315  break;
316  }
317 
318  // parse the autopsy-specific output
319  if (regOutputFiles.autopsyPlugins.isEmpty() == false && parseAutopsyPluginOutput(regOutputFiles.autopsyPlugins, regFile) == false) {
320  this.addErrorMessage(
321  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.failedParsingResults",
322  this.getName(), regFileName));
323  }
324 
325  // create a report for the full output
326  if (!regOutputFiles.fullPlugins.isEmpty()) {
327  //parse the full regripper output from SAM hive files
328  if (regFileNameLocal.toLowerCase().contains("sam") && parseSamPluginOutput(regOutputFiles.fullPlugins, regFile) == false) {
329  this.addErrorMessage(
330  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.failedParsingResults",
331  this.getName(), regFileName));
332  } else if (regFileNameLocal.toLowerCase().contains("ntuser") || regFileNameLocal.toLowerCase().contains("usrclass")) {
333  try {
334  List<ShellBag> shellbags = ShellBagParser.parseShellbagOutput(regOutputFiles.fullPlugins);
335  createShellBagArtifacts(regFile, shellbags);
336  createRecentlyUsedArtifacts(regOutputFiles.fullPlugins, regFile);
337  } catch (IOException | TskCoreException ex) {
338  logger.log(Level.WARNING, String.format("Unable to get shell bags from file %s", regOutputFiles.fullPlugins), ex);
339  }
340  }
341  try {
342  Report report = currentCase.addReport(regOutputFiles.fullPlugins,
343  NbBundle.getMessage(this.getClass(), "ExtractRegistry.parentModuleName.noSpace"),
344  "RegRipper " + regFile.getUniquePath(), regFile); //NON-NLS
345 
346  // Index the report content so that it will be available for keyword search.
347  KeywordSearchService searchService = Lookup.getDefault().lookup(KeywordSearchService.class);
348  if (null == searchService) {
349  logger.log(Level.WARNING, "Keyword search service not found. Report will not be indexed");
350  } else {
351  searchService.index(report);
352  report.close();
353  }
354  } catch (TskCoreException e) {
355  this.addErrorMessage("Error adding regripper output as Autopsy report: " + e.getLocalizedMessage()); //NON-NLS
356  }
357  }
358  // delete the hive
359  regFileNameLocalFile.delete();
360  }
361 
362  try {
363  if (logFile != null) {
364  logFile.close();
365  }
366  } catch (IOException ex) {
367  logger.log(Level.SEVERE, null, ex);
368  }
369  }
370 
378  private RegOutputFiles ripRegistryFile(String regFilePath, String outFilePathBase) {
379  String autopsyType = ""; // Type argument for rr for autopsy-specific modules
380  String fullType; // Type argument for rr for full set of modules
381 
382  RegOutputFiles regOutputFiles = new RegOutputFiles();
383 
384  if (regFilePath.toLowerCase().contains("system")) { //NON-NLS
385  autopsyType = "autopsysystem"; //NON-NLS
386  fullType = "system"; //NON-NLS
387  } else if (regFilePath.toLowerCase().contains("software")) { //NON-NLS
388  autopsyType = "autopsysoftware"; //NON-NLS
389  fullType = "software"; //NON-NLS
390  } else if (regFilePath.toLowerCase().contains("ntuser")) { //NON-NLS
391  autopsyType = "autopsyntuser"; //NON-NLS
392  fullType = "ntuser"; //NON-NLS
393  } else if (regFilePath.toLowerCase().contains("sam")) { //NON-NLS
394  //fullType sam output files are parsed for user information
395  fullType = "sam"; //NON-NLS
396  } else if (regFilePath.toLowerCase().contains("security")) { //NON-NLS
397  fullType = "security"; //NON-NLS
398  }else if (regFilePath.toLowerCase().contains("usrclass")) { //NON-NLS
399  fullType = "usrclass"; //NON-NLS
400  } else {
401  return regOutputFiles;
402  }
403 
404  // run the autopsy-specific set of modules
405  if (!autopsyType.isEmpty()) {
406  regOutputFiles.autopsyPlugins = outFilePathBase + "-autopsy.txt"; //NON-NLS
407  String errFilePath = outFilePathBase + "-autopsy.err.txt"; //NON-NLS
408  logger.log(Level.INFO, "Writing RegRipper results to: {0}", regOutputFiles.autopsyPlugins); //NON-NLS
409  executeRegRipper(rrCmd, rrHome, regFilePath, autopsyType, regOutputFiles.autopsyPlugins, errFilePath);
410  }
411  if (context.dataSourceIngestIsCancelled()) {
412  return regOutputFiles;
413  }
414 
415  // run the full set of rr modules
416  if (!fullType.isEmpty()) {
417  regOutputFiles.fullPlugins = outFilePathBase + "-full.txt"; //NON-NLS
418  String errFilePath = outFilePathBase + "-full.err.txt"; //NON-NLS
419  logger.log(Level.INFO, "Writing Full RegRipper results to: {0}", regOutputFiles.fullPlugins); //NON-NLS
420  executeRegRipper(rrFullCmd, rrFullHome, regFilePath, fullType, regOutputFiles.fullPlugins, errFilePath);
421  }
422  return regOutputFiles;
423  }
424 
425  private void executeRegRipper(List<String> regRipperPath, Path regRipperHomeDir, String hiveFilePath, String hiveFileType, String outputFile, String errFile) {
426  try {
427  List<String> commandLine = new ArrayList<>();
428  for (String cmd : regRipperPath) {
429  commandLine.add(cmd);
430  }
431  commandLine.add("-r"); //NON-NLS
432  commandLine.add(hiveFilePath);
433  commandLine.add("-f"); //NON-NLS
434  commandLine.add(hiveFileType);
435 
436  ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
437  processBuilder.directory(regRipperHomeDir.toFile()); // RegRipper 2.8 has to be run from its own directory
438  processBuilder.redirectOutput(new File(outputFile));
439  processBuilder.redirectError(new File(errFile));
440  ExecUtil.execute(processBuilder, new DataSourceIngestModuleProcessTerminator(context));
441  } catch (IOException ex) {
442  logger.log(Level.SEVERE, "Unable to run RegRipper", ex); //NON-NLS
443  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName()));
444  }
445  }
446 
447  // @@@ VERIFY that we are doing the right thing when we parse multiple NTUSER.DAT
456  private boolean parseAutopsyPluginOutput(String regFilePath, AbstractFile regFile) {
457  FileInputStream fstream = null;
458  List<BlackboardArtifact> newArtifacts = new ArrayList<>();
459  try {
460  // Read the file in and create a Document and elements
461  File regfile = new File(regFilePath);
462  fstream = new FileInputStream(regfile);
463  String regString = new Scanner(fstream, "UTF-8").useDelimiter("\\Z").next(); //NON-NLS
464  String startdoc = "<?xml version=\"1.0\"?><document>"; //NON-NLS
465  String result = regString.replaceAll("----------------------------------------", "");
466  result = result.replaceAll("\\n", ""); //NON-NLS
467  result = result.replaceAll("\\r", ""); //NON-NLS
468  result = result.replaceAll("'", "&apos;"); //NON-NLS
469  result = result.replaceAll("&", "&amp;"); //NON-NLS
470  result = result.replace('\0', ' '); // NON-NLS
471  String enddoc = "</document>"; //NON-NLS
472  String stringdoc = startdoc + result + enddoc;
473  DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
474  Document doc = builder.parse(new InputSource(new StringReader(stringdoc)));
475 
476  // cycle through the elements in the doc
477  Element oroot = doc.getDocumentElement();
478  NodeList children = oroot.getChildNodes();
479  int len = children.getLength();
480  for (int i = 0; i < len; i++) {
481 
482  if (context.dataSourceIngestIsCancelled()) {
483  return false;
484  }
485 
486  Element tempnode = (Element) children.item(i);
487 
488  String dataType = tempnode.getNodeName();
489  NodeList timenodes = tempnode.getElementsByTagName("mtime"); //NON-NLS
490  Long mtime = null;
491  if (timenodes.getLength() > 0) {
492  Element timenode = (Element) timenodes.item(0);
493  String etime = timenode.getTextContent();
494  //sometimes etime will be an empty string and therefore can not be parsed into a date
495  if (etime != null && !etime.isEmpty()) {
496  try {
497  mtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(etime).getTime();
498  String Tempdate = mtime.toString();
499  mtime = Long.valueOf(Tempdate) / MS_IN_SEC;
500  } catch (ParseException ex) {
501  logger.log(Level.WARNING, "Failed to parse epoch time when parsing the registry.", ex); //NON-NLS
502  }
503  }
504  }
505 
506  NodeList artroots = tempnode.getElementsByTagName("artifacts"); //NON-NLS
507  if (artroots.getLength() == 0) {
508  // If there isn't an artifact node, skip this entry
509  continue;
510  }
511 
512  Element artroot = (Element) artroots.item(0);
513  NodeList myartlist = artroot.getChildNodes();
514  String parentModuleName = RecentActivityExtracterModuleFactory.getModuleName();
515 
516  // If all artifact nodes should really go under one Blackboard artifact, need to process it differently
517  switch (dataType) {
518  case "WinVersion": //NON-NLS
519  String version = "";
520  String systemRoot = "";
521  String productId = "";
522  String regOwner = "";
523  String regOrg = "";
524  Long installtime = null;
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();
532  if (value != null) {
533  value = value.trim();
534  }
535  String name = artnode.getAttribute("name"); //NON-NLS
536  if (name == null) {
537  continue;
538  }
539  switch (name) {
540  case "ProductName": // NON-NLS
541  version = value;
542  break;
543  case "CSDVersion": // NON-NLS
544  // This is dependant on the fact that ProductName shows up first in the module output
545  version = version + " " + value;
546  break;
547  case "SystemRoot": //NON-NLS
548  systemRoot = value;
549  break;
550  case "ProductId": //NON-NLS
551  productId = value;
552  break;
553  case "RegisteredOwner": //NON-NLS
554  regOwner = value;
555  break;
556  case "RegisteredOrganization": //NON-NLS
557  regOrg = value;
558  break;
559  case "InstallDate": //NON-NLS
560  if (value != null && !value.isEmpty()) {
561  try {
562  installtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(value).getTime();
563  String Tempdate = installtime.toString();
564  installtime = Long.valueOf(Tempdate) / MS_IN_SEC;
565  } catch (ParseException e) {
566  logger.log(Level.WARNING, "RegRipper::Conversion on DateTime -> ", e); //NON-NLS
567  }
568  }
569  break;
570  default:
571  break;
572  }
573  }
574  }
575  try {
576  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
577  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, version));
578  if (installtime != null) {
579  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, installtime));
580  }
581  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, systemRoot));
582  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PRODUCT_ID, parentModuleName, productId));
583  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_OWNER, parentModuleName, regOwner));
584  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ORGANIZATION, parentModuleName, regOrg));
585 
586  // Check if there is already an OS_INFO artifact for this file, and add to that if possible.
587  ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
588  if (results.isEmpty()) {
589  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
590  bbart.addAttributes(bbattributes);
591 
592  newArtifacts.add(bbart);
593  } else {
594  results.get(0).addAttributes(bbattributes);
595  }
596 
597  } catch (TskCoreException ex) {
598  logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard."); //NON-NLS
599  }
600  break;
601  case "Profiler": // NON-NLS
602  String os = "";
603  String procArch = "";
604  String tempDir = "";
605  for (int j = 0; j < myartlist.getLength(); j++) {
606  Node artchild = myartlist.item(j);
607  // If it has attributes, then it is an Element (based off API)
608  if (artchild.hasAttributes()) {
609  Element artnode = (Element) artchild;
610 
611  String value = artnode.getTextContent().trim();
612  String name = artnode.getAttribute("name"); //NON-NLS
613  switch (name) {
614  case "OS": // NON-NLS
615  os = value;
616  break;
617  case "PROCESSOR_ARCHITECTURE": // NON-NLS
618  procArch = value;
619  break;
620  case "PROCESSOR_IDENTIFIER": //NON-NLS
621  break;
622  case "TEMP": //NON-NLS
623  tempDir = value;
624  break;
625  default:
626  break;
627  }
628  }
629  }
630  try {
631  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
632  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VERSION, parentModuleName, os));
633  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE, parentModuleName, procArch));
634  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEMP_DIR, parentModuleName, tempDir));
635 
636  // Check if there is already an OS_INFO artifact for this file and add to that if possible
637  ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
638  if (results.isEmpty()) {
639  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
640  bbart.addAttributes(bbattributes);
641 
642  newArtifacts.add(bbart);
643  } else {
644  results.get(0).addAttributes(bbattributes);
645  }
646  } catch (TskCoreException ex) {
647  logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS
648  }
649  break;
650  case "CompName": // NON-NLS
651  String compName = "";
652  String domain = "";
653  for (int j = 0; j < myartlist.getLength(); j++) {
654  Node artchild = myartlist.item(j);
655  // If it has attributes, then it is an Element (based off API)
656  if (artchild.hasAttributes()) {
657  Element artnode = (Element) artchild;
658 
659  String value = artnode.getTextContent().trim();
660  String name = artnode.getAttribute("name"); //NON-NLS
661 
662  if (name.equals("ComputerName")) { // NON-NLS
663  compName = value;
664  } else if (name.equals("Domain")) { // NON-NLS
665  domain = value;
666  }
667  }
668  }
669  try {
670  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
671  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, compName));
672  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, parentModuleName, domain));
673 
674  // Check if there is already an OS_INFO artifact for this file and add to that if possible
675  ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
676  if (results.isEmpty()) {
677  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
678  bbart.addAttributes(bbattributes);
679 
680  newArtifacts.add(bbart);
681  } else {
682  results.get(0).addAttributes(bbattributes);
683  }
684  } catch (TskCoreException ex) {
685  logger.log(Level.SEVERE, "Error adding os info artifact to blackboard.", ex); //NON-NLS
686  }
687  break;
688  default:
689  for (int j = 0; j < myartlist.getLength(); j++) {
690  Node artchild = myartlist.item(j);
691  // If it has attributes, then it is an Element (based off API)
692  if (artchild.hasAttributes()) {
693  Element artnode = (Element) artchild;
694 
695  String value = artnode.getTextContent().trim();
696  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
697 
698  switch (dataType) {
699  case "recentdocs": //NON-NLS
700  // BlackboardArtifact bbart = tskCase.getContentById(orgId).newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
701  // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", dataType, mtime));
702  // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity", dataType, mtimeItem));
703  // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), "RecentActivity", dataType, value));
704  // bbart.addAttributes(bbattributes);
705  // @@@ BC: Why are we ignoring this...
706  break;
707  case "usb": //NON-NLS
708  try {
709  Long usbMtime = Long.parseLong(artnode.getAttribute("mtime")); //NON-NLS
710  usbMtime = Long.valueOf(usbMtime.toString());
711 
712  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
713  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime));
714  String dev = artnode.getAttribute("dev"); //NON-NLS
715  String make = "";
716  String model = dev;
717  if (dev.toLowerCase().contains("vid")) { //NON-NLS
718  USBInfo info = USB_MAPPER.parseAndLookup(dev);
719  if (info.getVendor() != null) {
720  make = info.getVendor();
721  }
722  if (info.getProduct() != null) {
723  model = info.getProduct();
724  }
725  }
726  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make));
727  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model));
728  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value));
729  bbart.addAttributes(bbattributes);
730 
731  newArtifacts.add(bbart);
732  } catch (TskCoreException ex) {
733  logger.log(Level.SEVERE, "Error adding device attached artifact to blackboard.", ex); //NON-NLS
734  }
735  break;
736  case "uninstall": //NON-NLS
737  Long itemMtime = null;
738  try {
739  String mTimeAttr = artnode.getAttribute("mtime");
740  if (mTimeAttr != null && !mTimeAttr.isEmpty()) {
741  itemMtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(mTimeAttr).getTime(); //NON-NLS
742  itemMtime /= MS_IN_SEC;
743  }
744  } catch (ParseException ex) {
745  logger.log(Level.SEVERE, "Failed to parse epoch time for installed program artifact.", ex); //NON-NLS
746  }
747 
748  try {
749  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, value));
750  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, itemMtime));
751  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG);
752  bbart.addAttributes(bbattributes);
753 
754  newArtifacts.add(bbart);
755  } catch (TskCoreException ex) {
756  logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard.", ex); //NON-NLS
757  }
758  break;
759  case "office": //NON-NLS
760  String officeName = artnode.getAttribute("name"); //NON-NLS
761 
762  try {
763  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
764  // @@@ BC: Consider removing this after some more testing. It looks like an Mtime associated with the root key and not the individual item
765  if (mtime != null) {
766  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, parentModuleName, mtime));
767  }
768  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, officeName));
769  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, parentModuleName, value));
770  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, artnode.getNodeName()));
771  bbart.addAttributes(bbattributes);
772 
773  newArtifacts.add(bbart);
774  } catch (TskCoreException ex) {
775  logger.log(Level.SEVERE, "Error adding recent object artifact to blackboard.", ex); //NON-NLS
776  }
777  break;
778 
779  case "ProcessorArchitecture": //NON-NLS
780  // Architecture is now included under Profiler
781  //try {
782  // String processorArchitecture = value;
783  // if (processorArchitecture.equals("AMD64"))
784  // processorArchitecture = "x86-64";
785 
786  // BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
787  // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE.getTypeID(), parentModuleName, processorArchitecture));
788  // bbart.addAttributes(bbattributes);
789  //} catch (TskCoreException ex) {
790  // logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS
791  //}
792  break;
793 
794  case "ProfileList": //NON-NLS
795  try {
796  String homeDir = value;
797  String sid = artnode.getAttribute("sid"); //NON-NLS
798  String username = artnode.getAttribute("username"); //NON-NLS
799  BlackboardArtifact bbart = null;
800  try {
801  //check if any of the existing artifacts match this username
802  ArrayList<BlackboardArtifact> existingArtifacts = currentCase.getSleuthkitCase().getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
803  for (BlackboardArtifact artifact : existingArtifacts) {
804  if (artifact.getDataSource().getId() == regFile.getDataSourceObjectId()) {
805  BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID));
806  if (attribute != null && attribute.getValueString().equals(sid)) {
807  bbart = artifact;
808  break;
809  }
810  }
811  }
812  } catch (TskCoreException ex) {
813  logger.log(Level.SEVERE, "Error getting existing os account artifact", ex);
814  }
815  if (bbart == null) {
816  //create new artifact
817  bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
818  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
819  parentModuleName, username));
820  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID,
821  parentModuleName, sid));
822  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
823  parentModuleName, homeDir));
824  } else {
825  //add attributes to existing artifact
826  BlackboardAttribute bbattr = bbart.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_NAME));
827 
828  if (bbattr == null) {
829  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
830  parentModuleName, username));
831  }
832  bbattr = bbart.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH));
833  if (bbattr == null) {
834  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
835  parentModuleName, homeDir));
836  }
837  }
838  bbart.addAttributes(bbattributes);
839  newArtifacts.add(bbart);
840  } catch (TskCoreException ex) {
841  logger.log(Level.SEVERE, "Error adding account artifact to blackboard.", ex); //NON-NLS
842  }
843  break;
844 
845  case "NtuserNetwork": // NON-NLS
846  try {
847  String localPath = artnode.getAttribute("localPath"); //NON-NLS
848  String remoteName = value;
849  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_REMOTE_DRIVE);
850  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH,
851  parentModuleName, localPath));
852  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH,
853  parentModuleName, remoteName));
854  bbart.addAttributes(bbattributes);
855  newArtifacts.add(bbart);
856  } catch (TskCoreException ex) {
857  logger.log(Level.SEVERE, "Error adding network artifact to blackboard.", ex); //NON-NLS
858  }
859  break;
860  case "SSID": // NON-NLS
861  String adapter = artnode.getAttribute("adapter"); //NON-NLS
862  try {
863  Long lastWriteTime = Long.parseLong(artnode.getAttribute("writeTime")); //NON-NLS
864  lastWriteTime = Long.valueOf(lastWriteTime.toString());
865  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SSID, parentModuleName, value));
866  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, lastWriteTime));
867  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, adapter));
868  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_WIFI_NETWORK);
869  bbart.addAttributes(bbattributes);
870  newArtifacts.add(bbart);
871  } catch (TskCoreException ex) {
872  logger.log(Level.SEVERE, "Error adding SSID artifact to blackboard.", ex); //NON-NLS
873  }
874  break;
875  case "shellfolders": // NON-NLS
876  // The User Shell Folders subkey stores the paths to Windows Explorer folders for the current user of the computer
877  // (https://technet.microsoft.com/en-us/library/Cc962613.aspx).
878  // No useful information. Skip.
879  break;
880 
881  default:
882  logger.log(Level.SEVERE, "Unrecognized node name: {0}", dataType); //NON-NLS
883  break;
884  }
885  }
886  }
887  break;
888  }
889  } // for
890  return true;
891  } catch (FileNotFoundException ex) {
892  logger.log(Level.WARNING, String.format("Error finding the registry file: %s", regFilePath), ex); //NON-NLS
893  } catch (SAXException ex) {
894  logger.log(Level.WARNING, String.format("Error parsing the registry XML: %s", regFilePath), ex); //NON-NLS
895  } catch (IOException ex) {
896  logger.log(Level.WARNING, String.format("Error building the document parser: %s", regFilePath), ex); //NON-NLS
897  } catch (ParserConfigurationException ex) {
898  logger.log(Level.WARNING, String.format("Error configuring the registry parser: %s", regFilePath), ex); //NON-NLS
899  } finally {
900  try {
901  if (fstream != null) {
902  fstream.close();
903  }
904  } catch (IOException ex) {
905  }
906 
907  postArtifacts(newArtifacts);
908  }
909  return false;
910  }
911 
921  private boolean parseSamPluginOutput(String regFilePath, AbstractFile regAbstractFile) {
922  File regfile = new File(regFilePath);
923  List<BlackboardArtifact> newArtifacts = new ArrayList<>();
924  try (BufferedReader bufferedReader = new BufferedReader(new FileReader(regfile))) {
925  // Read the file in and create a Document and elements
926  String userInfoSection = "User Information";
927  String previousLine = null;
928  String line = bufferedReader.readLine();
929  Set<Map<String, String>> userSet = new HashSet<>();
930  Map<String, List<String>> groupMap = null;
931  while (line != null) {
932  if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains(userInfoSection)) {
933  readUsers(bufferedReader, userSet);
934  }
935 
936  if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains("Group Membership Information")) {
937  groupMap = readGroups(bufferedReader);
938  }
939 
940  previousLine = line;
941  line = bufferedReader.readLine();
942  }
943  Map<String, Map<String, String>> userInfoMap = new HashMap<>();
944  //load all the user info which was read into a map
945  for (Map<String, String> userInfo : userSet) {
946  userInfoMap.put(userInfo.get(SID_KEY), userInfo);
947  }
948  //get all existing OS account artifacts
949  List<BlackboardArtifact> existingOsAccounts = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
950  for (BlackboardArtifact osAccount : existingOsAccounts) {
951  //if the OS Account artifact was from the same data source check the user id
952  if (osAccount.getDataSource().getId() == regAbstractFile.getDataSourceObjectId()) {
953  BlackboardAttribute existingUserId = osAccount.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID));
954  if (existingUserId != null) {
955  String userID = existingUserId.getValueString().trim();
956  Map<String, String> userInfo = userInfoMap.remove(userID);
957  //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
958  if (userInfo != null) {
959  osAccount.addAttributes(getAttributesForAccount(userInfo, groupMap.get(userID), true, regAbstractFile));
960  }
961  }
962  }
963  }
964 
965  //add remaining userinfos as accounts;
966  for (Map<String, String> userInfo : userInfoMap.values()) {
967  BlackboardArtifact bbart = regAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
968  bbart.addAttributes(getAttributesForAccount(userInfo, groupMap.get(userInfo.get(SID_KEY)), false, regAbstractFile));
969  // index the artifact for keyword search
970  newArtifacts.add(bbart);
971  }
972  return true;
973  } catch (FileNotFoundException ex) {
974  logger.log(Level.WARNING, "Error finding the registry file.", ex); //NON-NLS
975  } catch (IOException ex) {
976  logger.log(Level.WARNING, "Error building the document parser: {0}", ex); //NON-NLS
977  } catch (ParseException ex) {
978  logger.log(Level.WARNING, "Error parsing the the date from the registry file", ex); //NON-NLS
979  } catch (TskCoreException ex) {
980  logger.log(Level.WARNING, "Error updating TSK_OS_ACCOUNT artifacts to include newly parsed data.", ex); //NON-NLS
981  } finally {
982  postArtifacts(newArtifacts);
983  }
984  return false;
985  }
986 
998  Collection<BlackboardAttribute> getAttributesForAccount(Map<String, String> userInfo, List<String> groupList, boolean existingUser, AbstractFile regAbstractFile) throws ParseException {
999  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
1000 
1001  SimpleDateFormat regRipperTimeFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy 'Z'");
1002  regRipperTimeFormat.setTimeZone(getTimeZone("GMT"));
1003 
1004  if (!existingUser) {
1005  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID,
1006  getRAModuleName(), userInfo.get(SID_KEY)));
1007 
1008  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
1009  this.moduleName, userInfo.get(USERNAME_KEY)));
1010  }
1011 
1012  String value = userInfo.get(ACCOUNT_CREATED_KEY);
1013  if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
1014  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
1015  getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC));
1016  }
1017 
1018  value = userInfo.get(LAST_LOGIN_KEY);
1019  if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
1020  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
1021  getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC));
1022  }
1023 
1024  value = userInfo.get(LOGIN_COUNT_KEY);
1025  if (value != null && !value.isEmpty()) {
1026  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
1027  getRAModuleName(), Integer.parseInt(value)));
1028  }
1029 
1030  value = userInfo.get(ACCOUNT_TYPE_KEY);
1031  if (value != null && !value.isEmpty()) {
1032  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE,
1033  getRAModuleName(), value));
1034  }
1035 
1036  value = userInfo.get(USER_COMMENT_KEY);
1037  if (value != null && !value.isEmpty()) {
1038  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DESCRIPTION,
1039  getRAModuleName(), value));
1040  }
1041 
1042  value = userInfo.get(NAME_KEY);
1043  if (value != null && !value.isEmpty()) {
1044  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
1045  getRAModuleName(), value));
1046  }
1047 
1048  value = userInfo.get(INTERNET_NAME_KEY);
1049  if (value != null && !value.isEmpty()) {
1050  try {
1051  // Create an account for this email, if it doesn't already exist.
1052  Case.getCurrentCaseThrows()
1053  .getSleuthkitCase()
1054  .getCommunicationsManager()
1055  .createAccountFileInstance(Account.Type.EMAIL,
1056  value, getRAModuleName(), regAbstractFile);
1057  } catch (NoCurrentCaseException | TskCoreException ex) {
1058  logger.log(Level.SEVERE,
1059  String.format("Error adding email account with value "
1060  + "%s, to the case database for file %s [objId=%d]",
1061  value, regAbstractFile.getName(), regAbstractFile.getId()), ex);
1062  }
1063 
1064  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL,
1065  getRAModuleName(), value));
1066  }
1067 
1068  value = userInfo.get(FULL_NAME_KEY);
1069  if (value != null && !value.isEmpty()) {
1070  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DISPLAY_NAME,
1071  getRAModuleName(), value));
1072  }
1073 
1074  value = userInfo.get(PWD_RESET_KEY);
1075  if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
1076  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_PASSWORD_RESET,
1077  getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC));
1078  }
1079 
1080  value = userInfo.get(PASSWORD_HINT);
1081  if (value != null && !value.isEmpty()) {
1082  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_HINT,
1083  getRAModuleName(), value));
1084  }
1085 
1086  value = userInfo.get(PWD_FAILE_KEY);
1087  if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
1088  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_PASSWORD_FAIL,
1089  getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC));
1090  }
1091 
1092  String settingString = "";
1093  for (String setting : PASSWORD_SETTINGS_FLAGS) {
1094  if (userInfo.containsKey(setting)) {
1095  settingString += setting + ", ";
1096  }
1097  }
1098 
1099  if (!settingString.isEmpty()) {
1100  settingString = settingString.substring(0, settingString.length() - 2);
1101  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_SETTINGS,
1102  getRAModuleName(), settingString));
1103  }
1104 
1105  settingString = "";
1106  for (String setting : ACCOUNT_SETTINGS_FLAGS) {
1107  if (userInfo.containsKey(setting)) {
1108  settingString += setting + ", ";
1109  }
1110  }
1111 
1112  if (!settingString.isEmpty()) {
1113  settingString = settingString.substring(0, settingString.length() - 2);
1114  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ACCOUNT_SETTINGS,
1115  getRAModuleName(), settingString));
1116  }
1117 
1118  settingString = "";
1119  for (String setting : ACCOUNT_TYPE_FLAGS) {
1120  if (userInfo.containsKey(setting)) {
1121  settingString += setting + ", ";
1122  }
1123  }
1124 
1125  if (!settingString.isEmpty()) {
1126  settingString = settingString.substring(0, settingString.length() - 2);
1127  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_FLAG,
1128  getRAModuleName(), settingString));
1129  }
1130 
1131  if (groupList != null && groupList.isEmpty()) {
1132  String groups = "";
1133  for (String group : groupList) {
1134  groups += group + ", ";
1135  }
1136 
1137  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_GROUPS,
1138  getRAModuleName(), groups.substring(0, groups.length() - 2)));
1139  }
1140 
1141  return bbattributes;
1142  }
1143 
1155  private void readUsers(BufferedReader bufferedReader, Set<Map<String, String>> users) throws IOException {
1156  String line = bufferedReader.readLine();
1157  //read until end of file or next section divider
1158  String userName = "";
1159  String user_rid = "";
1160  while (line != null && !line.contains(SECTION_DIVIDER)) {
1161  //when a user name field exists read the name and id number
1162  if (line.contains(USERNAME_KEY)) {
1163  String regx = USERNAME_KEY + "\\s*?:";
1164  String userNameAndIdString = line.replaceAll(regx, "");
1165  userName = userNameAndIdString.substring(0, userNameAndIdString.lastIndexOf('[')).trim();
1166  user_rid = userNameAndIdString.substring(userNameAndIdString.lastIndexOf('['), userNameAndIdString.lastIndexOf(']'));
1167  } else if (line.contains(SID_KEY) && !userName.isEmpty()) {
1168  Map.Entry<String, String> entry = getSAMKeyValue(line);
1169 
1170  HashMap<String, String> userInfo = new HashMap<>();
1171  userInfo.put(USERNAME_KEY, userName);
1172  userInfo.put(RID_KEY, user_rid);
1173  userInfo.put(entry.getKey(), entry.getValue());
1174 
1175  //continue reading this users information until end of file or a blank line between users
1176  line = bufferedReader.readLine();
1177  while (line != null && !line.isEmpty()) {
1178  entry = getSAMKeyValue(line);
1179  if (entry != null) {
1180  userInfo.put(entry.getKey(), entry.getValue());
1181  }
1182  line = bufferedReader.readLine();
1183  }
1184  users.add(userInfo);
1185 
1186  userName = "";
1187  }
1188  line = bufferedReader.readLine();
1189  }
1190  }
1191 
1201  private void createRecentlyUsedArtifacts(String regFileName, AbstractFile regFile) throws FileNotFoundException, IOException {
1202  File regfile = new File(regFileName);
1203  try (BufferedReader reader = new BufferedReader(new FileReader(regfile))) {
1204  String line = reader.readLine();
1205  while (line != null) {
1206  line = line.trim();
1207 
1208  if (line.matches("^adoberdr v.*")) {
1209  parseAdobeMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Adobe());
1210  } else if (line.matches("^mpmru v.*")) {
1211  parseMediaPlayerMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Mediaplayer());
1212  } else if (line.matches("^trustrecords v.*")) {
1213  parseOfficeTrustRecords(regFile, reader, Bundle.Recently_Used_Artifacts_Office_Trustrecords());
1214  } else if (line.matches("^ArcHistory:")) {
1215  parse7ZipMRU(regFile, reader, Bundle.Recently_Used_Artifacts_ArcHistory());
1216  } else if (line.matches("^applets v.*")) {
1217  parseGenericMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Applets());
1218  } else if (line.matches("^mmc v.*")) {
1219  parseGenericMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Mmc());
1220  } else if (line.matches("^winrar v.*")) {
1221  parseWinRARMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Winrar());
1222  } else if (line.matches("^officedocs2010 v.*")) {
1223  parseOfficeDocs2010MRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Officedocs());
1224  }
1225  line = reader.readLine();
1226  }
1227  }
1228  }
1229 
1241  private void parseAdobeMRUList(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException {
1242  List<BlackboardArtifact> bbartifacts = new ArrayList<>();
1243  String line = reader.readLine();
1244  SimpleDateFormat adobePluginDateFormat = new SimpleDateFormat("yyyyMMddHHmmssZ", US);
1245  Long adobeUsedTime = Long.valueOf(0);
1246  while (!line.contains(SECTION_DIVIDER)) {
1247  line = reader.readLine();
1248  line = line.trim();
1249  if (line.matches("^Key name,file name,sDate,uFileSize,uPageCount")) {
1250  line = reader.readLine();
1251  // Columns are
1252  // Key name, file name, sDate, uFileSize, uPageCount
1253  while (!line.contains(SECTION_DIVIDER)) {
1254  // Split csv line, handles double quotes around individual file names
1255  // since file names can contain commas
1256  String tokens[] = line.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)");
1257  String fileName = tokens[1].substring(0, tokens[1].length() -1);
1258  fileName = fileName.replace("\"", "");
1259  if (fileName.charAt(0) == '/') {
1260  fileName = fileName.substring(1,fileName.length() - 1);
1261  fileName = fileName.replaceFirst("/", ":/");
1262  }
1263  // Check to see if more then 2 tokens, Date may not be populated, will default to 0
1264  if (tokens.length > 2) {
1265  // Time in the format of 20200131104456-05'00'
1266  try {
1267  String fileUsedTime = tokens[2].replaceAll("'","");
1268  Date usedDate = adobePluginDateFormat.parse(fileUsedTime);
1269  adobeUsedTime = usedDate.getTime()/1000;
1270  } catch (ParseException ex) {
1271  // catching error and displaying date that could not be parsed
1272  // we set the timestamp to 0 and continue on processing
1273  logger.log(Level.WARNING, String.format("Failed to parse date/time %s for adobe file artifact.", tokens[2]), ex); //NON-NLS
1274  }
1275  }
1276  Collection<BlackboardAttribute> attributes = new ArrayList<>();
1277  attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName));
1278  attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, getName(), adobeUsedTime));
1279  attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1280  BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1281  if(bba != null) {
1282  bbartifacts.add(bba);
1283  fileName = fileName.replace("\0", "");
1284  bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba);
1285  if (bba != null) {
1286  bbartifacts.add(bba);
1287  }
1288  }
1289  line = reader.readLine();
1290  }
1291  line = line.trim();
1292  }
1293  }
1294  if (!bbartifacts.isEmpty()) {
1295  postArtifacts(bbartifacts);
1296  }
1297  }
1298 
1310  private void parseMediaPlayerMRUList(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException {
1311  List<BlackboardArtifact> bbartifacts = new ArrayList<>();
1312  String line = reader.readLine();
1313  while (!line.contains(SECTION_DIVIDER)) {
1314  line = reader.readLine();
1315  line = line.trim();
1316  if (line.contains("LastWrite")) {
1317  line = reader.readLine();
1318  // Columns are
1319  // FileX -> <Media file>
1320  while (!line.contains(SECTION_DIVIDER) && !line.contains("RecentFileList has no values.")) {
1321  // Split line on "> " which is the record delimiter between position and file
1322  String tokens[] = line.split("> ");
1323  String fileName = tokens[1];
1324  Collection<BlackboardAttribute> attributes = new ArrayList<>();
1325  attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName));
1326  attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1327  BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1328  if(bba != null) {
1329  bbartifacts.add(bba);
1330  bba = createAssociatedArtifact(fileName, bba);
1331  if (bba != null) {
1332  bbartifacts.add(bba);
1333  bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba);
1334  if (bba != null) {
1335  bbartifacts.add(bba);
1336  }
1337  }
1338  }
1339  line = reader.readLine();
1340  }
1341  line = line.trim();
1342  }
1343  }
1344  if (!bbartifacts.isEmpty()) {
1345  postArtifacts(bbartifacts);
1346  }
1347  }
1348 
1360  private void parseGenericMRUList(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException {
1361  List<BlackboardArtifact> bbartifacts = new ArrayList<>();
1362  String line = reader.readLine();
1363  while (!line.contains(SECTION_DIVIDER)) {
1364  line = reader.readLine();
1365  line = line.trim();
1366  if (line.contains("LastWrite")) {
1367  line = reader.readLine();
1368  // Columns are
1369  // FileX -> <file>
1370  while (!line.contains(SECTION_DIVIDER) && !line.isEmpty() && !line.contains("Applets")) {
1371  // Split line on "> " which is the record delimiter between position and file
1372  String tokens[] = line.split("> ");
1373  String fileName = tokens[1];
1374  Collection<BlackboardAttribute> attributes = new ArrayList<>();
1375  attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName));
1376  attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1377  BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1378  if(bba != null) {
1379  bbartifacts.add(bba);
1380  bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba);
1381  if (bba != null) {
1382  bbartifacts.add(bba);
1383  }
1384  }
1385  line = reader.readLine();
1386  }
1387  line = line.trim();
1388  }
1389  }
1390  if (!bbartifacts.isEmpty()) {
1391  postArtifacts(bbartifacts);
1392  }
1393  }
1394 
1406  private void parseWinRARMRUList(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException {
1407  List<BlackboardArtifact> bbartifacts = new ArrayList<>();
1408  String line = reader.readLine();
1409  while (!line.contains(SECTION_DIVIDER)) {
1410  line = reader.readLine();
1411  line = line.trim();
1412  if (line.contains("LastWrite")) {
1413  line = reader.readLine();
1414  // Columns are
1415  // FileX -> <Media file>
1416  if (!line.isEmpty()) {
1417  while (!line.contains(SECTION_DIVIDER)) {
1418  // Split line on "> " which is the record delimiter between position and file
1419  String tokens[] = line.split("> ");
1420  String fileName = tokens[1];
1421  Collection<BlackboardAttribute> attributes = new ArrayList<>();
1422  attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName));
1423  attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1424  BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1425  if(bba != null) {
1426  bbartifacts.add(bba);
1427  bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba);
1428  if (bba != null) {
1429  bbartifacts.add(bba);
1430  }
1431  }
1432  line = reader.readLine();
1433  }
1434  }
1435  line = line.trim();
1436  }
1437  }
1438  if (!bbartifacts.isEmpty()) {
1439  postArtifacts(bbartifacts);
1440  }
1441  }
1442 
1454  private void parse7ZipMRU(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException {
1455  List<BlackboardArtifact> bbartifacts = new ArrayList<>();
1456  String line = reader.readLine();
1457  line = line.trim();
1458  if (!line.contains("PathHistory:")) {
1459  while (!line.contains("PathHistory:") && !line.isEmpty()) {
1460  // Columns are
1461  // <fileName>
1462  String fileName = line;
1463  Collection<BlackboardAttribute> attributes = new ArrayList<>();
1464  attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName));
1465  attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1466  BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1467  if (bba != null) {
1468  bbartifacts.add(bba);
1469  bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba);
1470  if (bba != null) {
1471  bbartifacts.add(bba);
1472  }
1473  }
1474  line = reader.readLine();
1475  line = line.trim();
1476  }
1477  }
1478  if (!bbartifacts.isEmpty()) {
1479  postArtifacts(bbartifacts);
1480  }
1481  }
1482 
1494  private void parseOfficeDocs2010MRUList(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException {
1495  List<BlackboardArtifact> bbartifacts = new ArrayList<>();
1496  String line = reader.readLine();
1497  line = line.trim();
1498  // Reading to the SECTION DIVIDER to get next section of records to process. Dates appear to have
1499  // multiple spaces in them that makes it harder to parse so next section will be easier to parse
1500  while (!line.contains(SECTION_DIVIDER)) {
1501  line = reader.readLine();
1502  }
1503  line = reader.readLine();
1504  while (!line.contains(SECTION_DIVIDER)) {
1505  // record has the following format
1506  // 1294283922|REG|||OfficeDocs2010 - F:\Windows_time_Rules_xp.doc
1507  String tokens[] = line.split("\\|");
1508  Long docDate = Long.valueOf(tokens[0]);
1509  String fileNameTokens[] = tokens[4].split(" - ");
1510  String fileName = fileNameTokens[1];
1511  Collection<BlackboardAttribute> attributes = new ArrayList<>();
1512  attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName));
1513  attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, getName(), docDate));
1514  attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1515  BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1516  if(bba != null) {
1517  bbartifacts.add(bba);
1518  bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba);
1519  if (bba != null) {
1520  bbartifacts.add(bba);
1521  }
1522  }
1523  line = reader.readLine();
1524  line = line.trim();
1525  }
1526  if (!bbartifacts.isEmpty()) {
1527  postArtifacts(bbartifacts);
1528  }
1529  }
1530 
1542  private void parseOfficeTrustRecords(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException {
1543  String userProfile = regFile.getParentPath();
1544  userProfile = userProfile.substring(0, userProfile.length() - 1);
1545  List<BlackboardArtifact> bbartifacts = new ArrayList<>();
1546  SimpleDateFormat pluginDateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy", US);
1547  Long usedTime = Long.valueOf(0);
1548  String line = reader.readLine();
1549  while (!line.contains(SECTION_DIVIDER)) {
1550  line = reader.readLine();
1551  line = line.trim();
1552  usedTime = Long.valueOf(0);
1553  if (!line.contains("**") && !line.contains("----------") && !line.contains("LastWrite")
1554  && !line.contains(SECTION_DIVIDER) && !line.isEmpty()) {
1555  // Columns are
1556  // Date : <File Name>/<Website>
1557  // Split line on " : " which is the record delimiter between position and file
1558  String fileName = null;
1559  String tokens[] = line.split(" : ");
1560  fileName = tokens[1];
1561  fileName = fileName.replace("%USERPROFILE%", userProfile);
1562  // Time in the format of Wed May 31 14:33:03 2017 Z
1563  try {
1564  String fileUsedTime = tokens[0].replaceAll(" Z","");
1565  Date usedDate = pluginDateFormat.parse(fileUsedTime);
1566  usedTime = usedDate.getTime()/1000;
1567  } catch (ParseException ex) {
1568  // catching error and displaying date that could not be parsed
1569  // we set the timestamp to 0 and continue on processing
1570  logger.log(Level.WARNING, String.format("Failed to parse date/time %s for TrustRecords artifact.", tokens[0]), ex); //NON-NLS
1571  }
1572  Collection<BlackboardAttribute> attributes = new ArrayList<>();
1573  attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName));
1574  attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, getName(), usedTime));
1575  attributes.add(new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1576  BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1577  if(bba != null) {
1578  bbartifacts.add(bba);
1579  bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba);
1580  if (bba != null) {
1581  bbartifacts.add(bba);
1582  }
1583  }
1584  line = line.trim();
1585  }
1586  }
1587  if (!bbartifacts.isEmpty()) {
1588  postArtifacts(bbartifacts);
1589  }
1590  }
1591 
1601  private BlackboardArtifact createAssociatedArtifact(String filePathName, BlackboardArtifact bba) {
1602  org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
1603  String fileName = FilenameUtils.getName(filePathName);
1604  String filePath = FilenameUtils.getPath(filePathName);
1605  List<AbstractFile> sourceFiles;
1606  try {
1607  sourceFiles = fileManager.findFiles(dataSource, fileName, filePath); //NON-NLS
1608  if (!sourceFiles.isEmpty()) {
1609  for (AbstractFile sourceFile : sourceFiles) {
1610  if (sourceFile.getParentPath().endsWith(filePath)) {
1611  Collection<BlackboardAttribute> bbattributes2 = new ArrayList<>();
1612  bbattributes2.addAll(Arrays.asList(
1613  new BlackboardAttribute(TSK_ASSOCIATED_ARTIFACT, this.getName(),
1614  bba.getArtifactID())));
1615 
1616  BlackboardArtifact associatedObjectBba = createArtifactWithAttributes(TSK_ASSOCIATED_OBJECT, sourceFile, bbattributes2);
1617  if (associatedObjectBba != null) {
1618  return associatedObjectBba;
1619  }
1620  }
1621  }
1622  }
1623  } catch (TskCoreException ex) {
1624  // only catching the error and displaying the message as the file may not exist on the
1625  // system anymore
1626  logger.log(Level.WARNING, String.format("Error finding actual file %s. file may not exist", filePathName)); //NON-NLS
1627  }
1628 
1629  return null;
1630  }
1631 
1640  void createShellBagArtifacts(AbstractFile regFile, List<ShellBag> shellbags) throws TskCoreException {
1641  List<BlackboardArtifact> artifacts = new ArrayList<>();
1642  try{
1643  for (ShellBag bag : shellbags) {
1644  Collection<BlackboardAttribute> attributes = new ArrayList<>();
1645  BlackboardArtifact artifact = regFile.newArtifact(getShellBagArtifact().getTypeID());
1646  attributes.add(new BlackboardAttribute(TSK_PATH, getName(), bag.getResource()));
1647  attributes.add(new BlackboardAttribute(getKeyAttribute(), getName(), bag.getKey()));
1648 
1649  long time;
1650  time = bag.getLastWrite();
1651  if (time != 0) {
1652  attributes.add(new BlackboardAttribute(getLastWriteAttribute(), getName(), time));
1653  }
1654 
1655  time = bag.getModified();
1656  if (time != 0) {
1657  attributes.add(new BlackboardAttribute(TSK_DATETIME_MODIFIED, getName(), time));
1658  }
1659 
1660  time = bag.getCreated();
1661  if (time != 0) {
1662  attributes.add(new BlackboardAttribute(TSK_DATETIME_CREATED, getName(), time));
1663  }
1664 
1665  time = bag.getAccessed();
1666  if (time != 0) {
1667  attributes.add(new BlackboardAttribute(TSK_DATETIME_ACCESSED, getName(), time));
1668  }
1669 
1670  artifact.addAttributes(attributes);
1671 
1672  artifacts.add(artifact);
1673  }
1674  } finally {
1675  postArtifacts(artifacts);
1676  }
1677  }
1678 
1687  private BlackboardArtifact.Type getShellBagArtifact() throws TskCoreException {
1688  if (shellBagArtifactType == null) {
1689  shellBagArtifactType = tskCase.getArtifactType(SHELLBAG_ARTIFACT_NAME);
1690 
1691  if(shellBagArtifactType == null) {
1692  try {
1693  tskCase.addBlackboardArtifactType(SHELLBAG_ARTIFACT_NAME, Bundle.Shellbag_Artifact_Display_Name()); //NON-NLS
1694  } catch (TskDataException ex) {
1695  // Artifact already exists
1696  logger.log(Level.INFO, String.format("%s may have already been defined for this case", SHELLBAG_ARTIFACT_NAME));
1697  }
1698 
1699  shellBagArtifactType = tskCase.getArtifactType(SHELLBAG_ARTIFACT_NAME);
1700  }
1701  }
1702 
1703  return shellBagArtifactType;
1704  }
1705 
1714  private BlackboardAttribute.Type getLastWriteAttribute() throws TskCoreException {
1715  if (shellBagLastWriteAttributeType == null) {
1716  try {
1717  shellBagLastWriteAttributeType = tskCase.addArtifactAttributeType(SHELLBAG_ATTRIBUTE_LAST_WRITE,
1718  BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME,
1719  Bundle.Shellbag_Last_Write_Attribute_Display_Name());
1720  } catch (TskDataException ex) {
1721  // Attribute already exists get it from the case
1722  shellBagLastWriteAttributeType = tskCase.getAttributeType(SHELLBAG_ATTRIBUTE_LAST_WRITE);
1723  }
1724  }
1725  return shellBagLastWriteAttributeType;
1726  }
1727 
1736  private BlackboardAttribute.Type getKeyAttribute() throws TskCoreException {
1737  if (shellBagKeyAttributeType == null) {
1738  try {
1739  shellBagKeyAttributeType = tskCase.addArtifactAttributeType(SHELLBAG_ATTRIBUTE_KEY,
1740  BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING,
1741  Bundle.Shellbag_Key_Attribute_Display_Name());
1742  } catch (TskDataException ex) {
1743  // The attribute already exists get it from the case
1744  shellBagKeyAttributeType = tskCase.getAttributeType(SHELLBAG_ATTRIBUTE_KEY);
1745  }
1746  }
1747  return shellBagKeyAttributeType;
1748  }
1749 
1759  Map<String, List<String>> readGroups(BufferedReader bufferedReader) throws IOException {
1760  Map<String, List<String>> groupMap = new HashMap<>();
1761 
1762  String line = bufferedReader.readLine();
1763 
1764  int userCount = 0;
1765  String groupName = null;
1766 
1767  while (line != null && !line.contains(SECTION_DIVIDER)) {
1768 
1769  if (line.contains("Group Name")) {
1770  String value = line.replaceAll("Group Name\\s*?:", "").trim();
1771  groupName = (value.replaceAll("\\[\\d*?\\]", "")).trim();
1772  int startIndex = value.indexOf('[');
1773  int endIndex = value.indexOf(']');
1774 
1775  if (startIndex != -1 && endIndex != -1) {
1776  String countStr = value.substring(startIndex + 1, endIndex);
1777  userCount = Integer.parseInt(countStr);
1778  }
1779  } else if (line.matches("Users\\s*?:")) {
1780  for (int i = 0; i < userCount; i++) {
1781  line = bufferedReader.readLine();
1782  if (line != null) {
1783  String sid = line.trim();
1784  List<String> groupList = groupMap.get(sid);
1785  if (groupList == null) {
1786  groupList = new ArrayList<>();
1787  groupMap.put(sid, groupList);
1788  }
1789  groupList.add(groupName);
1790  }
1791  }
1792  groupName = null;
1793  }
1794  line = bufferedReader.readLine();
1795  }
1796  return groupMap;
1797  }
1798 
1808  private Map.Entry<String, String> getSAMKeyValue(String line) {
1809  int index = line.indexOf(':');
1810  Map.Entry<String, String> returnValue = null;
1811  String key = null;
1812  String value = null;
1813 
1814  if (index != -1) {
1815  key = line.substring(0, index).trim();
1816  if (index + 1 < line.length()) {
1817  value = line.substring(index + 1).trim();
1818  } else {
1819  value = "";
1820  }
1821 
1822  } else if (line.contains("-->")) {
1823  key = line.replace("-->", "").trim();
1824  value = "true";
1825  }
1826 
1827  if (key != null) {
1828  returnValue = new AbstractMap.SimpleEntry<>(key, value);
1829  }
1830 
1831  return returnValue;
1832  }
1833 
1834  @Override
1835  public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
1836  this.dataSource = dataSource;
1837  this.context = context;
1838 
1839  progressBar.progress(Bundle.Progress_Message_Analyze_Registry());
1840  analyzeRegistryFiles();
1841 
1842  }
1843 
1847  private class RegOutputFiles {
1848 
1849  public String autopsyPlugins = "";
1850  public String fullPlugins = "";
1851  }
1852 }
synchronized List< AbstractFile > findFiles(String fileName)

Copyright © 2012-2020 Basis Technology. Generated on: Wed Apr 8 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.