Autopsy  4.13.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
ExtractRegistry.java
Go to the documentation of this file.
1 /*
2  *
3  * Autopsy Forensic Browser
4  *
5  * Copyright 2012-2019 Basis Technology Corp.
6  *
7  * Copyright 2012 42six Solutions.
8  * Contact: aebadirad <at> 42six <dot> com
9  * Project Contact/Architect: carrier <at> sleuthkit <dot> org
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  * http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  */
23 package org.sleuthkit.autopsy.recentactivity;
24 
25 import java.io.BufferedReader;
26 import java.io.File;
27 import java.io.FileInputStream;
28 import java.io.FileNotFoundException;
29 import java.io.FileReader;
30 import java.io.FileWriter;
31 import java.io.IOException;
32 import java.io.StringReader;
33 import java.text.ParseException;
34 import java.text.SimpleDateFormat;
35 import java.util.logging.Level;
36 import javax.xml.parsers.DocumentBuilder;
37 import javax.xml.parsers.DocumentBuilderFactory;
38 import javax.xml.parsers.ParserConfigurationException;
39 import org.openide.modules.InstalledFileLocator;
40 import org.openide.util.NbBundle;
48 import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
49 import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
50 import org.w3c.dom.Document;
51 import org.w3c.dom.Element;
52 import org.w3c.dom.Node;
53 import org.w3c.dom.NodeList;
54 import org.xml.sax.InputSource;
55 import org.xml.sax.SAXException;
56 import java.nio.file.Path;
57 import java.util.AbstractMap;
58 import java.util.ArrayList;
59 import java.util.List;
60 import java.util.Collection;
61 import java.util.HashMap;
62 import java.util.Map;
63 import java.util.Scanner;
64 import java.util.Set;
65 import java.util.HashSet;
66 import static java.util.TimeZone.getTimeZone;
67 import org.openide.util.Lookup;
72 import org.sleuthkit.datamodel.AbstractFile;
73 import org.sleuthkit.datamodel.BlackboardArtifact;
74 import org.sleuthkit.datamodel.BlackboardAttribute;
75 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED;
76 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED;
77 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED;
78 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH;
79 import org.sleuthkit.datamodel.Content;
80 import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
81 import org.sleuthkit.datamodel.Report;
82 import org.sleuthkit.datamodel.TskCoreException;
83 import org.sleuthkit.datamodel.TskDataException;
84 
91 @NbBundle.Messages({
92  "RegRipperNotFound=Autopsy RegRipper executable not found.",
93  "RegRipperFullNotFound=Full version RegRipper executable not found.",
94  "Progress_Message_Analyze_Registry=Analyzing Registry Files",
95  "Shellbag_Artifact_Display_Name=Shell Bags",
96  "Shellbag_Key_Attribute_Display_Name=Key",
97  "Shellbag_Last_Write_Attribute_Display_Name=Last Write"
98 })
99 class ExtractRegistry extends Extract {
100 
101  private static final String USERNAME_KEY = "Username"; //NON-NLS
102  private static final String SID_KEY = "SID"; //NON-NLS
103  private static final String RID_KEY = "RID"; //NON-NLS
104  private static final String ACCOUNT_CREATED_KEY = "Account Created"; //NON-NLS
105  private static final String LAST_LOGIN_KEY = "Last Login Date"; //NON-NLS
106  private static final String LOGIN_COUNT_KEY = "Login Count"; //NON-NLS
107  private static final String FULL_NAME_KEY = "Full Name"; //NON-NLS
108  private static final String USER_COMMENT_KEY = "User Comment"; //NON-NLS
109  private static final String ACCOUNT_TYPE_KEY = "Account Type"; //NON-NLS
110  private static final String NAME_KEY = "Name"; //NON-NLS
111  private static final String PWD_RESET_KEY = "Pwd Rest Date"; //NON-NLS
112  private static final String PWD_FAILE_KEY = "Pwd Fail Date"; //NON-NLS
113  private static final String INTERNET_NAME_KEY = "InternetName"; //NON-NLS
114  private static final String PWD_DOES_NOT_EXPIRE_KEY = "Password does not expire"; //NON-NLS
115  private static final String ACCOUNT_DISABLED_KEY = "Account Disabled"; //NON-NLS
116  private static final String PWD_NOT_REQUIRED_KEY = "Password not required"; //NON-NLS
117  private static final String NORMAL_ACCOUNT_KEY = "Normal user account"; //NON-NLS
118  private static final String HOME_DIRECTORY_REQUIRED_KEY = "Home directory required";
119  private static final String TEMPORARY_DUPLICATE_ACCOUNT = "Temporary duplicate account";
120  private static final String MNS_LOGON_ACCOUNT_KEY = "MNS logon user account";
121  private static final String INTERDOMAIN_TRUST_ACCOUNT_KEY = "Interdomain trust account";
122  private static final String WORKSTATION_TRUST_ACCOUNT = "Workstation trust account";
123  private static final String SERVER_TRUST_ACCOUNT = "Server trust account";
124  private static final String ACCOUNT_AUTO_LOCKED = "Account auto locked";
125  private static final String PASSWORD_HINT = "Password Hint";
126 
127  private static final String[] PASSWORD_SETTINGS_FLAGS = {PWD_DOES_NOT_EXPIRE_KEY, PWD_NOT_REQUIRED_KEY};
128  private static final String[] ACCOUNT_SETTINGS_FLAGS = {ACCOUNT_AUTO_LOCKED, HOME_DIRECTORY_REQUIRED_KEY, ACCOUNT_DISABLED_KEY};
129  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};
130 
131  final private static UsbDeviceIdMapper USB_MAPPER = new UsbDeviceIdMapper();
132  final private static String RIP_EXE = "rip.exe";
133  final private static String RIP_PL = "rip.pl";
134  final private static int MS_IN_SEC = 1000;
135  final private static String NEVER_DATE = "Never";
136  final private static String SECTION_DIVIDER = "-------------------------";
137  final private static Logger logger = Logger.getLogger(ExtractRegistry.class.getName());
138  private final List<String> rrCmd = new ArrayList<>();
139  private final List<String> rrFullCmd = new ArrayList<>();
140  private final Path rrHome; // Path to the Autopsy version of RegRipper
141  private final Path rrFullHome; // Path to the full version of RegRipper
142  private Content dataSource;
143  private IngestJobContext context;
144 
145  private static final String SHELLBAG_ARTIFACT_NAME = "RA_SHELL_BAG"; //NON-NLS
146  private static final String SHELLBAG_ATTRIBUTE_LAST_WRITE = "RA_SHELL_BAG_LAST_WRITE"; //NON-NLS
147  private static final String SHELLBAG_ATTRIBUTE_KEY= "RA_SHELL_BAG_KEY"; //NON-NLS
148 
149  BlackboardArtifact.Type shellBagArtifactType = null;
150  BlackboardAttribute.Type shellBagKeyAttributeType = null;
151  BlackboardAttribute.Type shellBagLastWriteAttributeType = null;
152 
153  ExtractRegistry() throws IngestModuleException {
154  moduleName = NbBundle.getMessage(ExtractIE.class, "ExtractRegistry.moduleName.text");
155 
156  final File rrRoot = InstalledFileLocator.getDefault().locate("rr", ExtractRegistry.class.getPackage().getName(), false); //NON-NLS
157  if (rrRoot == null) {
158  throw new IngestModuleException(Bundle.RegRipperNotFound());
159  }
160 
161  final File rrFullRoot = InstalledFileLocator.getDefault().locate("rr-full", ExtractRegistry.class.getPackage().getName(), false); //NON-NLS
162  if (rrFullRoot == null) {
163  throw new IngestModuleException(Bundle.RegRipperFullNotFound());
164  }
165 
166  String executableToRun = RIP_EXE;
167  if (!PlatformUtil.isWindowsOS()) {
168  executableToRun = RIP_PL;
169  }
170  rrHome = rrRoot.toPath();
171  String rrPath = rrHome.resolve(executableToRun).toString();
172  rrFullHome = rrFullRoot.toPath();
173 
174  if (!(new File(rrPath).exists())) {
175  throw new IngestModuleException(Bundle.RegRipperNotFound());
176  }
177  String rrFullPath = rrFullHome.resolve(executableToRun).toString();
178  if (!(new File(rrFullPath).exists())) {
179  throw new IngestModuleException(Bundle.RegRipperFullNotFound());
180  }
181  if (PlatformUtil.isWindowsOS()) {
182  rrCmd.add(rrPath);
183  rrFullCmd.add(rrFullPath);
184  } else {
185  String perl;
186  File usrBin = new File("/usr/bin/perl");
187  File usrLocalBin = new File("/usr/local/bin/perl");
188  if (usrBin.canExecute() && usrBin.exists() && !usrBin.isDirectory()) {
189  perl = "/usr/bin/perl";
190  } else if (usrLocalBin.canExecute() && usrLocalBin.exists() && !usrLocalBin.isDirectory()) {
191  perl = "/usr/local/bin/perl";
192  } else {
193  throw new IngestModuleException("perl not found in your system");
194  }
195  rrCmd.add(perl);
196  rrCmd.add(rrPath);
197  rrFullCmd.add(perl);
198  rrFullCmd.add(rrFullPath);
199  }
200  }
201 
205  private List<AbstractFile> findRegistryFiles() {
206  List<AbstractFile> allRegistryFiles = new ArrayList<>();
207  org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
208 
209  // find the user-specific ntuser-dat files
210  try {
211  allRegistryFiles.addAll(fileManager.findFiles(dataSource, "ntuser.dat")); //NON-NLS
212  } catch (TskCoreException ex) {
213  logger.log(Level.WARNING, "Error fetching 'ntuser.dat' file."); //NON-NLS
214  }
215 
216  // find the user-specific ntuser-dat files
217  try {
218  allRegistryFiles.addAll(fileManager.findFiles(dataSource, "usrclass.dat")); //NON-NLS
219  } catch (TskCoreException ex) {
220  logger.log(Level.WARNING, String.format("Error finding 'usrclass.dat' files."), ex); //NON-NLS
221  }
222 
223  // find the system hives'
224  String[] regFileNames = new String[]{"system", "software", "security", "sam"}; //NON-NLS
225  for (String regFileName : regFileNames) {
226  try {
227  allRegistryFiles.addAll(fileManager.findFiles(dataSource, regFileName, "/system32/config")); //NON-NLS
228  } catch (TskCoreException ex) {
229  String msg = NbBundle.getMessage(this.getClass(),
230  "ExtractRegistry.findRegFiles.errMsg.errReadingFile", regFileName);
231  logger.log(Level.WARNING, msg, ex);
232  this.addErrorMessage(this.getName() + ": " + msg);
233  }
234  }
235  return allRegistryFiles;
236  }
237 
242  private void analyzeRegistryFiles() {
243  List<AbstractFile> allRegistryFiles = findRegistryFiles();
244 
245  // open the log file
246  FileWriter logFile = null;
247  try {
248  logFile = new FileWriter(RAImageIngestModule.getRAOutputPath(currentCase, "reg") + File.separator + "regripper-info.txt"); //NON-NLS
249  } catch (IOException ex) {
250  logger.log(Level.SEVERE, null, ex);
251  }
252 
253  for (AbstractFile regFile : allRegistryFiles) {
254  String regFileName = regFile.getName();
255  long regFileId = regFile.getId();
256  String regFileNameLocal = RAImageIngestModule.getRATempPath(currentCase, "reg") + File.separator + regFileName;
257  String outputPathBase = RAImageIngestModule.getRAOutputPath(currentCase, "reg") + File.separator + regFileName + "-regripper-" + Long.toString(regFileId); //NON-NLS
258  File regFileNameLocalFile = new File(regFileNameLocal);
259  try {
260  ContentUtils.writeToFile(regFile, regFileNameLocalFile, context::dataSourceIngestIsCancelled);
261  } catch (ReadContentInputStreamException ex) {
262  logger.log(Level.WARNING, String.format("Error reading registry file '%s' (id=%d).",
263  regFile.getName(), regFileId), ex); //NON-NLS
264  this.addErrorMessage(
265  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
266  this.getName(), regFileName));
267  continue;
268  } catch (IOException ex) {
269  logger.log(Level.SEVERE, String.format("Error writing temp registry file '%s' for registry file '%s' (id=%d).",
270  regFileNameLocal, regFile.getName(), regFileId), ex); //NON-NLS
271  this.addErrorMessage(
272  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
273  this.getName(), regFileName));
274  continue;
275  }
276 
277  if (context.dataSourceIngestIsCancelled()) {
278  break;
279  }
280 
281  try {
282  if (logFile != null) {
283  logFile.write(Long.toString(regFileId) + "\t" + regFile.getUniquePath() + "\n");
284  }
285  } catch (TskCoreException | IOException ex) {
286  logger.log(Level.SEVERE, null, ex);
287  }
288 
289  logger.log(Level.INFO, "{0}- Now getting registry information from {1}", new Object[]{moduleName, regFileNameLocal}); //NON-NLS
290  RegOutputFiles regOutputFiles = ripRegistryFile(regFileNameLocal, outputPathBase);
291  if (context.dataSourceIngestIsCancelled()) {
292  break;
293  }
294 
295  // parse the autopsy-specific output
296  if (regOutputFiles.autopsyPlugins.isEmpty() == false && parseAutopsyPluginOutput(regOutputFiles.autopsyPlugins, regFile) == false) {
297  this.addErrorMessage(
298  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.failedParsingResults",
299  this.getName(), regFileName));
300  }
301 
302  // create a report for the full output
303  if (!regOutputFiles.fullPlugins.isEmpty()) {
304  //parse the full regripper output from SAM hive files
305  if (regFileNameLocal.toLowerCase().contains("sam") && parseSamPluginOutput(regOutputFiles.fullPlugins, regFile) == false) {
306  this.addErrorMessage(
307  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.failedParsingResults",
308  this.getName(), regFileName));
309  } else if (regFileNameLocal.toLowerCase().contains("ntuser") || regFileNameLocal.toLowerCase().contains("usrclass")) {
310  try {
311  List<ShellBag> shellbags = ShellBagParser.parseShellbagOutput(regOutputFiles.fullPlugins);
312  createShellBagArtifacts(regFile, shellbags);
313  } catch (IOException | TskCoreException ex) {
314  logger.log(Level.WARNING, String.format("Unable to get shell bags from file %s", regOutputFiles.fullPlugins), ex);
315  }
316  }
317  try {
318  Report report = currentCase.addReport(regOutputFiles.fullPlugins,
319  NbBundle.getMessage(this.getClass(), "ExtractRegistry.parentModuleName.noSpace"),
320  "RegRipper " + regFile.getUniquePath(), regFile); //NON-NLS
321 
322  // Index the report content so that it will be available for keyword search.
323  KeywordSearchService searchService = Lookup.getDefault().lookup(KeywordSearchService.class);
324  if (null == searchService) {
325  logger.log(Level.WARNING, "Keyword search service not found. Report will not be indexed");
326  } else {
327  searchService.index(report);
328  report.close();
329  }
330  } catch (TskCoreException e) {
331  this.addErrorMessage("Error adding regripper output as Autopsy report: " + e.getLocalizedMessage()); //NON-NLS
332  }
333  }
334  // delete the hive
335  regFileNameLocalFile.delete();
336  }
337 
338  try {
339  if (logFile != null) {
340  logFile.close();
341  }
342  } catch (IOException ex) {
343  logger.log(Level.SEVERE, null, ex);
344  }
345  }
346 
354  private RegOutputFiles ripRegistryFile(String regFilePath, String outFilePathBase) {
355  String autopsyType = ""; // Type argument for rr for autopsy-specific modules
356  String fullType; // Type argument for rr for full set of modules
357 
358  RegOutputFiles regOutputFiles = new RegOutputFiles();
359 
360  if (regFilePath.toLowerCase().contains("system")) { //NON-NLS
361  autopsyType = "autopsysystem"; //NON-NLS
362  fullType = "system"; //NON-NLS
363  } else if (regFilePath.toLowerCase().contains("software")) { //NON-NLS
364  autopsyType = "autopsysoftware"; //NON-NLS
365  fullType = "software"; //NON-NLS
366  } else if (regFilePath.toLowerCase().contains("ntuser")) { //NON-NLS
367  autopsyType = "autopsyntuser"; //NON-NLS
368  fullType = "ntuser"; //NON-NLS
369  } else if (regFilePath.toLowerCase().contains("sam")) { //NON-NLS
370  //fullType sam output files are parsed for user information
371  fullType = "sam"; //NON-NLS
372  } else if (regFilePath.toLowerCase().contains("security")) { //NON-NLS
373  fullType = "security"; //NON-NLS
374  }else if (regFilePath.toLowerCase().contains("usrclass")) { //NON-NLS
375  fullType = "usrclass"; //NON-NLS
376  } else {
377  return regOutputFiles;
378  }
379 
380  // run the autopsy-specific set of modules
381  if (!autopsyType.isEmpty()) {
382  regOutputFiles.autopsyPlugins = outFilePathBase + "-autopsy.txt"; //NON-NLS
383  String errFilePath = outFilePathBase + "-autopsy.err.txt"; //NON-NLS
384  logger.log(Level.INFO, "Writing RegRipper results to: {0}", regOutputFiles.autopsyPlugins); //NON-NLS
385  executeRegRipper(rrCmd, rrHome, regFilePath, autopsyType, regOutputFiles.autopsyPlugins, errFilePath);
386  }
387  if (context.dataSourceIngestIsCancelled()) {
388  return regOutputFiles;
389  }
390 
391  // run the full set of rr modules
392  if (!fullType.isEmpty()) {
393  regOutputFiles.fullPlugins = outFilePathBase + "-full.txt"; //NON-NLS
394  String errFilePath = outFilePathBase + "-full.err.txt"; //NON-NLS
395  logger.log(Level.INFO, "Writing Full RegRipper results to: {0}", regOutputFiles.fullPlugins); //NON-NLS
396  executeRegRipper(rrFullCmd, rrFullHome, regFilePath, fullType, regOutputFiles.fullPlugins, errFilePath);
397  }
398  return regOutputFiles;
399  }
400 
401  private void executeRegRipper(List<String> regRipperPath, Path regRipperHomeDir, String hiveFilePath, String hiveFileType, String outputFile, String errFile) {
402  try {
403  List<String> commandLine = new ArrayList<>();
404  for (String cmd : regRipperPath) {
405  commandLine.add(cmd);
406  }
407  commandLine.add("-r"); //NON-NLS
408  commandLine.add(hiveFilePath);
409  commandLine.add("-f"); //NON-NLS
410  commandLine.add(hiveFileType);
411 
412  ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
413  processBuilder.directory(regRipperHomeDir.toFile()); // RegRipper 2.8 has to be run from its own directory
414  processBuilder.redirectOutput(new File(outputFile));
415  processBuilder.redirectError(new File(errFile));
416  ExecUtil.execute(processBuilder, new DataSourceIngestModuleProcessTerminator(context));
417  } catch (IOException ex) {
418  logger.log(Level.SEVERE, "Unable to run RegRipper", ex); //NON-NLS
419  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName()));
420  }
421  }
422 
423  // @@@ VERIFY that we are doing the right thing when we parse multiple NTUSER.DAT
432  private boolean parseAutopsyPluginOutput(String regFilePath, AbstractFile regFile) {
433  FileInputStream fstream = null;
434  List<BlackboardArtifact> newArtifacts = new ArrayList<>();
435  try {
436  // Read the file in and create a Document and elements
437  File regfile = new File(regFilePath);
438  fstream = new FileInputStream(regfile);
439  String regString = new Scanner(fstream, "UTF-8").useDelimiter("\\Z").next(); //NON-NLS
440  String startdoc = "<?xml version=\"1.0\"?><document>"; //NON-NLS
441  String result = regString.replaceAll("----------------------------------------", "");
442  result = result.replaceAll("\\n", ""); //NON-NLS
443  result = result.replaceAll("\\r", ""); //NON-NLS
444  result = result.replaceAll("'", "&apos;"); //NON-NLS
445  result = result.replaceAll("&", "&amp;"); //NON-NLS
446  result = result.replace('\0', ' '); // NON-NLS
447  String enddoc = "</document>"; //NON-NLS
448  String stringdoc = startdoc + result + enddoc;
449  DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
450  Document doc = builder.parse(new InputSource(new StringReader(stringdoc)));
451 
452  // cycle through the elements in the doc
453  Element oroot = doc.getDocumentElement();
454  NodeList children = oroot.getChildNodes();
455  int len = children.getLength();
456  for (int i = 0; i < len; i++) {
457 
458  if (context.dataSourceIngestIsCancelled()) {
459  return false;
460  }
461 
462  Element tempnode = (Element) children.item(i);
463 
464  String dataType = tempnode.getNodeName();
465  NodeList timenodes = tempnode.getElementsByTagName("mtime"); //NON-NLS
466  Long mtime = null;
467  if (timenodes.getLength() > 0) {
468  Element timenode = (Element) timenodes.item(0);
469  String etime = timenode.getTextContent();
470  //sometimes etime will be an empty string and therefore can not be parsed into a date
471  if (etime != null && !etime.isEmpty()) {
472  try {
473  mtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(etime).getTime();
474  String Tempdate = mtime.toString();
475  mtime = Long.valueOf(Tempdate) / MS_IN_SEC;
476  } catch (ParseException ex) {
477  logger.log(Level.WARNING, "Failed to parse epoch time when parsing the registry.", ex); //NON-NLS
478  }
479  }
480  }
481 
482  NodeList artroots = tempnode.getElementsByTagName("artifacts"); //NON-NLS
483  if (artroots.getLength() == 0) {
484  // If there isn't an artifact node, skip this entry
485  continue;
486  }
487 
488  Element artroot = (Element) artroots.item(0);
489  NodeList myartlist = artroot.getChildNodes();
490  String parentModuleName = RecentActivityExtracterModuleFactory.getModuleName();
491 
492  // If all artifact nodes should really go under one Blackboard artifact, need to process it differently
493  switch (dataType) {
494  case "WinVersion": //NON-NLS
495  String version = "";
496  String systemRoot = "";
497  String productId = "";
498  String regOwner = "";
499  String regOrg = "";
500  Long installtime = null;
501  for (int j = 0; j < myartlist.getLength(); j++) {
502  Node artchild = myartlist.item(j);
503  // If it has attributes, then it is an Element (based off API)
504  if (artchild.hasAttributes()) {
505  Element artnode = (Element) artchild;
506 
507  String value = artnode.getTextContent();
508  if (value != null) {
509  value = value.trim();
510  }
511  String name = artnode.getAttribute("name"); //NON-NLS
512  if (name == null) {
513  continue;
514  }
515  switch (name) {
516  case "ProductName": // NON-NLS
517  version = value;
518  break;
519  case "CSDVersion": // NON-NLS
520  // This is dependant on the fact that ProductName shows up first in the module output
521  version = version + " " + value;
522  break;
523  case "SystemRoot": //NON-NLS
524  systemRoot = value;
525  break;
526  case "ProductId": //NON-NLS
527  productId = value;
528  break;
529  case "RegisteredOwner": //NON-NLS
530  regOwner = value;
531  break;
532  case "RegisteredOrganization": //NON-NLS
533  regOrg = value;
534  break;
535  case "InstallDate": //NON-NLS
536  if (value != null && !value.isEmpty()) {
537  try {
538  installtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(value).getTime();
539  String Tempdate = installtime.toString();
540  installtime = Long.valueOf(Tempdate) / MS_IN_SEC;
541  } catch (ParseException e) {
542  logger.log(Level.WARNING, "RegRipper::Conversion on DateTime -> ", e); //NON-NLS
543  }
544  }
545  break;
546  default:
547  break;
548  }
549  }
550  }
551  try {
552  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
553  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, version));
554  if (installtime != null) {
555  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, installtime));
556  }
557  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, systemRoot));
558  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PRODUCT_ID, parentModuleName, productId));
559  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_OWNER, parentModuleName, regOwner));
560  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ORGANIZATION, parentModuleName, regOrg));
561 
562  // Check if there is already an OS_INFO artifact for this file, and add to that if possible.
563  ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
564  if (results.isEmpty()) {
565  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
566  bbart.addAttributes(bbattributes);
567 
568  newArtifacts.add(bbart);
569  } else {
570  results.get(0).addAttributes(bbattributes);
571  }
572 
573  } catch (TskCoreException ex) {
574  logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard."); //NON-NLS
575  }
576  break;
577  case "Profiler": // NON-NLS
578  String os = "";
579  String procArch = "";
580  String tempDir = "";
581  for (int j = 0; j < myartlist.getLength(); j++) {
582  Node artchild = myartlist.item(j);
583  // If it has attributes, then it is an Element (based off API)
584  if (artchild.hasAttributes()) {
585  Element artnode = (Element) artchild;
586 
587  String value = artnode.getTextContent().trim();
588  String name = artnode.getAttribute("name"); //NON-NLS
589  switch (name) {
590  case "OS": // NON-NLS
591  os = value;
592  break;
593  case "PROCESSOR_ARCHITECTURE": // NON-NLS
594  procArch = value;
595  break;
596  case "PROCESSOR_IDENTIFIER": //NON-NLS
597  break;
598  case "TEMP": //NON-NLS
599  tempDir = value;
600  break;
601  default:
602  break;
603  }
604  }
605  }
606  try {
607  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
608  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VERSION, parentModuleName, os));
609  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE, parentModuleName, procArch));
610  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEMP_DIR, parentModuleName, tempDir));
611 
612  // Check if there is already an OS_INFO artifact for this file and add to that if possible
613  ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
614  if (results.isEmpty()) {
615  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
616  bbart.addAttributes(bbattributes);
617 
618  newArtifacts.add(bbart);
619  } else {
620  results.get(0).addAttributes(bbattributes);
621  }
622  } catch (TskCoreException ex) {
623  logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS
624  }
625  break;
626  case "CompName": // NON-NLS
627  String compName = "";
628  String domain = "";
629  for (int j = 0; j < myartlist.getLength(); j++) {
630  Node artchild = myartlist.item(j);
631  // If it has attributes, then it is an Element (based off API)
632  if (artchild.hasAttributes()) {
633  Element artnode = (Element) artchild;
634 
635  String value = artnode.getTextContent().trim();
636  String name = artnode.getAttribute("name"); //NON-NLS
637 
638  if (name.equals("ComputerName")) { // NON-NLS
639  compName = value;
640  } else if (name.equals("Domain")) { // NON-NLS
641  domain = value;
642  }
643  }
644  }
645  try {
646  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
647  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, compName));
648  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, parentModuleName, domain));
649 
650  // Check if there is already an OS_INFO artifact for this file and add to that if possible
651  ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
652  if (results.isEmpty()) {
653  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
654  bbart.addAttributes(bbattributes);
655 
656  newArtifacts.add(bbart);
657  } else {
658  results.get(0).addAttributes(bbattributes);
659  }
660  } catch (TskCoreException ex) {
661  logger.log(Level.SEVERE, "Error adding os info artifact to blackboard.", ex); //NON-NLS
662  }
663  break;
664  default:
665  for (int j = 0; j < myartlist.getLength(); j++) {
666  Node artchild = myartlist.item(j);
667  // If it has attributes, then it is an Element (based off API)
668  if (artchild.hasAttributes()) {
669  Element artnode = (Element) artchild;
670 
671  String value = artnode.getTextContent().trim();
672  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
673 
674  switch (dataType) {
675  case "recentdocs": //NON-NLS
676  // BlackboardArtifact bbart = tskCase.getContentById(orgId).newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
677  // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", dataType, mtime));
678  // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity", dataType, mtimeItem));
679  // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), "RecentActivity", dataType, value));
680  // bbart.addAttributes(bbattributes);
681  // @@@ BC: Why are we ignoring this...
682  break;
683  case "usb": //NON-NLS
684  try {
685  Long usbMtime = Long.parseLong(artnode.getAttribute("mtime")); //NON-NLS
686  usbMtime = Long.valueOf(usbMtime.toString());
687 
688  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
689  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime));
690  String dev = artnode.getAttribute("dev"); //NON-NLS
691  String make = "";
692  String model = dev;
693  if (dev.toLowerCase().contains("vid")) { //NON-NLS
694  USBInfo info = USB_MAPPER.parseAndLookup(dev);
695  if (info.getVendor() != null) {
696  make = info.getVendor();
697  }
698  if (info.getProduct() != null) {
699  model = info.getProduct();
700  }
701  }
702  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make));
703  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model));
704  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value));
705  bbart.addAttributes(bbattributes);
706 
707  newArtifacts.add(bbart);
708  } catch (TskCoreException ex) {
709  logger.log(Level.SEVERE, "Error adding device attached artifact to blackboard.", ex); //NON-NLS
710  }
711  break;
712  case "uninstall": //NON-NLS
713  Long itemMtime = null;
714  try {
715  String mTimeAttr = artnode.getAttribute("mtime");
716  if (mTimeAttr != null && !mTimeAttr.isEmpty()) {
717  itemMtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(mTimeAttr).getTime(); //NON-NLS
718  itemMtime /= MS_IN_SEC;
719  }
720  } catch (ParseException ex) {
721  logger.log(Level.SEVERE, "Failed to parse epoch time for installed program artifact.", ex); //NON-NLS
722  }
723 
724  try {
725  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, value));
726  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, itemMtime));
727  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG);
728  bbart.addAttributes(bbattributes);
729 
730  newArtifacts.add(bbart);
731  } catch (TskCoreException ex) {
732  logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard.", ex); //NON-NLS
733  }
734  break;
735  case "office": //NON-NLS
736  String officeName = artnode.getAttribute("name"); //NON-NLS
737 
738  try {
739  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
740  // @@@ BC: Consider removing this after some more testing. It looks like an Mtime associated with the root key and not the individual item
741  if (mtime != null) {
742  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, parentModuleName, mtime));
743  }
744  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, officeName));
745  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, parentModuleName, value));
746  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, artnode.getNodeName()));
747  bbart.addAttributes(bbattributes);
748 
749  newArtifacts.add(bbart);
750  } catch (TskCoreException ex) {
751  logger.log(Level.SEVERE, "Error adding recent object artifact to blackboard.", ex); //NON-NLS
752  }
753  break;
754 
755  case "ProcessorArchitecture": //NON-NLS
756  // Architecture is now included under Profiler
757  //try {
758  // String processorArchitecture = value;
759  // if (processorArchitecture.equals("AMD64"))
760  // processorArchitecture = "x86-64";
761 
762  // BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
763  // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE.getTypeID(), parentModuleName, processorArchitecture));
764  // bbart.addAttributes(bbattributes);
765  //} catch (TskCoreException ex) {
766  // logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS
767  //}
768  break;
769 
770  case "ProfileList": //NON-NLS
771  try {
772  String homeDir = value;
773  String sid = artnode.getAttribute("sid"); //NON-NLS
774  String username = artnode.getAttribute("username"); //NON-NLS
775  BlackboardArtifact bbart = null;
776  try {
777  //check if any of the existing artifacts match this username
778  ArrayList<BlackboardArtifact> existingArtifacts = currentCase.getSleuthkitCase().getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
779  for (BlackboardArtifact artifact : existingArtifacts) {
780  if (artifact.getDataSource().getId() == regFile.getDataSourceObjectId()) {
781  BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID));
782  if (attribute != null && attribute.getValueString().equals(sid)) {
783  bbart = artifact;
784  break;
785  }
786  }
787  }
788  } catch (TskCoreException ex) {
789  logger.log(Level.SEVERE, "Error getting existing os account artifact", ex);
790  }
791  if (bbart == null) {
792  //create new artifact
793  bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
794  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
795  parentModuleName, username));
796  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID,
797  parentModuleName, sid));
798  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
799  parentModuleName, homeDir));
800  } else {
801  //add attributes to existing artifact
802  BlackboardAttribute bbattr = bbart.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_NAME));
803 
804  if (bbattr == null) {
805  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
806  parentModuleName, username));
807  }
808  bbattr = bbart.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH));
809  if (bbattr == null) {
810  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
811  parentModuleName, homeDir));
812  }
813  }
814  bbart.addAttributes(bbattributes);
815  newArtifacts.add(bbart);
816  } catch (TskCoreException ex) {
817  logger.log(Level.SEVERE, "Error adding account artifact to blackboard.", ex); //NON-NLS
818  }
819  break;
820 
821  case "NtuserNetwork": // NON-NLS
822  try {
823  String localPath = artnode.getAttribute("localPath"); //NON-NLS
824  String remoteName = value;
825  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_REMOTE_DRIVE);
826  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH,
827  parentModuleName, localPath));
828  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH,
829  parentModuleName, remoteName));
830  bbart.addAttributes(bbattributes);
831  newArtifacts.add(bbart);
832  } catch (TskCoreException ex) {
833  logger.log(Level.SEVERE, "Error adding network artifact to blackboard.", ex); //NON-NLS
834  }
835  break;
836  case "SSID": // NON-NLS
837  String adapter = artnode.getAttribute("adapter"); //NON-NLS
838  try {
839  Long lastWriteTime = Long.parseLong(artnode.getAttribute("writeTime")); //NON-NLS
840  lastWriteTime = Long.valueOf(lastWriteTime.toString());
841  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SSID, parentModuleName, value));
842  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, lastWriteTime));
843  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, adapter));
844  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_WIFI_NETWORK);
845  bbart.addAttributes(bbattributes);
846  newArtifacts.add(bbart);
847  } catch (TskCoreException ex) {
848  logger.log(Level.SEVERE, "Error adding SSID artifact to blackboard.", ex); //NON-NLS
849  }
850  break;
851  case "shellfolders": // NON-NLS
852  // The User Shell Folders subkey stores the paths to Windows Explorer folders for the current user of the computer
853  // (https://technet.microsoft.com/en-us/library/Cc962613.aspx).
854  // No useful information. Skip.
855  break;
856 
857  default:
858  logger.log(Level.SEVERE, "Unrecognized node name: {0}", dataType); //NON-NLS
859  break;
860  }
861  }
862  }
863  break;
864  }
865  } // for
866  return true;
867  } catch (FileNotFoundException ex) {
868  logger.log(Level.WARNING, String.format("Error finding the registry file: %s", regFilePath), ex); //NON-NLS
869  } catch (SAXException ex) {
870  logger.log(Level.WARNING, String.format("Error parsing the registry XML: %s", regFilePath), ex); //NON-NLS
871  } catch (IOException ex) {
872  logger.log(Level.WARNING, String.format("Error building the document parser: %s", regFilePath), ex); //NON-NLS
873  } catch (ParserConfigurationException ex) {
874  logger.log(Level.WARNING, String.format("Error configuring the registry parser: %s", regFilePath), ex); //NON-NLS
875  } finally {
876  try {
877  if (fstream != null) {
878  fstream.close();
879  }
880  } catch (IOException ex) {
881  }
882 
883  postArtifacts(newArtifacts);
884  }
885  return false;
886  }
887 
897  private boolean parseSamPluginOutput(String regFilePath, AbstractFile regAbstractFile) {
898  File regfile = new File(regFilePath);
899  List<BlackboardArtifact> newArtifacts = new ArrayList<>();
900  try (BufferedReader bufferedReader = new BufferedReader(new FileReader(regfile))) {
901  // Read the file in and create a Document and elements
902  String userInfoSection = "User Information";
903  String previousLine = null;
904  String line = bufferedReader.readLine();
905  Set<Map<String, String>> userSet = new HashSet<>();
906  Map<String, List<String>> groupMap = null;
907  while (line != null) {
908  if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains(userInfoSection)) {
909  readUsers(bufferedReader, userSet);
910  }
911 
912  if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains("Group Membership Information")) {
913  groupMap = readGroups(bufferedReader);
914  }
915 
916  previousLine = line;
917  line = bufferedReader.readLine();
918  }
919  Map<String, Map<String, String>> userInfoMap = new HashMap<>();
920  //load all the user info which was read into a map
921  for (Map<String, String> userInfo : userSet) {
922  userInfoMap.put(userInfo.get(SID_KEY), userInfo);
923  }
924  //get all existing OS account artifacts
925  List<BlackboardArtifact> existingOsAccounts = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
926  for (BlackboardArtifact osAccount : existingOsAccounts) {
927  //if the OS Account artifact was from the same data source check the user id
928  if (osAccount.getDataSource().getId() == regAbstractFile.getDataSourceObjectId()) {
929  BlackboardAttribute existingUserId = osAccount.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID));
930  if (existingUserId != null) {
931  String userID = existingUserId.getValueString().trim();
932  Map<String, String> userInfo = userInfoMap.remove(userID);
933  //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
934  if (userInfo != null) {
935  osAccount.addAttributes(getAttributesForAccount(userInfo, groupMap.get(userID), true));
936  }
937  }
938  }
939  }
940 
941  //add remaining userinfos as accounts;
942  for (Map<String, String> userInfo : userInfoMap.values()) {
943  BlackboardArtifact bbart = regAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
944  bbart.addAttributes(getAttributesForAccount(userInfo, groupMap.get(userInfo.get(SID_KEY)), false));
945  // index the artifact for keyword search
946  newArtifacts.add(bbart);
947  }
948  return true;
949  } catch (FileNotFoundException ex) {
950  logger.log(Level.WARNING, "Error finding the registry file.", ex); //NON-NLS
951  } catch (IOException ex) {
952  logger.log(Level.WARNING, "Error building the document parser: {0}", ex); //NON-NLS
953  } catch (ParseException ex) {
954  logger.log(Level.WARNING, "Error parsing the the date from the registry file", ex); //NON-NLS
955  } catch (TskCoreException ex) {
956  logger.log(Level.WARNING, "Error updating TSK_OS_ACCOUNT artifacts to include newly parsed data.", ex); //NON-NLS
957  } finally {
958  postArtifacts(newArtifacts);
959  }
960  return false;
961  }
962 
974  Collection<BlackboardAttribute> getAttributesForAccount(Map<String, String> userInfo, List<String> groupList, boolean existingUser) throws ParseException {
975  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
976 
977  SimpleDateFormat regRipperTimeFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy 'Z'");
978  regRipperTimeFormat.setTimeZone(getTimeZone("GMT"));
979 
980  if (!existingUser) {
981  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID,
982  getRAModuleName(), userInfo.get(SID_KEY)));
983 
984  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
985  this.moduleName, userInfo.get(USERNAME_KEY)));
986  }
987 
988  String value = userInfo.get(ACCOUNT_CREATED_KEY);
989  if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
990  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
991  getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC));
992  }
993 
994  value = userInfo.get(LAST_LOGIN_KEY);
995  if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
996  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
997  getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC));
998  }
999 
1000  value = userInfo.get(LOGIN_COUNT_KEY);
1001  if (value != null && !value.isEmpty()) {
1002  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
1003  getRAModuleName(), Integer.parseInt(value)));
1004  }
1005 
1006  value = userInfo.get(ACCOUNT_TYPE_KEY);
1007  if (value != null && !value.isEmpty()) {
1008  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE,
1009  getRAModuleName(), value));
1010  }
1011 
1012  value = userInfo.get(USER_COMMENT_KEY);
1013  if (value != null && !value.isEmpty()) {
1014  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DESCRIPTION,
1015  getRAModuleName(), value));
1016  }
1017 
1018  value = userInfo.get(NAME_KEY);
1019  if (value != null && !value.isEmpty()) {
1020  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
1021  getRAModuleName(), value));
1022  }
1023 
1024  value = userInfo.get(INTERNET_NAME_KEY);
1025  if (value != null && !value.isEmpty()) {
1026  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL,
1027  getRAModuleName(), value));
1028  }
1029 
1030  value = userInfo.get(FULL_NAME_KEY);
1031  if (value != null && !value.isEmpty()) {
1032  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DISPLAY_NAME,
1033  getRAModuleName(), value));
1034  }
1035 
1036  value = userInfo.get(PWD_RESET_KEY);
1037  if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
1038  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_PASSWORD_RESET,
1039  getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC));
1040  }
1041 
1042  value = userInfo.get(PASSWORD_HINT);
1043  if (value != null && !value.isEmpty()) {
1044  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_HINT,
1045  getRAModuleName(), value));
1046  }
1047 
1048  value = userInfo.get(PWD_FAILE_KEY);
1049  if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
1050  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_PASSWORD_FAIL,
1051  getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC));
1052  }
1053 
1054  String settingString = "";
1055  for (String setting : PASSWORD_SETTINGS_FLAGS) {
1056  if (userInfo.containsKey(setting)) {
1057  settingString += setting + ", ";
1058  }
1059  }
1060 
1061  if (!settingString.isEmpty()) {
1062  settingString = settingString.substring(0, settingString.length() - 2);
1063  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_SETTINGS,
1064  getRAModuleName(), settingString));
1065  }
1066 
1067  settingString = "";
1068  for (String setting : ACCOUNT_SETTINGS_FLAGS) {
1069  if (userInfo.containsKey(setting)) {
1070  settingString += setting + ", ";
1071  }
1072  }
1073 
1074  if (!settingString.isEmpty()) {
1075  settingString = settingString.substring(0, settingString.length() - 2);
1076  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ACCOUNT_SETTINGS,
1077  getRAModuleName(), settingString));
1078  }
1079 
1080  settingString = "";
1081  for (String setting : ACCOUNT_TYPE_FLAGS) {
1082  if (userInfo.containsKey(setting)) {
1083  settingString += setting + ", ";
1084  }
1085  }
1086 
1087  if (!settingString.isEmpty()) {
1088  settingString = settingString.substring(0, settingString.length() - 2);
1089  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_FLAG,
1090  getRAModuleName(), settingString));
1091  }
1092 
1093  if (groupList != null && groupList.isEmpty()) {
1094  String groups = "";
1095  for (String group : groupList) {
1096  groups += group + ", ";
1097  }
1098 
1099  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_GROUPS,
1100  getRAModuleName(), groups.substring(0, groups.length() - 2)));
1101  }
1102 
1103  return bbattributes;
1104  }
1105 
1117  private void readUsers(BufferedReader bufferedReader, Set<Map<String, String>> users) throws IOException {
1118  String line = bufferedReader.readLine();
1119  //read until end of file or next section divider
1120  String userName = "";
1121  String user_rid = "";
1122  while (line != null && !line.contains(SECTION_DIVIDER)) {
1123  //when a user name field exists read the name and id number
1124  if (line.contains(USERNAME_KEY)) {
1125  String regx = USERNAME_KEY + "\\s*?:";
1126  String userNameAndIdString = line.replaceAll(regx, "");
1127  userName = userNameAndIdString.substring(0, userNameAndIdString.lastIndexOf('[')).trim();
1128  user_rid = userNameAndIdString.substring(userNameAndIdString.lastIndexOf('['), userNameAndIdString.lastIndexOf(']'));
1129  } else if (line.contains(SID_KEY) && !userName.isEmpty()) {
1130  Map.Entry<String, String> entry = getSAMKeyValue(line);
1131 
1132  HashMap<String, String> userInfo = new HashMap<>();
1133  userInfo.put(USERNAME_KEY, userName);
1134  userInfo.put(RID_KEY, user_rid);
1135  userInfo.put(entry.getKey(), entry.getValue());
1136 
1137  //continue reading this users information until end of file or a blank line between users
1138  line = bufferedReader.readLine();
1139  while (line != null && !line.isEmpty()) {
1140  entry = getSAMKeyValue(line);
1141  if (entry != null) {
1142  userInfo.put(entry.getKey(), entry.getValue());
1143  }
1144  line = bufferedReader.readLine();
1145  }
1146  users.add(userInfo);
1147 
1148  userName = "";
1149  }
1150  line = bufferedReader.readLine();
1151  }
1152  }
1153 
1154 
1163  void createShellBagArtifacts(AbstractFile regFile, List<ShellBag> shellbags) throws TskCoreException {
1164  List<BlackboardArtifact> artifacts = new ArrayList<>();
1165  try{
1166  for (ShellBag bag : shellbags) {
1167  Collection<BlackboardAttribute> attributes = new ArrayList<>();
1168  BlackboardArtifact artifact = regFile.newArtifact(getShellBagArtifact().getTypeID());
1169  attributes.add(new BlackboardAttribute(TSK_PATH, getName(), bag.getResource()));
1170  attributes.add(new BlackboardAttribute(getKeyAttribute(), getName(), bag.getKey()));
1171 
1172  long time;
1173  time = bag.getLastWrite();
1174  if (time != 0) {
1175  attributes.add(new BlackboardAttribute(getLastWriteAttribute(), getName(), time));
1176  }
1177 
1178  time = bag.getModified();
1179  if (time != 0) {
1180  attributes.add(new BlackboardAttribute(TSK_DATETIME_MODIFIED, getName(), time));
1181  }
1182 
1183  time = bag.getCreated();
1184  if (time != 0) {
1185  attributes.add(new BlackboardAttribute(TSK_DATETIME_CREATED, getName(), time));
1186  }
1187 
1188  time = bag.getAccessed();
1189  if (time != 0) {
1190  attributes.add(new BlackboardAttribute(TSK_DATETIME_ACCESSED, getName(), time));
1191  }
1192 
1193  artifact.addAttributes(attributes);
1194 
1195  artifacts.add(artifact);
1196  }
1197  } finally {
1198  postArtifacts(artifacts);
1199  }
1200  }
1201 
1210  private BlackboardArtifact.Type getShellBagArtifact() throws TskCoreException {
1211  if (shellBagArtifactType == null) {
1212  shellBagArtifactType = tskCase.getArtifactType(SHELLBAG_ARTIFACT_NAME);
1213 
1214  if(shellBagArtifactType == null) {
1215  try {
1216  tskCase.addBlackboardArtifactType(SHELLBAG_ARTIFACT_NAME, Bundle.Shellbag_Artifact_Display_Name()); //NON-NLS
1217  } catch (TskDataException ex) {
1218  // Artifact already exists
1219  logger.log(Level.INFO, String.format("%s may have already been defined for this case", SHELLBAG_ARTIFACT_NAME));
1220  }
1221 
1222  shellBagArtifactType = tskCase.getArtifactType(SHELLBAG_ARTIFACT_NAME);
1223  }
1224  }
1225 
1226  return shellBagArtifactType;
1227  }
1228 
1237  private BlackboardAttribute.Type getLastWriteAttribute() throws TskCoreException {
1238  if (shellBagLastWriteAttributeType == null) {
1239  try {
1240  shellBagLastWriteAttributeType = tskCase.addArtifactAttributeType(SHELLBAG_ATTRIBUTE_LAST_WRITE,
1241  BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME,
1242  Bundle.Shellbag_Last_Write_Attribute_Display_Name());
1243  } catch (TskDataException ex) {
1244  // Attribute already exists get it from the case
1245  shellBagLastWriteAttributeType = tskCase.getAttributeType(SHELLBAG_ATTRIBUTE_LAST_WRITE);
1246  }
1247  }
1248  return shellBagLastWriteAttributeType;
1249  }
1250 
1259  private BlackboardAttribute.Type getKeyAttribute() throws TskCoreException {
1260  if (shellBagKeyAttributeType == null) {
1261  try {
1262  shellBagKeyAttributeType = tskCase.addArtifactAttributeType(SHELLBAG_ATTRIBUTE_KEY,
1263  BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING,
1264  Bundle.Shellbag_Key_Attribute_Display_Name());
1265  } catch (TskDataException ex) {
1266  // The attribute already exists get it from the case
1267  shellBagKeyAttributeType = tskCase.getAttributeType(SHELLBAG_ATTRIBUTE_KEY);
1268  }
1269  }
1270  return shellBagKeyAttributeType;
1271  }
1272 
1282  Map<String, List<String>> readGroups(BufferedReader bufferedReader) throws IOException {
1283  Map<String, List<String>> groupMap = new HashMap<>();
1284 
1285  String line = bufferedReader.readLine();
1286 
1287  int userCount = 0;
1288  String groupName = null;
1289 
1290  while (line != null && !line.contains(SECTION_DIVIDER)) {
1291 
1292  if (line.contains("Group Name")) {
1293  String value = line.replaceAll("Group Name\\s*?:", "").trim();
1294  groupName = (value.replaceAll("\\[\\d*?\\]", "")).trim();
1295  int startIndex = value.indexOf('[');
1296  int endIndex = value.indexOf(']');
1297 
1298  if (startIndex != -1 && endIndex != -1) {
1299  String countStr = value.substring(startIndex + 1, endIndex);
1300  userCount = Integer.parseInt(countStr);
1301  }
1302  } else if (line.matches("Users\\s*?:")) {
1303  for (int i = 0; i < userCount; i++) {
1304  line = bufferedReader.readLine();
1305  if (line != null) {
1306  String sid = line.trim();
1307  List<String> groupList = groupMap.get(sid);
1308  if (groupList == null) {
1309  groupList = new ArrayList<>();
1310  groupMap.put(sid, groupList);
1311  }
1312  groupList.add(groupName);
1313  }
1314  }
1315  groupName = null;
1316  }
1317  line = bufferedReader.readLine();
1318  }
1319  return groupMap;
1320  }
1321 
1331  private Map.Entry<String, String> getSAMKeyValue(String line) {
1332  int index = line.indexOf(':');
1333  Map.Entry<String, String> returnValue = null;
1334  String key = null;
1335  String value = null;
1336 
1337  if (index != -1) {
1338  key = line.substring(0, index).trim();
1339  if (index + 1 < line.length()) {
1340  value = line.substring(index + 1).trim();
1341  } else {
1342  value = "";
1343  }
1344 
1345  } else if (line.contains("-->")) {
1346  key = line.replace("-->", "").trim();
1347  value = "true";
1348  }
1349 
1350  if (key != null) {
1351  returnValue = new AbstractMap.SimpleEntry<>(key, value);
1352  }
1353 
1354  return returnValue;
1355  }
1356 
1357  @Override
1358  public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
1359  this.dataSource = dataSource;
1360  this.context = context;
1361 
1362  progressBar.progress(Bundle.Progress_Message_Analyze_Registry());
1363  analyzeRegistryFiles();
1364 
1365  }
1366 
1370  private class RegOutputFiles {
1371 
1372  public String autopsyPlugins = "";
1373  public String fullPlugins = "";
1374  }
1375 }

Copyright © 2012-2019 Basis Technology. Generated on: Tue Jan 7 2020
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.