Autopsy  4.12.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;
71 import org.sleuthkit.datamodel.AbstractFile;
72 import org.sleuthkit.datamodel.BlackboardArtifact;
73 import org.sleuthkit.datamodel.BlackboardAttribute;
74 import org.sleuthkit.datamodel.Content;
75 import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
76 import org.sleuthkit.datamodel.Report;
77 import org.sleuthkit.datamodel.TskCoreException;
78 
85 @NbBundle.Messages({
86  "RegRipperNotFound=Autopsy RegRipper executable not found.",
87  "RegRipperFullNotFound=Full version RegRipper executable not found.",
88  "Progress_Message_Analyze_Registry=Analyzing Registry Files"
89 })
90 class ExtractRegistry extends Extract {
91 
92  private static final String USERNAME_KEY = "Username"; //NON-NLS
93  private static final String SID_KEY = "SID"; //NON-NLS
94  private static final String RID_KEY = "RID"; //NON-NLS
95  private static final String ACCOUNT_CREATED_KEY = "Account Created"; //NON-NLS
96  private static final String LAST_LOGIN_KEY = "Last Login Date"; //NON-NLS
97  private static final String LOGIN_COUNT_KEY = "Login Count"; //NON-NLS
98  private static final String FULL_NAME_KEY = "Full Name"; //NON-NLS
99  private static final String USER_COMMENT_KEY = "User Comment"; //NON-NLS
100  private static final String ACCOUNT_TYPE_KEY = "Account Type"; //NON-NLS
101  private static final String NAME_KEY = "Name"; //NON-NLS
102  private static final String PWD_RESET_KEY = "Pwd Rest Date"; //NON-NLS
103  private static final String PWD_FAILE_KEY = "Pwd Fail Date"; //NON-NLS
104  private static final String INTERNET_NAME_KEY = "InternetName"; //NON-NLS
105  private static final String PWD_DOES_NOT_EXPIRE_KEY = "Password does not expire"; //NON-NLS
106  private static final String ACCOUNT_DISABLED_KEY = "Account Disabled"; //NON-NLS
107  private static final String PWD_NOT_REQUIRED_KEY = "Password not required"; //NON-NLS
108  private static final String NORMAL_ACCOUNT_KEY = "Normal user account"; //NON-NLS
109  private static final String HOME_DIRECTORY_REQUIRED_KEY = "Home directory required";
110  private static final String TEMPORARY_DUPLICATE_ACCOUNT = "Temporary duplicate account";
111  private static final String MNS_LOGON_ACCOUNT_KEY = "MNS logon user account";
112  private static final String INTERDOMAIN_TRUST_ACCOUNT_KEY = "Interdomain trust account";
113  private static final String WORKSTATION_TRUST_ACCOUNT = "Workstation trust account";
114  private static final String SERVER_TRUST_ACCOUNT = "Server trust account";
115  private static final String ACCOUNT_AUTO_LOCKED = "Account auto locked";
116  private static final String PASSWORD_HINT = "Password Hint";
117 
118  private static final String[] PASSWORD_SETTINGS_FLAGS = {PWD_DOES_NOT_EXPIRE_KEY, PWD_NOT_REQUIRED_KEY};
119  private static final String[] ACCOUNT_SETTINGS_FLAGS = {ACCOUNT_AUTO_LOCKED, HOME_DIRECTORY_REQUIRED_KEY, ACCOUNT_DISABLED_KEY};
120  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};
121 
122  final private static UsbDeviceIdMapper USB_MAPPER = new UsbDeviceIdMapper();
123  final private static String RIP_EXE = "rip.exe";
124  final private static String RIP_PL = "rip.pl";
125  final private static int MS_IN_SEC = 1000;
126  final private static String NEVER_DATE = "Never";
127  final private static String SECTION_DIVIDER = "-------------------------";
128  final private static Logger logger = Logger.getLogger(ExtractRegistry.class.getName());
129  private final List<String> rrCmd = new ArrayList<>();
130  private final List<String> rrFullCmd = new ArrayList<>();
131  private final Path rrHome; // Path to the Autopsy version of RegRipper
132  private final Path rrFullHome; // Path to the full version of RegRipper
133  private Content dataSource;
134  private IngestJobContext context;
135 
136  ExtractRegistry() throws IngestModuleException {
137  moduleName = NbBundle.getMessage(ExtractIE.class, "ExtractRegistry.moduleName.text");
138 
139  final File rrRoot = InstalledFileLocator.getDefault().locate("rr", ExtractRegistry.class.getPackage().getName(), false); //NON-NLS
140  if (rrRoot == null) {
141  throw new IngestModuleException(Bundle.RegRipperNotFound());
142  }
143 
144  final File rrFullRoot = InstalledFileLocator.getDefault().locate("rr-full", ExtractRegistry.class.getPackage().getName(), false); //NON-NLS
145  if (rrFullRoot == null) {
146  throw new IngestModuleException(Bundle.RegRipperFullNotFound());
147  }
148 
149  String executableToRun = RIP_EXE;
150  if (!PlatformUtil.isWindowsOS()) {
151  executableToRun = RIP_PL;
152  }
153  rrHome = rrRoot.toPath();
154  String rrPath = rrHome.resolve(executableToRun).toString();
155  rrFullHome = rrFullRoot.toPath();
156 
157  if (!(new File(rrPath).exists())) {
158  throw new IngestModuleException(Bundle.RegRipperNotFound());
159  }
160  String rrFullPath = rrFullHome.resolve(executableToRun).toString();
161  if (!(new File(rrFullPath).exists())) {
162  throw new IngestModuleException(Bundle.RegRipperFullNotFound());
163  }
164  if (PlatformUtil.isWindowsOS()) {
165  rrCmd.add(rrPath);
166  rrFullCmd.add(rrFullPath);
167  } else {
168  String perl;
169  File usrBin = new File("/usr/bin/perl");
170  File usrLocalBin = new File("/usr/local/bin/perl");
171  if (usrBin.canExecute() && usrBin.exists() && !usrBin.isDirectory()) {
172  perl = "/usr/bin/perl";
173  } else if (usrLocalBin.canExecute() && usrLocalBin.exists() && !usrLocalBin.isDirectory()) {
174  perl = "/usr/local/bin/perl";
175  } else {
176  throw new IngestModuleException("perl not found in your system");
177  }
178  rrCmd.add(perl);
179  rrCmd.add(rrPath);
180  rrFullCmd.add(perl);
181  rrFullCmd.add(rrFullPath);
182  }
183  }
184 
188  private List<AbstractFile> findRegistryFiles() {
189  List<AbstractFile> allRegistryFiles = new ArrayList<>();
190  org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
191 
192  // find the user-specific ntuser-dat files
193  try {
194  allRegistryFiles.addAll(fileManager.findFiles(dataSource, "ntuser.dat")); //NON-NLS
195  } catch (TskCoreException ex) {
196  logger.log(Level.WARNING, "Error fetching 'ntuser.dat' file."); //NON-NLS
197  }
198 
199  // find the system hives'
200  String[] regFileNames = new String[]{"system", "software", "security", "sam"}; //NON-NLS
201  for (String regFileName : regFileNames) {
202  try {
203  allRegistryFiles.addAll(fileManager.findFiles(dataSource, regFileName, "/system32/config")); //NON-NLS
204  } catch (TskCoreException ex) {
205  String msg = NbBundle.getMessage(this.getClass(),
206  "ExtractRegistry.findRegFiles.errMsg.errReadingFile", regFileName);
207  logger.log(Level.WARNING, msg);
208  this.addErrorMessage(this.getName() + ": " + msg);
209  }
210  }
211  return allRegistryFiles;
212  }
213 
218  private void analyzeRegistryFiles() {
219  List<AbstractFile> allRegistryFiles = findRegistryFiles();
220 
221  // open the log file
222  FileWriter logFile = null;
223  try {
224  logFile = new FileWriter(RAImageIngestModule.getRAOutputPath(currentCase, "reg") + File.separator + "regripper-info.txt"); //NON-NLS
225  } catch (IOException ex) {
226  logger.log(Level.SEVERE, null, ex);
227  }
228 
229  for (AbstractFile regFile : allRegistryFiles) {
230  String regFileName = regFile.getName();
231  long regFileId = regFile.getId();
232  String regFileNameLocal = RAImageIngestModule.getRATempPath(currentCase, "reg") + File.separator + regFileName;
233  String outputPathBase = RAImageIngestModule.getRAOutputPath(currentCase, "reg") + File.separator + regFileName + "-regripper-" + Long.toString(regFileId); //NON-NLS
234  File regFileNameLocalFile = new File(regFileNameLocal);
235  try {
236  ContentUtils.writeToFile(regFile, regFileNameLocalFile, context::dataSourceIngestIsCancelled);
237  } catch (ReadContentInputStreamException ex) {
238  logger.log(Level.WARNING, String.format("Error reading registry file '%s' (id=%d).",
239  regFile.getName(), regFileId), ex); //NON-NLS
240  this.addErrorMessage(
241  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
242  this.getName(), regFileName));
243  continue;
244  } catch (IOException ex) {
245  logger.log(Level.SEVERE, String.format("Error writing temp registry file '%s' for registry file '%s' (id=%d).",
246  regFileNameLocal, regFile.getName(), regFileId), ex); //NON-NLS
247  this.addErrorMessage(
248  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
249  this.getName(), regFileName));
250  continue;
251  }
252 
253  if (context.dataSourceIngestIsCancelled()) {
254  break;
255  }
256 
257  try {
258  if (logFile != null) {
259  logFile.write(Long.toString(regFileId) + "\t" + regFile.getUniquePath() + "\n");
260  }
261  } catch (TskCoreException | IOException ex) {
262  logger.log(Level.SEVERE, null, ex);
263  }
264 
265  logger.log(Level.INFO, "{0}- Now getting registry information from {1}", new Object[]{moduleName, regFileNameLocal}); //NON-NLS
266  RegOutputFiles regOutputFiles = ripRegistryFile(regFileNameLocal, outputPathBase);
267  if (context.dataSourceIngestIsCancelled()) {
268  break;
269  }
270 
271  // parse the autopsy-specific output
272  if (regOutputFiles.autopsyPlugins.isEmpty() == false && parseAutopsyPluginOutput(regOutputFiles.autopsyPlugins, regFile) == false) {
273  this.addErrorMessage(
274  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.failedParsingResults",
275  this.getName(), regFileName));
276  }
277 
278  // create a report for the full output
279  if (!regOutputFiles.fullPlugins.isEmpty()) {
280  //parse the full regripper output from SAM hive files
281  if (regFileNameLocal.toLowerCase().contains("sam") && parseSamPluginOutput(regOutputFiles.fullPlugins, regFile) == false) {
282  this.addErrorMessage(
283  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.failedParsingResults",
284  this.getName(), regFileName));
285  }
286  try {
287  Report report = currentCase.addReport(regOutputFiles.fullPlugins,
288  NbBundle.getMessage(this.getClass(), "ExtractRegistry.parentModuleName.noSpace"),
289  "RegRipper " + regFile.getUniquePath(), regFile); //NON-NLS
290 
291  // Index the report content so that it will be available for keyword search.
292  KeywordSearchService searchService = Lookup.getDefault().lookup(KeywordSearchService.class);
293  if (null == searchService) {
294  logger.log(Level.WARNING, "Keyword search service not found. Report will not be indexed");
295  } else {
296  searchService.index(report);
297  report.close();
298  }
299  } catch (TskCoreException e) {
300  this.addErrorMessage("Error adding regripper output as Autopsy report: " + e.getLocalizedMessage()); //NON-NLS
301  }
302  }
303  // delete the hive
304  regFileNameLocalFile.delete();
305  }
306 
307  try {
308  if (logFile != null) {
309  logFile.close();
310  }
311  } catch (IOException ex) {
312  logger.log(Level.SEVERE, null, ex);
313  }
314  }
315 
323  private RegOutputFiles ripRegistryFile(String regFilePath, String outFilePathBase) {
324  String autopsyType = ""; // Type argument for rr for autopsy-specific modules
325  String fullType; // Type argument for rr for full set of modules
326 
327  RegOutputFiles regOutputFiles = new RegOutputFiles();
328 
329  if (regFilePath.toLowerCase().contains("system")) { //NON-NLS
330  autopsyType = "autopsysystem"; //NON-NLS
331  fullType = "system"; //NON-NLS
332  } else if (regFilePath.toLowerCase().contains("software")) { //NON-NLS
333  autopsyType = "autopsysoftware"; //NON-NLS
334  fullType = "software"; //NON-NLS
335  } else if (regFilePath.toLowerCase().contains("ntuser")) { //NON-NLS
336  autopsyType = "autopsyntuser"; //NON-NLS
337  fullType = "ntuser"; //NON-NLS
338  } else if (regFilePath.toLowerCase().contains("sam")) { //NON-NLS
339  //fullType sam output files are parsed for user information
340  fullType = "sam"; //NON-NLS
341  } else if (regFilePath.toLowerCase().contains("security")) { //NON-NLS
342  fullType = "security"; //NON-NLS
343  } else {
344  return regOutputFiles;
345  }
346 
347  // run the autopsy-specific set of modules
348  if (!autopsyType.isEmpty()) {
349  regOutputFiles.autopsyPlugins = outFilePathBase + "-autopsy.txt"; //NON-NLS
350  String errFilePath = outFilePathBase + "-autopsy.err.txt"; //NON-NLS
351  logger.log(Level.INFO, "Writing RegRipper results to: {0}", regOutputFiles.autopsyPlugins); //NON-NLS
352  executeRegRipper(rrCmd, rrHome, regFilePath, autopsyType, regOutputFiles.autopsyPlugins, errFilePath);
353  }
354  if (context.dataSourceIngestIsCancelled()) {
355  return regOutputFiles;
356  }
357 
358  // run the full set of rr modules
359  if (!fullType.isEmpty()) {
360  regOutputFiles.fullPlugins = outFilePathBase + "-full.txt"; //NON-NLS
361  String errFilePath = outFilePathBase + "-full.err.txt"; //NON-NLS
362  logger.log(Level.INFO, "Writing Full RegRipper results to: {0}", regOutputFiles.fullPlugins); //NON-NLS
363  executeRegRipper(rrFullCmd, rrFullHome, regFilePath, fullType, regOutputFiles.fullPlugins, errFilePath);
364  }
365  return regOutputFiles;
366  }
367 
368  private void executeRegRipper(List<String> regRipperPath, Path regRipperHomeDir, String hiveFilePath, String hiveFileType, String outputFile, String errFile) {
369  try {
370  List<String> commandLine = new ArrayList<>();
371  for (String cmd : regRipperPath) {
372  commandLine.add(cmd);
373  }
374  commandLine.add("-r"); //NON-NLS
375  commandLine.add(hiveFilePath);
376  commandLine.add("-f"); //NON-NLS
377  commandLine.add(hiveFileType);
378 
379  ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
380  processBuilder.directory(regRipperHomeDir.toFile()); // RegRipper 2.8 has to be run from its own directory
381  processBuilder.redirectOutput(new File(outputFile));
382  processBuilder.redirectError(new File(errFile));
383  ExecUtil.execute(processBuilder, new DataSourceIngestModuleProcessTerminator(context));
384  } catch (IOException ex) {
385  logger.log(Level.SEVERE, "Unable to run RegRipper", ex); //NON-NLS
386  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName()));
387  }
388  }
389 
390  // @@@ VERIFY that we are doing the right thing when we parse multiple NTUSER.DAT
399  private boolean parseAutopsyPluginOutput(String regFilePath, AbstractFile regFile) {
400  FileInputStream fstream = null;
401  try {
402  // Read the file in and create a Document and elements
403  File regfile = new File(regFilePath);
404  fstream = new FileInputStream(regfile);
405  String regString = new Scanner(fstream, "UTF-8").useDelimiter("\\Z").next(); //NON-NLS
406  String startdoc = "<?xml version=\"1.0\"?><document>"; //NON-NLS
407  String result = regString.replaceAll("----------------------------------------", "");
408  result = result.replaceAll("\\n", ""); //NON-NLS
409  result = result.replaceAll("\\r", ""); //NON-NLS
410  result = result.replaceAll("'", "&apos;"); //NON-NLS
411  result = result.replaceAll("&", "&amp;"); //NON-NLS
412  result = result.replace('\0', ' '); // NON-NLS
413  String enddoc = "</document>"; //NON-NLS
414  String stringdoc = startdoc + result + enddoc;
415  DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
416  Document doc = builder.parse(new InputSource(new StringReader(stringdoc)));
417 
418  // cycle through the elements in the doc
419  Element oroot = doc.getDocumentElement();
420  NodeList children = oroot.getChildNodes();
421  int len = children.getLength();
422  for (int i = 0; i < len; i++) {
423 
424  if (context.dataSourceIngestIsCancelled()) {
425  return false;
426  }
427 
428  Element tempnode = (Element) children.item(i);
429 
430  String dataType = tempnode.getNodeName();
431  NodeList timenodes = tempnode.getElementsByTagName("mtime"); //NON-NLS
432  Long mtime = null;
433  if (timenodes.getLength() > 0) {
434  Element timenode = (Element) timenodes.item(0);
435  String etime = timenode.getTextContent();
436  //sometimes etime will be an empty string and therefore can not be parsed into a date
437  if (etime != null && !etime.isEmpty()) {
438  try {
439  mtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(etime).getTime();
440  String Tempdate = mtime.toString();
441  mtime = Long.valueOf(Tempdate) / MS_IN_SEC;
442  } catch (ParseException ex) {
443  logger.log(Level.WARNING, "Failed to parse epoch time when parsing the registry.", ex); //NON-NLS
444  }
445  }
446  }
447 
448  NodeList artroots = tempnode.getElementsByTagName("artifacts"); //NON-NLS
449  if (artroots.getLength() == 0) {
450  // If there isn't an artifact node, skip this entry
451  continue;
452  }
453 
454  Element artroot = (Element) artroots.item(0);
455  NodeList myartlist = artroot.getChildNodes();
456  String parentModuleName = RecentActivityExtracterModuleFactory.getModuleName();
457 
458  // If all artifact nodes should really go under one Blackboard artifact, need to process it differently
459  switch (dataType) {
460  case "WinVersion": //NON-NLS
461  String version = "";
462  String systemRoot = "";
463  String productId = "";
464  String regOwner = "";
465  String regOrg = "";
466  Long installtime = null;
467  for (int j = 0; j < myartlist.getLength(); j++) {
468  Node artchild = myartlist.item(j);
469  // If it has attributes, then it is an Element (based off API)
470  if (artchild.hasAttributes()) {
471  Element artnode = (Element) artchild;
472 
473  String value = artnode.getTextContent();
474  if (value != null) {
475  value = value.trim();
476  }
477  String name = artnode.getAttribute("name"); //NON-NLS
478  if (name == null) {
479  continue;
480  }
481  switch (name) {
482  case "ProductName": // NON-NLS
483  version = value;
484  break;
485  case "CSDVersion": // NON-NLS
486  // This is dependant on the fact that ProductName shows up first in the module output
487  version = version + " " + value;
488  break;
489  case "SystemRoot": //NON-NLS
490  systemRoot = value;
491  break;
492  case "ProductId": //NON-NLS
493  productId = value;
494  break;
495  case "RegisteredOwner": //NON-NLS
496  regOwner = value;
497  break;
498  case "RegisteredOrganization": //NON-NLS
499  regOrg = value;
500  break;
501  case "InstallDate": //NON-NLS
502  if (value != null && !value.isEmpty()) {
503  try {
504  installtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(value).getTime();
505  String Tempdate = installtime.toString();
506  installtime = Long.valueOf(Tempdate) / MS_IN_SEC;
507  } catch (ParseException e) {
508  logger.log(Level.SEVERE, "RegRipper::Conversion on DateTime -> ", e); //NON-NLS
509  }
510  }
511  break;
512  default:
513  break;
514  }
515  }
516  }
517  try {
518  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
519  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, version));
520  if (installtime != null) {
521  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, installtime));
522  }
523  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, systemRoot));
524  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PRODUCT_ID, parentModuleName, productId));
525  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_OWNER, parentModuleName, regOwner));
526  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ORGANIZATION, parentModuleName, regOrg));
527 
528  // Check if there is already an OS_INFO artifact for this file, and add to that if possible.
529  ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
530  if (results.isEmpty()) {
531  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
532  bbart.addAttributes(bbattributes);
533 
534  // index the artifact for keyword search
535  postArtifact(bbart);
536  } else {
537  results.get(0).addAttributes(bbattributes);
538  }
539 
540  } catch (TskCoreException ex) {
541  logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard."); //NON-NLS
542  }
543  break;
544  case "Profiler": // NON-NLS
545  String os = "";
546  String procArch = "";
547  String tempDir = "";
548  for (int j = 0; j < myartlist.getLength(); j++) {
549  Node artchild = myartlist.item(j);
550  // If it has attributes, then it is an Element (based off API)
551  if (artchild.hasAttributes()) {
552  Element artnode = (Element) artchild;
553 
554  String value = artnode.getTextContent().trim();
555  String name = artnode.getAttribute("name"); //NON-NLS
556  switch (name) {
557  case "OS": // NON-NLS
558  os = value;
559  break;
560  case "PROCESSOR_ARCHITECTURE": // NON-NLS
561  procArch = value;
562  break;
563  case "PROCESSOR_IDENTIFIER": //NON-NLS
564  break;
565  case "TEMP": //NON-NLS
566  tempDir = value;
567  break;
568  default:
569  break;
570  }
571  }
572  }
573  try {
574  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
575  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VERSION, parentModuleName, os));
576  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE, parentModuleName, procArch));
577  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEMP_DIR, parentModuleName, tempDir));
578 
579  // Check if there is already an OS_INFO artifact for this file and add to that if possible
580  ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
581  if (results.isEmpty()) {
582  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
583  bbart.addAttributes(bbattributes);
584 
585  // index the artifact for keyword search
586  postArtifact(bbart);
587  } else {
588  results.get(0).addAttributes(bbattributes);
589  }
590  } catch (TskCoreException ex) {
591  logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS
592  }
593  break;
594  case "CompName": // NON-NLS
595  String compName = "";
596  String domain = "";
597  for (int j = 0; j < myartlist.getLength(); j++) {
598  Node artchild = myartlist.item(j);
599  // If it has attributes, then it is an Element (based off API)
600  if (artchild.hasAttributes()) {
601  Element artnode = (Element) artchild;
602 
603  String value = artnode.getTextContent().trim();
604  String name = artnode.getAttribute("name"); //NON-NLS
605 
606  if (name.equals("ComputerName")) { // NON-NLS
607  compName = value;
608  } else if (name.equals("Domain")) { // NON-NLS
609  domain = value;
610  }
611  }
612  }
613  try {
614  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
615  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, compName));
616  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, parentModuleName, domain));
617 
618  // Check if there is already an OS_INFO artifact for this file and add to that if possible
619  ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
620  if (results.isEmpty()) {
621  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
622  bbart.addAttributes(bbattributes);
623 
624  // index the artifact for keyword search
625  postArtifact(bbart);
626  } else {
627  results.get(0).addAttributes(bbattributes);
628  }
629  } catch (TskCoreException ex) {
630  logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS
631  }
632  break;
633  default:
634  for (int j = 0; j < myartlist.getLength(); j++) {
635  Node artchild = myartlist.item(j);
636  // If it has attributes, then it is an Element (based off API)
637  if (artchild.hasAttributes()) {
638  Element artnode = (Element) artchild;
639 
640  String value = artnode.getTextContent().trim();
641  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
642 
643  switch (dataType) {
644  case "recentdocs": //NON-NLS
645  // BlackboardArtifact bbart = tskCase.getContentById(orgId).newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
646  // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", dataType, mtime));
647  // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity", dataType, mtimeItem));
648  // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), "RecentActivity", dataType, value));
649  // bbart.addAttributes(bbattributes);
650  // @@@ BC: Why are we ignoring this...
651  break;
652  case "usb": //NON-NLS
653  try {
654  Long usbMtime = Long.parseLong(artnode.getAttribute("mtime")); //NON-NLS
655  usbMtime = Long.valueOf(usbMtime.toString());
656 
657  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED);
658  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime));
659  String dev = artnode.getAttribute("dev"); //NON-NLS
660  String make = "";
661  String model = dev;
662  if (dev.toLowerCase().contains("vid")) { //NON-NLS
663  USBInfo info = USB_MAPPER.parseAndLookup(dev);
664  if (info.getVendor() != null) {
665  make = info.getVendor();
666  }
667  if (info.getProduct() != null) {
668  model = info.getProduct();
669  }
670  }
671  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make));
672  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model));
673  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value));
674  bbart.addAttributes(bbattributes);
675 
676  // index the artifact for keyword search
677  postArtifact(bbart);
678  } catch (TskCoreException ex) {
679  logger.log(Level.SEVERE, "Error adding device attached artifact to blackboard.", ex); //NON-NLS
680  }
681  break;
682  case "uninstall": //NON-NLS
683  Long itemMtime = null;
684  try {
685  String mTimeAttr = artnode.getAttribute("mtime");
686  if (mTimeAttr != null && !mTimeAttr.isEmpty()) {
687  itemMtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy").parse(mTimeAttr).getTime(); //NON-NLS
688  itemMtime /= MS_IN_SEC;
689  }
690  } catch (ParseException ex) {
691  logger.log(Level.WARNING, "Failed to parse epoch time for installed program artifact.", ex); //NON-NLS
692  }
693 
694  try {
695  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, value));
696  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, itemMtime));
697  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_INSTALLED_PROG);
698  bbart.addAttributes(bbattributes);
699 
700  // index the artifact for keyword search
701  postArtifact(bbart);
702  } catch (TskCoreException ex) {
703  logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard.", ex); //NON-NLS
704  }
705  break;
706  case "office": //NON-NLS
707  String officeName = artnode.getAttribute("name"); //NON-NLS
708 
709  try {
710  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
711  // @@@ BC: Consider removing this after some more testing. It looks like an Mtime associated with the root key and not the individual item
712  if (mtime != null) {
713  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, parentModuleName, mtime));
714  }
715  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, officeName));
716  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, parentModuleName, value));
717  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, artnode.getNodeName()));
718  bbart.addAttributes(bbattributes);
719 
720  // index the artifact for keyword search
721  postArtifact(bbart);
722  } catch (TskCoreException ex) {
723  logger.log(Level.SEVERE, "Error adding recent object artifact to blackboard.", ex); //NON-NLS
724  }
725  break;
726 
727  case "ProcessorArchitecture": //NON-NLS
728  // Architecture is now included under Profiler
729  //try {
730  // String processorArchitecture = value;
731  // if (processorArchitecture.equals("AMD64"))
732  // processorArchitecture = "x86-64";
733 
734  // BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
735  // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE.getTypeID(), parentModuleName, processorArchitecture));
736  // bbart.addAttributes(bbattributes);
737  //} catch (TskCoreException ex) {
738  // logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS
739  //}
740  break;
741 
742  case "ProfileList": //NON-NLS
743  try {
744  String homeDir = value;
745  String sid = artnode.getAttribute("sid"); //NON-NLS
746  String username = artnode.getAttribute("username"); //NON-NLS
747  BlackboardArtifact bbart = null;
748  try {
749  //check if any of the existing artifacts match this username
750  ArrayList<BlackboardArtifact> existingArtifacts = currentCase.getSleuthkitCase().getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
751  for (BlackboardArtifact artifact : existingArtifacts) {
752  if (artifact.getDataSource().getId() == regFile.getDataSourceObjectId()) {
753  BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID));
754  if (attribute != null && attribute.getValueString().equals(sid)) {
755  bbart = artifact;
756  break;
757  }
758  }
759  }
760  } catch (TskCoreException ex) {
761  logger.log(Level.WARNING, "Error getting existing os account artifact", ex);
762  }
763  if (bbart == null) {
764  //create new artifact
765  bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
766  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
767  parentModuleName, username));
768  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID,
769  parentModuleName, sid));
770  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
771  parentModuleName, homeDir));
772  } else {
773  //add attributes to existing artifact
774  BlackboardAttribute bbattr = bbart.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_NAME));
775 
776  if (bbattr == null) {
777  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
778  parentModuleName, username));
779  }
780  bbattr = bbart.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_PATH));
781  if (bbattr == null) {
782  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH,
783  parentModuleName, homeDir));
784  }
785  }
786  bbart.addAttributes(bbattributes);
787  // index the artifact for keyword search
788  postArtifact(bbart);
789  } catch (TskCoreException ex) {
790  logger.log(Level.SEVERE, "Error adding account artifact to blackboard.", ex); //NON-NLS
791  }
792  break;
793 
794  case "NtuserNetwork": // NON-NLS
795  try {
796  String localPath = artnode.getAttribute("localPath"); //NON-NLS
797  String remoteName = value;
798  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_REMOTE_DRIVE);
799  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH,
800  parentModuleName, localPath));
801  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH,
802  parentModuleName, remoteName));
803  bbart.addAttributes(bbattributes);
804  // index the artifact for keyword search
805  postArtifact(bbart);
806  } catch (TskCoreException ex) {
807  logger.log(Level.SEVERE, "Error adding network artifact to blackboard.", ex); //NON-NLS
808  }
809  break;
810  case "SSID": // NON-NLS
811  String adapter = artnode.getAttribute("adapter"); //NON-NLS
812  try {
813  Long lastWriteTime = Long.parseLong(artnode.getAttribute("writeTime")); //NON-NLS
814  lastWriteTime = Long.valueOf(lastWriteTime.toString());
815  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SSID, parentModuleName, value));
816  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, lastWriteTime));
817  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, adapter));
818  BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_WIFI_NETWORK);
819  bbart.addAttributes(bbattributes);
820  // index the artifact for keyword search
821  postArtifact(bbart);
822  } catch (TskCoreException ex) {
823  logger.log(Level.SEVERE, "Error adding SSID artifact to blackboard.", ex); //NON-NLS
824  }
825  break;
826  case "shellfolders": // NON-NLS
827  // The User Shell Folders subkey stores the paths to Windows Explorer folders for the current user of the computer
828  // (https://technet.microsoft.com/en-us/library/Cc962613.aspx).
829  // No useful information. Skip.
830  break;
831 
832  default:
833  logger.log(Level.WARNING, "Unrecognized node name: {0}", dataType); //NON-NLS
834  break;
835  }
836  }
837  }
838  break;
839  }
840  } // for
841  return true;
842  } catch (FileNotFoundException ex) {
843  logger.log(Level.SEVERE, "Error finding the registry file.", ex); //NON-NLS
844  } catch (SAXException ex) {
845  logger.log(Level.SEVERE, "Error parsing the registry XML.", ex); //NON-NLS
846  } catch (IOException ex) {
847  logger.log(Level.SEVERE, "Error building the document parser.", ex); //NON-NLS
848  } catch (ParserConfigurationException ex) {
849  logger.log(Level.SEVERE, "Error configuring the registry parser.", ex); //NON-NLS
850  } finally {
851  try {
852  if (fstream != null) {
853  fstream.close();
854  }
855  } catch (IOException ex) {
856  }
857  }
858  return false;
859  }
860 
870  private boolean parseSamPluginOutput(String regFilePath, AbstractFile regAbstractFile) {
871  File regfile = new File(regFilePath);
872  try (BufferedReader bufferedReader = new BufferedReader(new FileReader(regfile))) {
873  // Read the file in and create a Document and elements
874  String userInfoSection = "User Information";
875  String previousLine = null;
876  String line = bufferedReader.readLine();
877  Set<Map<String, String>> userSet = new HashSet<>();
878  Map<String, List<String>> groupMap = null;
879  while (line != null) {
880  if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains(userInfoSection)) {
881  readUsers(bufferedReader, userSet);
882  }
883 
884  if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains("Group Membership Information")) {
885  groupMap = readGroups(bufferedReader);
886  }
887 
888  previousLine = line;
889  line = bufferedReader.readLine();
890  }
891  Map<String, Map<String, String>> userInfoMap = new HashMap<>();
892  //load all the user info which was read into a map
893  for (Map<String, String> userInfo : userSet) {
894  userInfoMap.put(userInfo.get(SID_KEY), userInfo);
895  }
896  //get all existing OS account artifacts
897  List<BlackboardArtifact> existingOsAccounts = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
898  for (BlackboardArtifact osAccount : existingOsAccounts) {
899  //if the OS Account artifact was from the same data source check the user id
900  if (osAccount.getDataSource().getId() == regAbstractFile.getDataSourceObjectId()) {
901  BlackboardAttribute existingUserId = osAccount.getAttribute(new BlackboardAttribute.Type(ATTRIBUTE_TYPE.TSK_USER_ID));
902  if (existingUserId != null) {
903  String userID = existingUserId.getValueString().trim();
904  Map<String, String> userInfo = userInfoMap.remove(userID);
905  //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
906  if (userInfo != null) {
907  osAccount.addAttributes(getAttributesForAccount(userInfo, groupMap.get(userID), true));
908  }
909  }
910  }
911  }
912  //add remaining userinfos as accounts;
913  for (Map<String, String> userInfo : userInfoMap.values()) {
914  BlackboardArtifact bbart = regAbstractFile.newArtifact(ARTIFACT_TYPE.TSK_OS_ACCOUNT);
915  bbart.addAttributes(getAttributesForAccount(userInfo, groupMap.get(userInfo.get(SID_KEY)), false));
916  // index the artifact for keyword search
917  postArtifact(bbart);
918  }
919  //store set of attributes to make artifact for later in collection of artifact like objects
920  return true;
921  } catch (FileNotFoundException ex) {
922  logger.log(Level.SEVERE, "Error finding the registry file.", ex); //NON-NLS
923  } catch (IOException ex) {
924  logger.log(Level.SEVERE, "Error building the document parser: {0}", ex); //NON-NLS
925  } catch (ParseException ex) {
926  logger.log(Level.SEVERE, "Error parsing the the date from the registry file", ex); //NON-NLS
927  } catch (TskCoreException ex) {
928  logger.log(Level.SEVERE, "Error updating TSK_OS_ACCOUNT artifacts to include newly parsed data.", ex); //NON-NLS
929  }
930  return false;
931  }
932 
944  Collection<BlackboardAttribute> getAttributesForAccount(Map<String, String> userInfo, List<String> groupList, boolean existingUser) throws ParseException {
945  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
946 
947  SimpleDateFormat regRipperTimeFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy 'Z'");
948  regRipperTimeFormat.setTimeZone(getTimeZone("GMT"));
949 
950  if (!existingUser) {
951  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_ID,
952  getRAModuleName(), userInfo.get(SID_KEY)));
953 
954  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME,
955  this.moduleName, userInfo.get(USERNAME_KEY)));
956  }
957 
958  String value = userInfo.get(ACCOUNT_CREATED_KEY);
959  if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
960  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED,
961  getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC));
962  }
963 
964  value = userInfo.get(LAST_LOGIN_KEY);
965  if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
966  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED,
967  getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC));
968  }
969 
970  value = userInfo.get(LOGIN_COUNT_KEY);
971  if (value != null && !value.isEmpty()) {
972  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
973  getRAModuleName(), Integer.parseInt(value)));
974  }
975 
976  value = userInfo.get(ACCOUNT_TYPE_KEY);
977  if (value != null && !value.isEmpty()) {
978  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE,
979  getRAModuleName(), value));
980  }
981 
982  value = userInfo.get(USER_COMMENT_KEY);
983  if (value != null && !value.isEmpty()) {
984  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DESCRIPTION,
985  getRAModuleName(), value));
986  }
987 
988  value = userInfo.get(NAME_KEY);
989  if (value != null && !value.isEmpty()) {
990  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME,
991  getRAModuleName(), value));
992  }
993 
994  value = userInfo.get(INTERNET_NAME_KEY);
995  if (value != null && !value.isEmpty()) {
996  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL,
997  getRAModuleName(), value));
998  }
999 
1000  value = userInfo.get(FULL_NAME_KEY);
1001  if (value != null && !value.isEmpty()) {
1002  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DISPLAY_NAME,
1003  getRAModuleName(), value));
1004  }
1005 
1006  value = userInfo.get(PWD_RESET_KEY);
1007  if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
1008  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_PASSWORD_RESET,
1009  getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC));
1010  }
1011 
1012  value = userInfo.get(PASSWORD_HINT);
1013  if (value != null && !value.isEmpty()) {
1014  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_HINT,
1015  getRAModuleName(), value));
1016  }
1017 
1018  value = userInfo.get(PWD_FAILE_KEY);
1019  if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
1020  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_PASSWORD_FAIL,
1021  getRAModuleName(), regRipperTimeFormat.parse(value).getTime() / MS_IN_SEC));
1022  }
1023 
1024  String settingString = "";
1025  for (String setting : PASSWORD_SETTINGS_FLAGS) {
1026  if (userInfo.containsKey(setting)) {
1027  settingString += setting + ", ";
1028  }
1029  }
1030 
1031  if (!settingString.isEmpty()) {
1032  settingString = settingString.substring(0, settingString.length() - 2);
1033  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_SETTINGS,
1034  getRAModuleName(), settingString));
1035  }
1036 
1037  settingString = "";
1038  for (String setting : ACCOUNT_SETTINGS_FLAGS) {
1039  if (userInfo.containsKey(setting)) {
1040  settingString += setting + ", ";
1041  }
1042  }
1043 
1044  if (!settingString.isEmpty()) {
1045  settingString = settingString.substring(0, settingString.length() - 2);
1046  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ACCOUNT_SETTINGS,
1047  getRAModuleName(), settingString));
1048  }
1049 
1050  settingString = "";
1051  for (String setting : ACCOUNT_TYPE_FLAGS) {
1052  if (userInfo.containsKey(setting)) {
1053  settingString += setting + ", ";
1054  }
1055  }
1056 
1057  if (!settingString.isEmpty()) {
1058  settingString = settingString.substring(0, settingString.length() - 2);
1059  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_FLAG,
1060  getRAModuleName(), settingString));
1061  }
1062 
1063  if (groupList != null && groupList.isEmpty()) {
1064  String groups = "";
1065  for (String group : groupList) {
1066  groups += group + ", ";
1067  }
1068 
1069  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_GROUPS,
1070  getRAModuleName(), groups.substring(0, groups.length() - 2)));
1071  }
1072 
1073  return bbattributes;
1074  }
1075 
1087  private void readUsers(BufferedReader bufferedReader, Set<Map<String, String>> users) throws IOException {
1088  String line = bufferedReader.readLine();
1089  //read until end of file or next section divider
1090  String userName = "";
1091  String user_rid = "";
1092  while (line != null && !line.contains(SECTION_DIVIDER)) {
1093  //when a user name field exists read the name and id number
1094  if (line.contains(USERNAME_KEY)) {
1095  String regx = USERNAME_KEY + "\\s*?:";
1096  String userNameAndIdString = line.replaceAll(regx, "");
1097  userName = userNameAndIdString.substring(0, userNameAndIdString.lastIndexOf('[')).trim();
1098  user_rid = userNameAndIdString.substring(userNameAndIdString.lastIndexOf('['), userNameAndIdString.lastIndexOf(']'));
1099  } else if (line.contains(SID_KEY) && !userName.isEmpty()) {
1100  Map.Entry<String, String> entry = getSAMKeyValue(line);
1101 
1102  HashMap<String, String> userInfo = new HashMap<>();
1103  userInfo.put(USERNAME_KEY, userName);
1104  userInfo.put(RID_KEY, user_rid);
1105  userInfo.put(entry.getKey(), entry.getValue());
1106 
1107  //continue reading this users information until end of file or a blank line between users
1108  line = bufferedReader.readLine();
1109  while (line != null && !line.isEmpty()) {
1110  entry = getSAMKeyValue(line);
1111  userInfo.put(entry.getKey(), entry.getValue());
1112  line = bufferedReader.readLine();
1113  }
1114  users.add(userInfo);
1115 
1116  userName = "";
1117  }
1118  line = bufferedReader.readLine();
1119  }
1120  }
1121 
1131  Map<String, List<String>> readGroups(BufferedReader bufferedReader) throws IOException {
1132  Map<String, List<String>> groupMap = new HashMap<>();
1133 
1134  String line = bufferedReader.readLine();
1135 
1136  int userCount = 0;
1137  String groupName = null;
1138 
1139  while (line != null && !line.contains(SECTION_DIVIDER)) {
1140 
1141  if (line.contains("Group Name")) {
1142  String value = line.replaceAll("Group Name\\s*?:", "").trim();
1143  groupName = (value.replaceAll("\\[\\d*?\\]", "")).trim();
1144  int startIndex = value.indexOf('[');
1145  int endIndex = value.indexOf(']');
1146 
1147  if (startIndex != -1 && endIndex != -1) {
1148  String countStr = value.substring(startIndex + 1, endIndex);
1149  userCount = Integer.parseInt(countStr);
1150  }
1151  } else if (line.matches("Users\\s*?:")) {
1152  for (int i = 0; i < userCount; i++) {
1153  line = bufferedReader.readLine();
1154  if (line != null) {
1155  String sid = line.trim();
1156  List<String> groupList = groupMap.get(sid);
1157  if (groupList == null) {
1158  groupList = new ArrayList<>();
1159  groupMap.put(sid, groupList);
1160  }
1161  groupList.add(groupName);
1162  }
1163  }
1164  groupName = null;
1165  }
1166  line = bufferedReader.readLine();
1167  }
1168  return groupMap;
1169  }
1170 
1180  private Map.Entry<String, String> getSAMKeyValue(String line) {
1181  int index = line.indexOf(':');
1182  Map.Entry<String, String> returnValue = null;
1183  String key = null;
1184  String value = null;
1185 
1186  if (index != -1) {
1187  key = line.substring(0, index).trim();
1188  if (index + 1 < line.length()) {
1189  value = line.substring(index + 1).trim();
1190  } else {
1191  value = "";
1192  }
1193 
1194  } else if (line.contains("-->")) {
1195  key = line.replace("-->", "").trim();
1196  value = "true";
1197  }
1198 
1199  if (key != null) {
1200  returnValue = new AbstractMap.SimpleEntry<>(key, value);
1201  }
1202 
1203  return returnValue;
1204  }
1205 
1206  @Override
1207  public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
1208  this.dataSource = dataSource;
1209  this.context = context;
1210 
1211  progressBar.progress(Bundle.Progress_Message_Analyze_Registry());
1212  analyzeRegistryFiles();
1213 
1214  }
1215 
1219  private class RegOutputFiles {
1220 
1221  public String autopsyPlugins = "";
1222  public String fullPlugins = "";
1223  }
1224 }

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