Autopsy  4.19.2
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-2021 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.InputStreamReader;
33 import java.io.StringReader;
34 import java.nio.charset.StandardCharsets;
35 import java.text.ParseException;
36 import java.text.SimpleDateFormat;
37 import java.util.logging.Level;
38 import javax.xml.parsers.DocumentBuilder;
39 import javax.xml.parsers.DocumentBuilderFactory;
40 import javax.xml.parsers.ParserConfigurationException;
41 import org.apache.commons.io.FilenameUtils;
42 import org.openide.modules.InstalledFileLocator;
43 import org.openide.util.NbBundle;
51 import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
52 import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
53 import org.w3c.dom.Document;
54 import org.w3c.dom.Element;
55 import org.w3c.dom.Node;
56 import org.w3c.dom.NodeList;
57 import org.xml.sax.InputSource;
58 import org.xml.sax.SAXException;
59 import java.nio.file.Path;
60 import java.util.AbstractMap;
61 import java.util.ArrayList;
62 import java.util.List;
63 import java.util.Collection;
64 import java.util.Date;
65 import java.util.HashMap;
66 import java.util.Map;
67 import java.util.Scanner;
68 import java.util.Set;
69 import java.util.HashSet;
70 import static java.util.Locale.US;
71 import java.util.Optional;
72 import static java.util.TimeZone.getTimeZone;
73 import java.util.stream.Collectors;
74 import org.openide.util.Lookup;
79 import org.sleuthkit.datamodel.AbstractFile;
80 import org.sleuthkit.datamodel.Account;
81 import org.sleuthkit.datamodel.Blackboard.BlackboardException;
82 import org.sleuthkit.datamodel.BlackboardArtifact;
83 import org.sleuthkit.datamodel.BlackboardAttribute;
84 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT;
85 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME;
86 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED;
87 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED;
88 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED;
89 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_ID;
90 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME;
91 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH;
92 import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_HOME_DIR;
93 import org.sleuthkit.datamodel.Content;
94 import org.sleuthkit.datamodel.DataSource;
95 import org.sleuthkit.datamodel.Host;
96 import org.sleuthkit.datamodel.HostManager;
97 import org.sleuthkit.datamodel.OsAccount;
98 import org.sleuthkit.datamodel.OsAccount.OsAccountAttribute;
99 import org.sleuthkit.datamodel.OsAccountInstance;
100 import org.sleuthkit.datamodel.OsAccountManager;
101 import org.sleuthkit.datamodel.OsAccountManager.NotUserSIDException;
102 import org.sleuthkit.datamodel.OsAccountManager.OsAccountUpdateResult;
103 import org.sleuthkit.datamodel.OsAccountRealm;
104 import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
105 import org.sleuthkit.datamodel.Report;
106 import org.sleuthkit.datamodel.TskCoreException;
107 import org.sleuthkit.datamodel.TskDataException;
108 
115 @NbBundle.Messages({
116  "RegRipperNotFound=Autopsy RegRipper executable not found.",
117  "RegRipperFullNotFound=Full version RegRipper executable not found.",
118  "Progress_Message_Analyze_Registry=Analyzing Registry Files",
119  "Shellbag_Artifact_Display_Name=Shell Bags",
120  "Shellbag_Key_Attribute_Display_Name=Key",
121  "Shellbag_Last_Write_Attribute_Display_Name=Last Write",
122  "Recently_Used_Artifacts_Office_Trustrecords=Stored in TrustRecords because Office security exception was granted",
123  "Recently_Used_Artifacts_ArcHistory=Recently opened by 7Zip",
124  "Recently_Used_Artifacts_Applets=Recently opened according to Applets registry key",
125  "Recently_Used_Artifacts_Mmc=Recently opened according to Windows Management Console MRU",
126  "Recently_Used_Artifacts_Winrar=Recently opened according to WinRAR MRU",
127  "Recently_Used_Artifacts_Officedocs=Recently opened according to Office MRU",
128  "Recently_Used_Artifacts_Adobe=Recently opened according to Adobe MRU",
129  "Recently_Used_Artifacts_Mediaplayer=Recently opened according to Media Player MRU",
130  "Registry_System_Bam=Recently Executed according to Background Activity Moderator (BAM)"
131 })
132 class ExtractRegistry extends Extract {
133 
134  private static final String USERNAME_KEY = "Username"; //NON-NLS
135  private static final String SID_KEY = "SID"; //NON-NLS
136  private static final String RID_KEY = "RID"; //NON-NLS
137  private static final String ACCOUNT_CREATED_KEY = "Account Created"; //NON-NLS
138  private static final String LAST_LOGIN_KEY = "Last Login Date"; //NON-NLS
139  private static final String LOGIN_COUNT_KEY = "Login Count"; //NON-NLS
140  private static final String FULL_NAME_KEY = "Full Name"; //NON-NLS
141  private static final String USER_COMMENT_KEY = "User Comment"; //NON-NLS
142  private static final String ACCOUNT_TYPE_KEY = "Account Type"; //NON-NLS
143  private static final String NAME_KEY = "Name"; //NON-NLS
144  private static final String PWD_RESET_KEY = "Pwd Rest Date"; //NON-NLS
145  private static final String PWD_FAILE_KEY = "Pwd Fail Date"; //NON-NLS
146  private static final String INTERNET_NAME_KEY = "InternetName"; //NON-NLS
147  private static final String PWD_DOES_NOT_EXPIRE_KEY = "Password does not expire"; //NON-NLS
148  private static final String ACCOUNT_DISABLED_KEY = "Account Disabled"; //NON-NLS
149  private static final String PWD_NOT_REQUIRED_KEY = "Password not required"; //NON-NLS
150  private static final String NORMAL_ACCOUNT_KEY = "Normal user account"; //NON-NLS
151  private static final String HOME_DIRECTORY_REQUIRED_KEY = "Home directory required";
152  private static final String TEMPORARY_DUPLICATE_ACCOUNT = "Temporary duplicate account";
153  private static final String MNS_LOGON_ACCOUNT_KEY = "MNS logon user account";
154  private static final String INTERDOMAIN_TRUST_ACCOUNT_KEY = "Interdomain trust account";
155  private static final String WORKSTATION_TRUST_ACCOUNT = "Workstation trust account";
156  private static final String SERVER_TRUST_ACCOUNT = "Server trust account";
157  private static final String ACCOUNT_AUTO_LOCKED = "Account auto locked";
158  private static final String PASSWORD_HINT = "Password Hint";
159 
160  private static final String[] PASSWORD_SETTINGS_FLAGS = {PWD_DOES_NOT_EXPIRE_KEY, PWD_NOT_REQUIRED_KEY};
161  private static final String[] ACCOUNT_SETTINGS_FLAGS = {ACCOUNT_AUTO_LOCKED, HOME_DIRECTORY_REQUIRED_KEY, ACCOUNT_DISABLED_KEY};
162  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};
163 
164  final private static UsbDeviceIdMapper USB_MAPPER = new UsbDeviceIdMapper();
165  final private static String RIP_EXE = "rip.exe";
166  final private static String RIP_PL = "rip.pl";
167  final private static String RIP_PL_INCLUDE_FLAG = "-I";
168  final private static int MS_IN_SEC = 1000;
169  final private static String NEVER_DATE = "Never";
170  final private static String SECTION_DIVIDER = "-------------------------";
171  final private static Logger logger = Logger.getLogger(ExtractRegistry.class.getName());
172  private final List<String> rrCmd = new ArrayList<>();
173  private final List<String> rrFullCmd = new ArrayList<>();
174  private final Path rrHome; // Path to the Autopsy version of RegRipper
175  private final Path rrFullHome; // Path to the full version of RegRipper
176  private Content dataSource;
177  private final IngestJobContext context;
178  private Map<String, String> userNameMap;
179  private final List<String> samDomainIDsList = new ArrayList<>();
180 
181  private String compName = "";
182  private String domainName = "";
183 
184  private static final String SHELLBAG_ARTIFACT_NAME = "RA_SHELL_BAG"; //NON-NLS
185  private static final String SHELLBAG_ATTRIBUTE_LAST_WRITE = "RA_SHELL_BAG_LAST_WRITE"; //NON-NLS
186  private static final String SHELLBAG_ATTRIBUTE_KEY = "RA_SHELL_BAG_KEY"; //NON-NLS
187 
188  private static final SimpleDateFormat REG_RIPPER_TIME_FORMAT = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy 'Z'", US);
189 
190  private BlackboardArtifact.Type shellBagArtifactType = null;
191  private BlackboardAttribute.Type shellBagKeyAttributeType = null;
192  private BlackboardAttribute.Type shellBagLastWriteAttributeType = null;
193 
194  static {
195  REG_RIPPER_TIME_FORMAT.setTimeZone(getTimeZone("GMT"));
196  }
197 
198  ExtractRegistry(IngestJobContext context) throws IngestModuleException {
199  super(NbBundle.getMessage(ExtractRegistry.class, "ExtractRegistry.moduleName.text"), context);
200  this.context = context;
201 
202  final File rrRoot = InstalledFileLocator.getDefault().locate("rr", ExtractRegistry.class.getPackage().getName(), false); //NON-NLS
203  if (rrRoot == null) {
204  throw new IngestModuleException(Bundle.RegRipperNotFound());
205  }
206 
207  final File rrFullRoot = InstalledFileLocator.getDefault().locate("rr-full", ExtractRegistry.class.getPackage().getName(), false); //NON-NLS
208  if (rrFullRoot == null) {
209  throw new IngestModuleException(Bundle.RegRipperFullNotFound());
210  }
211 
212  String executableToRun = RIP_EXE;
213  if (!PlatformUtil.isWindowsOS()) {
214  executableToRun = RIP_PL;
215  }
216  rrHome = rrRoot.toPath();
217  String rrPath = rrHome.resolve(executableToRun).toString();
218  rrFullHome = rrFullRoot.toPath();
219 
220  if (!(new File(rrPath).exists())) {
221  throw new IngestModuleException(Bundle.RegRipperNotFound());
222  }
223  String rrFullPath = rrFullHome.resolve(executableToRun).toString();
224  if (!(new File(rrFullPath).exists())) {
225  throw new IngestModuleException(Bundle.RegRipperFullNotFound());
226  }
227  if (PlatformUtil.isWindowsOS()) {
228  rrCmd.add(rrPath);
229  rrFullCmd.add(rrFullPath);
230  } else {
231  String perl;
232  File usrBin = new File("/usr/bin/perl");
233  File usrLocalBin = new File("/usr/local/bin/perl");
234  if (usrBin.canExecute() && usrBin.exists() && !usrBin.isDirectory()) {
235  perl = "/usr/bin/perl";
236  } else if (usrLocalBin.canExecute() && usrLocalBin.exists() && !usrLocalBin.isDirectory()) {
237  perl = "/usr/local/bin/perl";
238  } else {
239  throw new IngestModuleException("perl not found in your system");
240  }
241  rrCmd.add(perl);
242  rrCmd.add(RIP_PL_INCLUDE_FLAG);
243  rrCmd.add(rrHome.toString());
244  rrCmd.add(rrPath);
245  rrFullCmd.add(perl);
246  rrFullCmd.add(RIP_PL_INCLUDE_FLAG);
247  rrFullCmd.add(rrFullHome.toString());
248  rrFullCmd.add(rrFullPath);
249  }
250  }
251 
255  private List<AbstractFile> findRegistryFiles() {
256  List<AbstractFile> allRegistryFiles = new ArrayList<>();
257  org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager();
258 
259  // find the sam hives', process this first so we can map the user id's and sids for later use
260  try {
261  allRegistryFiles.addAll(fileManager.findFiles(dataSource, "sam", "/system32/config")); //NON-NLS
262  } catch (TskCoreException ex) {
263  String msg = NbBundle.getMessage(this.getClass(),
264  "ExtractRegistry.findRegFiles.errMsg.errReadingFile", "sam");
265  logger.log(Level.WARNING, msg, ex);
266  this.addErrorMessage(this.getDisplayName() + ": " + msg);
267  }
268 
269  // find the user-specific ntuser-dat files
270  try {
271  allRegistryFiles.addAll(fileManager.findFiles(dataSource, "ntuser.dat")); //NON-NLS
272  } catch (TskCoreException ex) {
273  logger.log(Level.WARNING, "Error fetching 'ntuser.dat' file."); //NON-NLS
274  }
275 
276  // find the user-specific ntuser-dat files
277  try {
278  allRegistryFiles.addAll(fileManager.findFiles(dataSource, "usrclass.dat")); //NON-NLS
279  } catch (TskCoreException ex) {
280  logger.log(Level.WARNING, String.format("Error finding 'usrclass.dat' files."), ex); //NON-NLS
281  }
282 
283  // find the system hives'
284  String[] regFileNames = new String[]{"system", "software", "security"}; //NON-NLS
285  for (String regFileName : regFileNames) {
286  try {
287  allRegistryFiles.addAll(fileManager.findFiles(dataSource, regFileName, "/system32/config")); //NON-NLS
288  } catch (TskCoreException ex) {
289  String msg = NbBundle.getMessage(this.getClass(),
290  "ExtractRegistry.findRegFiles.errMsg.errReadingFile", regFileName);
291  logger.log(Level.WARNING, msg, ex);
292  this.addErrorMessage(this.getDisplayName() + ": " + msg);
293  }
294  }
295  return allRegistryFiles;
296  }
297 
304  private void analyzeRegistryFiles(long ingestJobId) {
305  List<AbstractFile> allRegistryFiles = findRegistryFiles();
306 
307  // open the log file
308  FileWriter logFile = null;
309  try {
310  logFile = new FileWriter(RAImageIngestModule.getRAOutputPath(currentCase, "reg", ingestJobId) + File.separator + "regripper-info.txt"); //NON-NLS
311  } catch (IOException ex) {
312  logger.log(Level.SEVERE, null, ex);
313  }
314 
315  for (AbstractFile regFile : allRegistryFiles) {
316  if (context.dataSourceIngestIsCancelled()) {
317  return;
318  }
319 
320  String regFileName = regFile.getName();
321  long regFileId = regFile.getId();
322  String regFileNameLocal = RAImageIngestModule.getRATempPath(currentCase, "reg", ingestJobId) + File.separator + regFileName;
323  String outputPathBase = RAImageIngestModule.getRAOutputPath(currentCase, "reg", ingestJobId) + File.separator + regFileName + "-regripper-" + Long.toString(regFileId); //NON-NLS
324  File regFileNameLocalFile = new File(regFileNameLocal);
325  try {
326  ContentUtils.writeToFile(regFile, regFileNameLocalFile, context::dataSourceIngestIsCancelled);
327  } catch (ReadContentInputStreamException ex) {
328  logger.log(Level.WARNING, String.format("Error reading registry file '%s' (id=%d).",
329  regFile.getName(), regFileId), ex); //NON-NLS
330  this.addErrorMessage(
331  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
332  this.getDisplayName(), regFileName));
333  continue;
334  } catch (IOException ex) {
335  logger.log(Level.SEVERE, String.format("Error writing temp registry file '%s' for registry file '%s' (id=%d).",
336  regFileNameLocal, regFile.getName(), regFileId), ex); //NON-NLS
337  this.addErrorMessage(
338  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
339  this.getDisplayName(), regFileName));
340  continue;
341  }
342 
343  if (context.dataSourceIngestIsCancelled()) {
344  break;
345  }
346 
347  try {
348  if (logFile != null) {
349  logFile.write(Long.toString(regFileId) + "\t" + regFile.getUniquePath() + "\n");
350  }
351  } catch (TskCoreException | IOException ex) {
352  logger.log(Level.SEVERE, null, ex);
353  }
354 
355  logger.log(Level.INFO, "{0}- Now getting registry information from {1}", new Object[]{getDisplayName(), regFileNameLocal}); //NON-NLS
356  RegOutputFiles regOutputFiles = ripRegistryFile(regFileNameLocal, outputPathBase);
357  if (context.dataSourceIngestIsCancelled()) {
358  break;
359  }
360 
361  // parse the autopsy-specific output
362  if (regOutputFiles.autopsyPlugins.isEmpty() == false && parseAutopsyPluginOutput(regOutputFiles.autopsyPlugins, regFile) == false) {
363  this.addErrorMessage(
364  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.failedParsingResults",
365  this.getDisplayName(), regFileName));
366  }
367 
368  if (context.dataSourceIngestIsCancelled()) {
369  return;
370  }
371 
372  // create a report for the full output
373  if (!regOutputFiles.fullPlugins.isEmpty()) {
374  //parse the full regripper output from SAM hive files
375  if (regFileNameLocal.toLowerCase().contains("sam") && parseSamPluginOutput(regOutputFiles.fullPlugins, regFile, ingestJobId) == false) {
376  this.addErrorMessage(
377  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.failedParsingResults",
378  this.getDisplayName(), regFileName));
379  } else if (regFileNameLocal.toLowerCase().contains("ntuser") || regFileNameLocal.toLowerCase().contains("usrclass")) {
380  try {
381  List<ShellBag> shellbags = ShellBagParser.parseShellbagOutput(regOutputFiles.fullPlugins);
382  createShellBagArtifacts(regFile, shellbags);
383  createRecentlyUsedArtifacts(regOutputFiles.fullPlugins, regFile);
384  } catch (IOException | TskCoreException ex) {
385  logger.log(Level.WARNING, String.format("Unable to get shell bags from file %s", regOutputFiles.fullPlugins), ex);
386  }
387  } else if (regFileNameLocal.toLowerCase().contains("system") && parseSystemPluginOutput(regOutputFiles.fullPlugins, regFile) == false) {
388  this.addErrorMessage(
389  NbBundle.getMessage(this.getClass(), "ExtractRegistry.analyzeRegFiles.failedParsingResults",
390  this.getDisplayName(), regFileName));
391  }
392 
393  if (context.dataSourceIngestIsCancelled()) {
394  return;
395  }
396 
397  try {
398  Report report = currentCase.addReport(regOutputFiles.fullPlugins,
399  NbBundle.getMessage(this.getClass(), "ExtractRegistry.parentModuleName.noSpace"),
400  "RegRipper " + regFile.getUniquePath(), regFile); //NON-NLS
401 
402  // Index the report content so that it will be available for keyword search.
403  KeywordSearchService searchService = Lookup.getDefault().lookup(KeywordSearchService.class);
404  if (null == searchService) {
405  logger.log(Level.WARNING, "Keyword search service not found. Report will not be indexed");
406  } else {
407  searchService.index(report);
408  report.close();
409  }
410  } catch (TskCoreException e) {
411  this.addErrorMessage("Error adding regripper output as Autopsy report: " + e.getLocalizedMessage()); //NON-NLS
412  }
413  }
414  // delete the hive
415  regFileNameLocalFile.delete();
416  }
417 
418  try {
419  if (logFile != null) {
420  logFile.close();
421  }
422  } catch (IOException ex) {
423  logger.log(Level.SEVERE, null, ex);
424  }
425  }
426 
434  private RegOutputFiles ripRegistryFile(String regFilePath, String outFilePathBase) {
435  String autopsyType = ""; // Type argument for rr for autopsy-specific modules
436  String fullType; // Type argument for rr for full set of modules
437 
438  RegOutputFiles regOutputFiles = new RegOutputFiles();
439 
440  if (regFilePath.toLowerCase().contains("system")) { //NON-NLS
441  autopsyType = "autopsysystem"; //NON-NLS
442  fullType = "system"; //NON-NLS
443  } else if (regFilePath.toLowerCase().contains("software")) { //NON-NLS
444  autopsyType = "autopsysoftware"; //NON-NLS
445  fullType = "software"; //NON-NLS
446  } else if (regFilePath.toLowerCase().contains("ntuser")) { //NON-NLS
447  autopsyType = "autopsyntuser"; //NON-NLS
448  fullType = "ntuser"; //NON-NLS
449  } else if (regFilePath.toLowerCase().contains("sam")) { //NON-NLS
450  //fullType sam output files are parsed for user information
451  fullType = "sam"; //NON-NLS
452  } else if (regFilePath.toLowerCase().contains("security")) { //NON-NLS
453  fullType = "security"; //NON-NLS
454  } else if (regFilePath.toLowerCase().contains("usrclass")) { //NON-NLS
455  fullType = "usrclass"; //NON-NLS
456  } else {
457  return regOutputFiles;
458  }
459 
460  // run the autopsy-specific set of modules
461  if (!autopsyType.isEmpty()) {
462  regOutputFiles.autopsyPlugins = outFilePathBase + "-autopsy.txt"; //NON-NLS
463  String errFilePath = outFilePathBase + "-autopsy.err.txt"; //NON-NLS
464  logger.log(Level.INFO, "Writing RegRipper results to: {0}", regOutputFiles.autopsyPlugins); //NON-NLS
465  executeRegRipper(rrCmd, rrHome, regFilePath, autopsyType, regOutputFiles.autopsyPlugins, errFilePath);
466  }
467  if (context.dataSourceIngestIsCancelled()) {
468  return regOutputFiles;
469  }
470 
471  // run the full set of rr modules
472  if (!fullType.isEmpty()) {
473  regOutputFiles.fullPlugins = outFilePathBase + "-full.txt"; //NON-NLS
474  String errFilePath = outFilePathBase + "-full.err.txt"; //NON-NLS
475  logger.log(Level.INFO, "Writing Full RegRipper results to: {0}", regOutputFiles.fullPlugins); //NON-NLS
476  executeRegRipper(rrFullCmd, rrFullHome, regFilePath, fullType, regOutputFiles.fullPlugins, errFilePath);
477  try {
478  scanErrorLogs(errFilePath);
479  } catch (IOException ex) {
480  logger.log(Level.SEVERE, String.format("Unable to run RegRipper on %s", regFilePath), ex); //NON-NLS
481  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getDisplayName(), regFilePath));
482  }
483  }
484  return regOutputFiles;
485  }
486 
487  private void scanErrorLogs(String errFilePath) throws IOException {
488  File regfile = new File(errFilePath);
489  try (BufferedReader reader = new BufferedReader(new FileReader(regfile))) {
490  String line = reader.readLine();
491  while (line != null) {
492  line = line.trim();
493  if (line.toLowerCase().contains("error") || line.toLowerCase().contains("@inc")) {
494  logger.log(Level.WARNING, "Regripper file {0} contains errors from run", errFilePath); //NON-NLS
495 
496  }
497  line = reader.readLine();
498  }
499  }
500  }
501 
502  private void executeRegRipper(List<String> regRipperPath, Path regRipperHomeDir, String hiveFilePath, String hiveFileType, String outputFile, String errFile) {
503  try {
504  List<String> commandLine = new ArrayList<>();
505  for (String cmd : regRipperPath) {
506  commandLine.add(cmd);
507  }
508  commandLine.add("-r"); //NON-NLS
509  commandLine.add(hiveFilePath);
510  commandLine.add("-f"); //NON-NLS
511  commandLine.add(hiveFileType);
512 
513  ProcessBuilder processBuilder = new ProcessBuilder(commandLine);
514  processBuilder.directory(regRipperHomeDir.toFile()); // RegRipper 2.8 has to be run from its own directory
515  processBuilder.redirectOutput(new File(outputFile));
516  processBuilder.redirectError(new File(errFile));
517  ExecUtil.execute(processBuilder, new DataSourceIngestModuleProcessTerminator(context, true));
518  } catch (IOException ex) {
519  logger.log(Level.SEVERE, String.format("Error running RegRipper on %s", hiveFilePath), ex); //NON-NLS
520  this.addErrorMessage(NbBundle.getMessage(this.getClass(), "ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getDisplayName(), hiveFilePath));
521  }
522  }
523 
524  // @@@ VERIFY that we are doing the right thing when we parse multiple NTUSER.DAT
533  private boolean parseAutopsyPluginOutput(String regFilePath, AbstractFile regFile) {
534  FileInputStream fstream = null;
535  List<BlackboardArtifact> newArtifacts = new ArrayList<>();
536  try {
537  // Read the file in and create a Document and elements
538  File regfile = new File(regFilePath);
539  fstream = new FileInputStream(regfile);
540  String regString = new Scanner(fstream, "UTF-8").useDelimiter("\\Z").next(); //NON-NLS
541  String startdoc = "<?xml version=\"1.0\"?><document>"; //NON-NLS
542  String result = regString.replaceAll("----------------------------------------", "");
543  result = result.replaceAll("\\n", ""); //NON-NLS
544  result = result.replaceAll("\\r", ""); //NON-NLS
545  result = result.replaceAll("'", "&apos;"); //NON-NLS
546  result = result.replaceAll("&", "&amp;"); //NON-NLS
547  result = result.replace('\0', ' '); // NON-NLS
548  String enddoc = "</document>"; //NON-NLS
549  String stringdoc = startdoc + result + enddoc;
550  DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
551  Document doc = builder.parse(new InputSource(new StringReader(stringdoc)));
552 
553  // cycle through the elements in the doc
554  Element oroot = doc.getDocumentElement();
555  NodeList children = oroot.getChildNodes();
556  int len = children.getLength();
557  for (int i = 0; i < len; i++) {
558 
559  if (context.dataSourceIngestIsCancelled()) {
560  return false;
561  }
562 
563  Element tempnode = (Element) children.item(i);
564 
565  String dataType = tempnode.getNodeName();
566  NodeList timenodes = tempnode.getElementsByTagName("mtime"); //NON-NLS
567  Long mtime = null;
568  if (timenodes.getLength() > 0) {
569  Element timenode = (Element) timenodes.item(0);
570  String etime = timenode.getTextContent().trim();
571  //sometimes etime will be an empty string and therefore can not be parsed into a date
572  if (etime != null && !etime.isEmpty()) {
573  try {
574  mtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy", US).parse(etime).getTime();
575  String Tempdate = mtime.toString();
576  mtime = Long.valueOf(Tempdate) / MS_IN_SEC;
577  } catch (ParseException ex) {
578  logger.log(Level.WARNING, "Failed to parse epoch time when parsing the registry.", ex); //NON-NLS
579  }
580  }
581  }
582 
583  NodeList artroots = tempnode.getElementsByTagName("artifacts"); //NON-NLS
584  if (artroots.getLength() == 0) {
585  // If there isn't an artifact node, skip this entry
586  continue;
587  }
588 
589  Element artroot = (Element) artroots.item(0);
590  NodeList myartlist = artroot.getChildNodes();
591  String parentModuleName = RecentActivityExtracterModuleFactory.getModuleName();
592 
593  // If all artifact nodes should really go under one Blackboard artifact, need to process it differently
594  switch (dataType) {
595  case "WinVersion": //NON-NLS
596  String version = "";
597  String systemRoot = "";
598  String productId = "";
599  String regOwner = "";
600  String regOrg = "";
601  Long installtime = null;
602  for (int j = 0; j < myartlist.getLength(); j++) {
603  Node artchild = myartlist.item(j);
604  // If it has attributes, then it is an Element (based off API)
605  if (artchild.hasAttributes()) {
606  Element artnode = (Element) artchild;
607 
608  String value = artnode.getTextContent();
609  if (value != null) {
610  value = value.trim();
611  }
612  String name = artnode.getAttribute("name"); //NON-NLS
613  if (name == null) {
614  continue;
615  }
616  switch (name) {
617  case "ProductName": // NON-NLS
618  version = value;
619  break;
620  case "CSDVersion": // NON-NLS
621  // This is dependant on the fact that ProductName shows up first in the module output
622  version = version + " " + value;
623  break;
624  case "SystemRoot": //NON-NLS
625  systemRoot = value;
626  break;
627  case "ProductId": //NON-NLS
628  productId = value;
629  break;
630  case "RegisteredOwner": //NON-NLS
631  regOwner = value;
632  break;
633  case "RegisteredOrganization": //NON-NLS
634  regOrg = value;
635  break;
636  case "InstallDate": //NON-NLS
637  if (value != null && !value.isEmpty()) {
638  try {
639  installtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyyZ", US).parse(value + "+0000").getTime();
640  String Tempdate = installtime.toString();
641  installtime = Long.valueOf(Tempdate) / MS_IN_SEC;
642  } catch (ParseException e) {
643  logger.log(Level.WARNING, "RegRipper::Conversion on DateTime -> ", e); //NON-NLS
644  }
645  }
646  break;
647  default:
648  break;
649  }
650  }
651  }
652  try {
653  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
654  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, version));
655  if (installtime != null) {
656  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, installtime));
657  }
658  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, systemRoot));
659  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PRODUCT_ID, parentModuleName, productId));
660  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_OWNER, parentModuleName, regOwner));
661  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ORGANIZATION, parentModuleName, regOrg));
662 
663  // Check if there is already an OS_INFO artifact for this file, and add to that if possible.
664  ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
665  if (results.isEmpty()) {
666  newArtifacts.add(createArtifactWithAttributes(BlackboardArtifact.Type.TSK_OS_INFO, regFile, bbattributes));
667  } else {
668  results.get(0).addAttributes(bbattributes);
669  }
670 
671  } catch (TskCoreException ex) {
672  logger.log(Level.SEVERE, String.format("Error adding installed program artifact to blackboard for file %d.", regFile.getId()), ex); //NON-NLS
673  }
674  break;
675  case "Profiler": // NON-NLS
676  String os = "";
677  String procArch = "";
678  String tempDir = "";
679  for (int j = 0; j < myartlist.getLength(); j++) {
680  Node artchild = myartlist.item(j);
681  // If it has attributes, then it is an Element (based off API)
682  if (artchild.hasAttributes()) {
683  Element artnode = (Element) artchild;
684 
685  String value = artnode.getTextContent().trim();
686  String name = artnode.getAttribute("name"); //NON-NLS
687  switch (name) {
688  case "OS": // NON-NLS
689  os = value;
690  break;
691  case "PROCESSOR_ARCHITECTURE": // NON-NLS
692  procArch = value;
693  break;
694  case "PROCESSOR_IDENTIFIER": //NON-NLS
695  break;
696  case "TEMP": //NON-NLS
697  tempDir = value;
698  break;
699  default:
700  break;
701  }
702  }
703  }
704  try {
705  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
706  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VERSION, parentModuleName, os));
707  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE, parentModuleName, procArch));
708  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEMP_DIR, parentModuleName, tempDir));
709 
710  // Check if there is already an OS_INFO artifact for this file and add to that if possible
711  ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
712  if (results.isEmpty()) {
713  newArtifacts.add(createArtifactWithAttributes(BlackboardArtifact.Type.TSK_OS_INFO, regFile, bbattributes));
714  } else {
715  results.get(0).addAttributes(bbattributes);
716  }
717  } catch (TskCoreException ex) {
718  logger.log(Level.SEVERE, String.format("Error adding installed os_info to blackboard for file %d.", regFile.getId()), ex); //NON-NLS
719  }
720  break;
721  case "CompName": // NON-NLS
722  for (int j = 0; j < myartlist.getLength(); j++) {
723  Node artchild = myartlist.item(j);
724  // If it has attributes, then it is an Element (based off API)
725  if (artchild.hasAttributes()) {
726  Element artnode = (Element) artchild;
727 
728  String value = artnode.getTextContent().trim();
729  String name = artnode.getAttribute("name"); //NON-NLS
730 
731  if (name.equals("ComputerName")) { // NON-NLS
732  compName = value;
733  } else if (name.equals("Domain")) { // NON-NLS
734  domainName = value;
735  }
736  }
737  }
738  try {
739  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
740  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, compName));
741  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, parentModuleName, domainName));
742 
743  // Check if there is already an OS_INFO artifact for this file and add to that if possible
744  ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
745  if (results.isEmpty()) {
746  newArtifacts.add(createArtifactWithAttributes(BlackboardArtifact.Type.TSK_OS_INFO, regFile, bbattributes));
747  } else {
748  results.get(0).addAttributes(bbattributes);
749  }
750  for (Map.Entry<String, String> userMap : getUserNameMap().entrySet()) {
751  String sid = "";
752  try {
753  sid = userMap.getKey();
754  String userName = userMap.getValue();
755  // Accounts in the SAM are all local accounts
756  createOrUpdateOsAccount(regFile, sid, userName, null, null, OsAccountRealm.RealmScope.LOCAL);
757  } catch (TskCoreException | TskDataException | NotUserSIDException ex) {
758  logger.log(Level.WARNING, String.format("Failed to update Domain for existing OsAccount: %s, sid: %s", regFile.getId(), sid), ex);
759  }
760  }
761  } catch (TskCoreException ex) {
762  logger.log(Level.SEVERE, String.format("Error adding os_info artifact to blackboard for file %d.", regFile.getId()), ex); //NON-NLS
763  }
764  break;
765  default:
766  for (int j = 0; j < myartlist.getLength(); j++) {
767  Node artchild = myartlist.item(j);
768  // If it has attributes, then it is an Element (based off API)
769  if (artchild.hasAttributes()) {
770  Element artnode = (Element) artchild;
771 
772  String value = artnode.getTextContent().trim();
773  Collection<BlackboardAttribute> bbattributes = new ArrayList<>();
774 
775  switch (dataType) {
776  case "recentdocs": //NON-NLS
777  // BlackboardArtifact bbart = tskCase.getContentById(orgId).newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT);
778  // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", dataType, mtime));
779  // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity", dataType, mtimeItem));
780  // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), "RecentActivity", dataType, value));
781  // bbart.addAttributes(bbattributes);
782  // @@@ BC: Why are we ignoring this...
783  break;
784  case "usb": //NON-NLS
785  try {
786  Long usbMtime = Long.valueOf("0");
787  if (!artnode.getAttribute("mtime").isEmpty()) {
788  usbMtime = Long.parseLong(artnode.getAttribute("mtime")); //NON-NLS
789  }
790  usbMtime = Long.valueOf(usbMtime.toString());
791  if (usbMtime > 0) {
792  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime));
793  }
794  String dev = artnode.getAttribute("dev"); //NON-NLS
795  String make = "";
796  String model = dev;
797  if (dev.toLowerCase().contains("vid")) { //NON-NLS
798  USBInfo info = USB_MAPPER.parseAndLookup(dev);
799  if (info.getVendor() != null) {
800  make = info.getVendor();
801  }
802  if (info.getProduct() != null) {
803  model = info.getProduct();
804  }
805  }
806  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make));
807  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model));
808  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value));
809  newArtifacts.add(createArtifactWithAttributes(BlackboardArtifact.Type.TSK_DEVICE_ATTACHED, regFile, bbattributes));
810  } catch (TskCoreException ex) {
811  logger.log(Level.SEVERE, String.format("Error adding device_attached artifact to blackboard for file %d.", regFile.getId()), ex); //NON-NLS
812  }
813  break;
814  case "uninstall": //NON-NLS
815  Long itemMtime = null;
816  try {
817  String mTimeAttr = artnode.getAttribute("mtime");
818  if (mTimeAttr != null && !mTimeAttr.isEmpty()) {
819  itemMtime = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy", US).parse(mTimeAttr).getTime(); //NON-NLS
820  itemMtime /= MS_IN_SEC;
821  }
822  } catch (ParseException ex) {
823  logger.log(Level.SEVERE, "Failed to parse epoch time for installed program artifact.", ex); //NON-NLS
824  }
825 
826  try {
827  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, value));
828  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, itemMtime));
829  BlackboardArtifact bbart = regFile.newDataArtifact(new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_INSTALLED_PROG), bbattributes);
830  newArtifacts.add(bbart);
831  } catch (TskCoreException ex) {
832  logger.log(Level.SEVERE, "Error adding installed program artifact to blackboard.", ex); //NON-NLS
833  }
834  break;
835  case "office": //NON-NLS
836  String officeName = artnode.getAttribute("name"); //NON-NLS
837 
838  try {
839  // @@@ BC: Consider removing this after some more testing. It looks like an Mtime associated with the root key and not the individual item
840  if (mtime != null) {
841  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, parentModuleName, mtime));
842  }
843  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, officeName));
844  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, parentModuleName, value));
845  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, artnode.getNodeName()));
846  BlackboardArtifact bbart = regFile.newDataArtifact(new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_RECENT_OBJECT), bbattributes);
847 
848  newArtifacts.add(bbart);
849  } catch (TskCoreException ex) {
850  logger.log(Level.SEVERE, "Error adding recent object artifact to blackboard.", ex); //NON-NLS
851  }
852  break;
853 
854  case "ProcessorArchitecture": //NON-NLS
855  // Architecture is now included under Profiler
856  //try {
857  // String processorArchitecture = value;
858  // if (processorArchitecture.equals("AMD64"))
859  // processorArchitecture = "x86-64";
860 
861  // BlackboardArtifact bbart = regFile.newArtifact(ARTIFACT_TYPE.TSK_OS_INFO);
862  // bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE.getTypeID(), parentModuleName, processorArchitecture));
863  // bbart.addAttributes(bbattributes);
864  //} catch (TskCoreException ex) {
865  // logger.log(Level.SEVERE, "Error adding os info artifact to blackboard."); //NON-NLS
866  //}
867  break;
868 
869  case "ProfileList": //NON-NLS
870  String homeDir = value;
871  String sid = artnode.getAttribute("sid"); //NON-NLS
872  String username = artnode.getAttribute("username"); //NON-NLS
873  String domName = domainName;
874 
875  // accounts in profileList can be either domain or local
876  // Assume domain unless the SID was seen before in the SAM (which is only local).
877  OsAccountRealm.RealmScope scope = OsAccountRealm.RealmScope.DOMAIN;
878  if (isDomainIdInSAMList(sid)) {
879  domName = null;
880  scope = OsAccountRealm.RealmScope.LOCAL;
881  }
882 
883  try {
884  createOrUpdateOsAccount(regFile, sid, username, homeDir, domName, scope);
885  } catch (TskCoreException | TskDataException | NotUserSIDException ex) {
886  logger.log(Level.SEVERE, String.format("Failed to create OsAccount for file: %s, sid: %s", regFile.getId(), sid), ex);
887  }
888  break;
889 
890  case "NtuserNetwork": // NON-NLS
891  try {
892  String localPath = artnode.getAttribute("localPath"); //NON-NLS
893  String remoteName = value;
894 
895  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH,
896  parentModuleName, localPath));
897  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH,
898  parentModuleName, remoteName));
899  BlackboardArtifact bbart = regFile.newDataArtifact(new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_REMOTE_DRIVE), bbattributes);
900  newArtifacts.add(bbart);
901  } catch (TskCoreException ex) {
902  logger.log(Level.SEVERE, "Error adding network artifact to blackboard.", ex); //NON-NLS
903  }
904  break;
905  case "SSID": // NON-NLS
906  String adapter = artnode.getAttribute("adapter"); //NON-NLS
907  try {
908  Long lastWriteTime = Long.parseLong(artnode.getAttribute("writeTime")); //NON-NLS
909  lastWriteTime = Long.valueOf(lastWriteTime.toString());
910  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SSID, parentModuleName, value));
911  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, lastWriteTime));
912  bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, adapter));
913  BlackboardArtifact bbart = regFile.newDataArtifact(new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_WIFI_NETWORK), bbattributes);
914  newArtifacts.add(bbart);
915  } catch (TskCoreException ex) {
916  logger.log(Level.SEVERE, "Error adding SSID artifact to blackboard.", ex); //NON-NLS
917  }
918  break;
919  case "shellfolders": // NON-NLS
920  // The User Shell Folders subkey stores the paths to Windows Explorer folders for the current user of the computer
921  // (https://technet.microsoft.com/en-us/library/Cc962613.aspx).
922  // No useful information. Skip.
923  break;
924 
925  default:
926  logger.log(Level.SEVERE, "Unrecognized node name: {0}", dataType); //NON-NLS
927  break;
928  }
929  }
930  }
931  break;
932  }
933  } // for
934  return true;
935  } catch (FileNotFoundException ex) {
936  logger.log(Level.WARNING, String.format("Error finding the registry file: %s", regFilePath), ex); //NON-NLS
937  } catch (SAXException ex) {
938  logger.log(Level.WARNING, String.format("Error parsing the registry XML: %s", regFilePath), ex); //NON-NLS
939  } catch (IOException ex) {
940  logger.log(Level.WARNING, String.format("Error building the document parser: %s", regFilePath), ex); //NON-NLS
941  } catch (ParserConfigurationException ex) {
942  logger.log(Level.WARNING, String.format("Error configuring the registry parser: %s", regFilePath), ex); //NON-NLS
943  } finally {
944  try {
945  if (fstream != null) {
946  fstream.close();
947  }
948  } catch (IOException ex) {
949  }
950 
951  if (!context.dataSourceIngestIsCancelled()) {
952  postArtifacts(newArtifacts);
953  }
954  }
955  return false;
956  }
957 
958  private boolean parseSystemPluginOutput(String regfilePath, AbstractFile regAbstractFile) {
959  File regfile = new File(regfilePath);
960  try (BufferedReader reader = new BufferedReader(new FileReader(regfile))) {
961  String line = reader.readLine();
962  while (line != null) {
963  line = line.trim();
964 
965  if (line.toLowerCase().matches("^bam v.*")) {
966  parseBamKey(regAbstractFile, reader, Bundle.Registry_System_Bam());
967  } else if (line.toLowerCase().matches("^bthport v..*")) {
968  parseBlueToothDevices(regAbstractFile, reader);
969  }
970  line = reader.readLine();
971  }
972  return true;
973  } catch (FileNotFoundException ex) {
974  logger.log(Level.WARNING, "Error finding the registry file.", ex); //NON-NLS
975  } catch (IOException ex) {
976  logger.log(Level.WARNING, "Error reading the system hive: {0}", ex); //NON-NLS
977  }
978 
979  return false;
980 
981  }
982 
995  private void parseBlueToothDevices(AbstractFile regFile, BufferedReader reader) throws FileNotFoundException, IOException {
996  List<BlackboardArtifact> bbartifacts = new ArrayList<>();
997  String line = reader.readLine();
998  while ((line != null) && (!line.contains(SECTION_DIVIDER))) {
999  line = reader.readLine();
1000 
1001  if (line != null) {
1002  line = line.trim();
1003  }
1004 
1005  if ((line != null) && (line.toLowerCase().contains("device unique id"))) {
1006  // Columns are seperated by colons :
1007  // Data : Values
1008  // Record is 4 lines in length (Device Unique Id, Name, Last Seen, LastConnected
1009  while (line != null && !line.contains(SECTION_DIVIDER) && !line.isEmpty() && !line.toLowerCase().contains("radio support not found")) {
1010  Collection<BlackboardAttribute> attributes = new ArrayList<>();
1011  addBlueToothAttribute(line, attributes, TSK_DEVICE_ID);
1012  line = reader.readLine();
1013  // Name may not exist, check for it to make sure.
1014  if ((line != null) && (line.toLowerCase().contains("name"))) {
1015  addBlueToothAttribute(line, attributes, TSK_NAME);
1016  line = reader.readLine();
1017  }
1018  addBlueToothAttribute(line, attributes, TSK_DATETIME);
1019  line = reader.readLine();
1020  addBlueToothAttribute(line, attributes, TSK_DATETIME_ACCESSED);
1021 
1022  try {
1023  bbartifacts.add(createArtifactWithAttributes(BlackboardArtifact.Type.TSK_BLUETOOTH_PAIRING, regFile, attributes));
1024  } catch (TskCoreException ex) {
1025  logger.log(Level.SEVERE, String.format("Failed to create bluetooth_pairing artifact for file %d", regFile.getId()), ex);
1026  }
1027  // Read blank line between records then next read line is start of next block
1028  reader.readLine();
1029  line = reader.readLine();
1030  }
1031 
1032  if (line != null) {
1033  line = line.trim();
1034  }
1035  }
1036  }
1037 
1038  if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1039  postArtifacts(bbartifacts);
1040  }
1041  }
1042 
1043  private void addBlueToothAttribute(String line, Collection<BlackboardAttribute> attributes, ATTRIBUTE_TYPE attributeType) {
1044  if (line == null) {
1045  return;
1046  }
1047 
1048  String tokens[] = line.split(": ");
1049  if (tokens.length > 1 && !tokens[1].isEmpty()) {
1050  String tokenString = tokens[1];
1051  if (attributeType.getDisplayName().toLowerCase().contains("date")) {
1052  String dateString = tokenString.toLowerCase().replace(" z", "");
1053  // date format for plugin Tue Jun 23 10:27:54 2020 Z
1054  SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy", US);
1055  Long dateLong = Long.valueOf(0);
1056  try {
1057  Date newDate = dateFormat.parse(dateString);
1058  dateLong = newDate.getTime() / 1000;
1059  } catch (ParseException ex) {
1060  // catching error and displaying date that could not be parsed
1061  // we set the timestamp to 0 and continue on processing
1062  logger.log(Level.WARNING, String.format("Failed to parse date/time %s for Bluetooth Last Seen attribute.", dateString), ex); //NON-NLS
1063  }
1064  attributes.add(new BlackboardAttribute(attributeType, getDisplayName(), dateLong));
1065  } else {
1066  attributes.add(new BlackboardAttribute(attributeType, getDisplayName(), tokenString));
1067  }
1068  }
1069  }
1070 
1081  private boolean parseSamPluginOutput(String regFilePath, AbstractFile regAbstractFile, long ingestJobId) {
1082 
1083  File regfile = new File(regFilePath);
1084  List<BlackboardArtifact> newArtifacts = new ArrayList<>();
1085  try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(regfile), StandardCharsets.UTF_8))) {
1086  // Read the file in and create a Document and elements
1087  String userInfoSection = "User Information";
1088  String previousLine = null;
1089  String line = bufferedReader.readLine();
1090  Set<Map<String, String>> userSet = new HashSet<>();
1091  Map<String, List<String>> groupMap = null;
1092  while (line != null) {
1093  if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains(userInfoSection)) {
1094  readUsers(bufferedReader, userSet);
1095  }
1096 
1097  if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains("Group Membership Information")) {
1098  groupMap = readGroups(bufferedReader);
1099  }
1100 
1101  previousLine = line;
1102  line = bufferedReader.readLine();
1103  }
1104  Map<String, Map<String, String>> userInfoMap = new HashMap<>();
1105  //load all the user info which was read into a map
1106  for (Map<String, String> userInfo : userSet) {
1107  String sid = userInfo.get(SID_KEY);
1108  userInfoMap.put(sid, userInfo);
1109  addSIDToSAMList(sid);
1110  }
1111 
1112  // New OsAccount Code
1113  OsAccountManager accountMgr = tskCase.getOsAccountManager();
1114  HostManager hostMrg = tskCase.getHostManager();
1115  Host host = hostMrg.getHostByDataSource((DataSource) dataSource);
1116 
1117  List<OsAccount> existingAccounts = accountMgr.getOsAccounts(host);
1118  for (OsAccount osAccount : existingAccounts) {
1119  Optional<String> optional = osAccount.getAddr();
1120  if (!optional.isPresent()) {
1121  continue;
1122  }
1123 
1124  String sid = optional.get();
1125  Map<String, String> userInfo = userInfoMap.remove(sid);
1126  if (userInfo != null) {
1127  addAccountInstance(accountMgr, osAccount, (DataSource) dataSource);
1128  updateOsAccount(osAccount, userInfo, groupMap.get(sid), regAbstractFile);
1129  }
1130  }
1131 
1132  //add remaining userinfos as accounts;
1133  for (Map<String, String> userInfo : userInfoMap.values()) {
1134  OsAccount osAccount = accountMgr.newWindowsOsAccount(userInfo.get(SID_KEY), null, null, host, OsAccountRealm.RealmScope.LOCAL);
1135  accountMgr.newOsAccountInstance(osAccount, (DataSource) dataSource, OsAccountInstance.OsAccountInstanceType.LAUNCHED);
1136  updateOsAccount(osAccount, userInfo, groupMap.get(userInfo.get(SID_KEY)), regAbstractFile);
1137  }
1138  return true;
1139  } catch (FileNotFoundException ex) {
1140  logger.log(Level.WARNING, "Error finding the registry file.", ex); //NON-NLS
1141  } catch (IOException ex) {
1142  logger.log(Level.WARNING, "Error building the document parser: {0}", ex); //NON-NLS
1143  } catch (TskDataException | TskCoreException ex) {
1144  logger.log(Level.WARNING, "Error updating TSK_OS_ACCOUNT artifacts to include newly parsed data.", ex); //NON-NLS
1145  } catch (OsAccountManager.NotUserSIDException ex) {
1146  logger.log(Level.WARNING, "Error creating OS Account, input SID is not a user SID.", ex); //NON-NLS
1147  } finally {
1148  if (!context.dataSourceIngestIsCancelled()) {
1149  postArtifacts(newArtifacts);
1150  }
1151  }
1152  return false;
1153  }
1154 
1166  private void readUsers(BufferedReader bufferedReader, Set<Map<String, String>> users) throws IOException {
1167  String line = bufferedReader.readLine();
1168  //read until end of file or next section divider
1169  String userName = "";
1170  String user_rid = "";
1171  while (line != null && !line.contains(SECTION_DIVIDER)) {
1172  //when a user name field exists read the name and id number
1173  if (line.contains(USERNAME_KEY)) {
1174  String regx = USERNAME_KEY + "\\s*?:";
1175  String userNameAndIdString = line.replaceAll(regx, "");
1176  userName = userNameAndIdString.substring(0, userNameAndIdString.lastIndexOf('[')).trim();
1177  user_rid = userNameAndIdString.substring(userNameAndIdString.lastIndexOf('['), userNameAndIdString.lastIndexOf(']'));
1178  } else if (line.contains(SID_KEY) && !userName.isEmpty()) {
1179  Map.Entry<String, String> entry = getSAMKeyValue(line);
1180 
1181  HashMap<String, String> userInfo = new HashMap<>();
1182  userInfo.put(USERNAME_KEY, userName);
1183  userInfo.put(RID_KEY, user_rid);
1184  userInfo.put(entry.getKey(), entry.getValue());
1185 
1186  //continue reading this users information until end of file or a blank line between users
1187  line = bufferedReader.readLine();
1188  while (line != null && !line.isEmpty()) {
1189  entry = getSAMKeyValue(line);
1190  if (entry != null) {
1191  userInfo.put(entry.getKey(), entry.getValue());
1192  }
1193  line = bufferedReader.readLine();
1194  }
1195  users.add(userInfo);
1196 
1197  userName = "";
1198  }
1199  line = bufferedReader.readLine();
1200  }
1201  }
1202 
1212  private void createRecentlyUsedArtifacts(String regFileName, AbstractFile regFile) throws FileNotFoundException, IOException {
1213  File regfile = new File(regFileName);
1214  try (BufferedReader reader = new BufferedReader(new FileReader(regfile))) {
1215  String line = reader.readLine();
1216  while (line != null) {
1217  line = line.trim();
1218 
1219  if (line.matches("^adoberdr v.*")) {
1220  parseAdobeMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Adobe());
1221  } else if (line.matches("^mpmru v.*")) {
1222  parseMediaPlayerMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Mediaplayer());
1223  } else if (line.matches("^trustrecords v.*")) {
1224  parseOfficeTrustRecords(regFile, reader, Bundle.Recently_Used_Artifacts_Office_Trustrecords());
1225  } else if (line.matches("^ArcHistory:")) {
1226  parse7ZipMRU(regFile, reader, Bundle.Recently_Used_Artifacts_ArcHistory());
1227  } else if (line.matches("^applets v.*")) {
1228  parseGenericMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Applets());
1229  } else if (line.matches("^mmc v.*")) {
1230  parseGenericMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Mmc());
1231  } else if (line.matches("^winrar v.*")) {
1232  parseWinRARMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Winrar());
1233  } else if (line.matches("^officedocs2010 v.*")) {
1234  parseOfficeDocs2010MRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Officedocs());
1235  }
1236  line = reader.readLine();
1237  }
1238  }
1239  }
1240 
1252  private void parseBamKey(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException {
1253  List<BlackboardArtifact> bbartifacts = new ArrayList<>();
1254  String line = reader.readLine();
1255  // Read thru first bam output to get to second bam output which is the same but delimited
1256  while (!line.contains(SECTION_DIVIDER)) {
1257  line = reader.readLine();
1258  line = line.trim();
1259  }
1260  line = reader.readLine();
1261  line = line.trim();
1262  while (!line.contains(SECTION_DIVIDER)) {
1263  // Split the line into it parts based on delimiter of "|"
1264  // 1570493613|BAM|||\Device\HarddiskVolume3\Program Files\TechSmith\Snagit 2018\Snagit32.exe (S-1-5-21-3042408413-2583535980-1301764466-1001)
1265  String tokens[] = line.split("\\|");
1266  Long progRunDateTime = Long.valueOf(tokens[0]);
1267  // Split on " (S-" as this signifies a User SID, if S- not used then may have issues becuase of (x86) in path is valid.
1268  // We can add the S- back to the string that we split on since S- is a valid beginning of a User SID
1269  String fileNameSid[] = tokens[4].split("\\s+\\(S-");
1270  String userSid = "S-" + fileNameSid[1].substring(0, fileNameSid[1].length() - 1);
1271  String userName = getUserNameMap().get(userSid);
1272  if (userName == null) {
1273  userName = userSid;
1274  }
1275  String fileName = fileNameSid[0];
1276  if (fileName.startsWith("\\Device\\HarddiskVolume")) {
1277  // Start at point past the 2nd slash
1278  int fileNameStart = fileName.indexOf('\\', 16);
1279  fileName = fileName.substring(fileNameStart, fileName.length());
1280 
1281  }
1282  Collection<BlackboardAttribute> attributes = new ArrayList<>();
1283  attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, getDisplayName(), fileName));
1284  attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, getDisplayName(), userName));
1285  attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, getDisplayName(), progRunDateTime));
1286  attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COMMENT, getDisplayName(), comment));
1287 
1288  try {
1289  BlackboardArtifact bba = createArtifactWithAttributes(BlackboardArtifact.Type.TSK_PROG_RUN, regFile, attributes);
1290  bbartifacts.add(bba);
1291  bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba);
1292  if (bba != null) {
1293  bbartifacts.add(bba);
1294  }
1295  } catch (TskCoreException ex) {
1296  logger.log(Level.SEVERE, String.format("Failed to create TSK_PROG_RUN artifact for file %d", regFile.getId()), ex);
1297  }
1298  line = reader.readLine();
1299  }
1300  if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1301  postArtifacts(bbartifacts);
1302  }
1303  }
1304 
1316  private void parseAdobeMRUList(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException {
1317  List<BlackboardArtifact> bbartifacts = new ArrayList<>();
1318  String line = reader.readLine();
1319  SimpleDateFormat adobePluginDateFormat = new SimpleDateFormat("yyyyMMddHHmmssZ", US);
1320  Long adobeUsedTime = Long.valueOf(0);
1321  while (!line.contains(SECTION_DIVIDER)) {
1322  line = reader.readLine();
1323  line = line.trim();
1324  if (line.matches("^Key name,file name,sDate,uFileSize,uPageCount")) {
1325  line = reader.readLine();
1326  // Columns are
1327  // Key name, file name, sDate, uFileSize, uPageCount
1328  while (!line.contains(SECTION_DIVIDER)) {
1329  // Split csv line, handles double quotes around individual file names
1330  // since file names can contain commas
1331  String tokens[] = line.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)");
1332  String fileName = tokens[1].substring(0, tokens[1].length() - 1);
1333  fileName = fileName.replace("\"", "");
1334  if (fileName.charAt(0) == '/') {
1335  fileName = fileName.substring(1, fileName.length() - 1);
1336  fileName = fileName.replaceFirst("/", ":/");
1337  }
1338  // Check to see if more then 2 tokens, Date may not be populated, will default to 0
1339  if (tokens.length > 2) {
1340  // Time in the format of 20200131104456-05'00'
1341  try {
1342  String fileUsedTime = tokens[2].replaceAll("'", "");
1343  Date usedDate = adobePluginDateFormat.parse(fileUsedTime);
1344  adobeUsedTime = usedDate.getTime() / 1000;
1345  } catch (ParseException ex) {
1346  // catching error and displaying date that could not be parsed
1347  // we set the timestamp to 0 and continue on processing
1348  logger.log(Level.WARNING, String.format("Failed to parse date/time %s for adobe file artifact.", tokens[2]), ex); //NON-NLS
1349  }
1350  }
1351  Collection<BlackboardAttribute> attributes = new ArrayList<>();
1352  attributes.add(new BlackboardAttribute(TSK_PATH, getDisplayName(), fileName));
1353  attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, getDisplayName(), adobeUsedTime));
1354  attributes.add(new BlackboardAttribute(TSK_COMMENT, getDisplayName(), comment));
1355  try {
1356  BlackboardArtifact bba = createArtifactWithAttributes(BlackboardArtifact.Type.TSK_RECENT_OBJECT, regFile, attributes);
1357  if (bba != null) {
1358  bbartifacts.add(bba);
1359  fileName = fileName.replace("\0", "");
1360  bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba);
1361  if (bba != null) {
1362  bbartifacts.add(bba);
1363  }
1364  }
1365  } catch (TskCoreException ex) {
1366  logger.log(Level.SEVERE, String.format("Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1367  }
1368  line = reader.readLine();
1369  }
1370  line = line.trim();
1371  }
1372  }
1373  if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1374  postArtifacts(bbartifacts);
1375  }
1376  }
1377 
1390  private void parseMediaPlayerMRUList(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException {
1391  List<BlackboardArtifact> bbartifacts = new ArrayList<>();
1392  String line = reader.readLine();
1393  while (!line.contains(SECTION_DIVIDER)) {
1394  line = reader.readLine();
1395  line = line.trim();
1396  if (line.contains("LastWrite")) {
1397  line = reader.readLine();
1398  // Columns are
1399  // FileX -> <Media file>
1400  while (!line.contains(SECTION_DIVIDER) && !line.contains("RecentFileList has no values.")) {
1401  // Split line on "> " which is the record delimiter between position and file
1402  String tokens[] = line.split("> ");
1403  String fileName = tokens[1];
1404  Collection<BlackboardAttribute> attributes = new ArrayList<>();
1405  attributes.add(new BlackboardAttribute(TSK_PATH, getDisplayName(), fileName));
1406  attributes.add(new BlackboardAttribute(TSK_COMMENT, getDisplayName(), comment));
1407  try {
1408  BlackboardArtifact bba = createArtifactWithAttributes(BlackboardArtifact.Type.TSK_RECENT_OBJECT, regFile, attributes);
1409  if (bba != null) {
1410  bbartifacts.add(bba);
1411  bba = createAssociatedArtifact(fileName, bba);
1412  if (bba != null) {
1413  bbartifacts.add(bba);
1414  bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba);
1415  if (bba != null) {
1416  bbartifacts.add(bba);
1417  }
1418  }
1419  }
1420  } catch (TskCoreException ex) {
1421  logger.log(Level.SEVERE, String.format("Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1422  }
1423  line = reader.readLine();
1424  }
1425  line = line.trim();
1426  }
1427  }
1428  if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1429  postArtifacts(bbartifacts);
1430  }
1431  }
1432 
1445  private void parseGenericMRUList(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException {
1446  List<BlackboardArtifact> bbartifacts = new ArrayList<>();
1447  String line = reader.readLine();
1448  while (!line.contains(SECTION_DIVIDER)) {
1449  line = reader.readLine();
1450  line = line.trim();
1451  if (line.contains("LastWrite")) {
1452  line = reader.readLine();
1453  // Columns are
1454  // FileX -> <file>
1455  while (!line.contains(SECTION_DIVIDER) && !line.isEmpty() && !line.contains("Applets")
1456  && !line.contains(("Recent File List"))) {
1457  // Split line on "> " which is the record delimiter between position and file
1458  String tokens[] = line.split("> ");
1459  if (tokens.length > 1) {
1460  String fileName = tokens[1];
1461  Collection<BlackboardAttribute> attributes = new ArrayList<>();
1462  attributes.add(new BlackboardAttribute(TSK_PATH, getDisplayName(), fileName));
1463  attributes.add(new BlackboardAttribute(TSK_COMMENT, getDisplayName(), comment));
1464  try {
1465  BlackboardArtifact bba = createArtifactWithAttributes(BlackboardArtifact.Type.TSK_RECENT_OBJECT, regFile, attributes);
1466  if (bba != null) {
1467  bbartifacts.add(bba);
1468  bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba);
1469  if (bba != null) {
1470  bbartifacts.add(bba);
1471  }
1472  }
1473  } catch (TskCoreException ex) {
1474  logger.log(Level.SEVERE, String.format("Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1475  }
1476  }
1477  line = reader.readLine();
1478  }
1479  line = line.trim();
1480  }
1481  }
1482  if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1483  postArtifacts(bbartifacts);
1484  }
1485  }
1486 
1499  private void parseWinRARMRUList(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException {
1500  List<BlackboardArtifact> bbartifacts = new ArrayList<>();
1501  String line = reader.readLine();
1502  while (!line.contains(SECTION_DIVIDER)) {
1503  line = reader.readLine();
1504  line = line.trim();
1505  if (line.contains("LastWrite")) {
1506  line = reader.readLine();
1507  // Columns are
1508  // FileX -> <Media file>
1509  if (!line.isEmpty()) {
1510  while (!line.contains(SECTION_DIVIDER)) {
1511  // Split line on "> " which is the record delimiter between position and file
1512  String tokens[] = line.split("> ");
1513  String fileName = tokens[1];
1514  Collection<BlackboardAttribute> attributes = new ArrayList<>();
1515  attributes.add(new BlackboardAttribute(TSK_PATH, getDisplayName(), fileName));
1516  attributes.add(new BlackboardAttribute(TSK_COMMENT, getDisplayName(), comment));
1517  try {
1518  BlackboardArtifact bba = createArtifactWithAttributes(BlackboardArtifact.Type.TSK_RECENT_OBJECT, regFile, attributes);
1519  bbartifacts.add(bba);
1520  bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba);
1521  if (bba != null) {
1522  bbartifacts.add(bba);
1523  }
1524  } catch (TskCoreException ex) {
1525  logger.log(Level.SEVERE, String.format("Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1526  }
1527  line = reader.readLine();
1528  }
1529  }
1530  line = line.trim();
1531  }
1532  }
1533  if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1534  postArtifacts(bbartifacts);
1535  }
1536  }
1537 
1550  private void parse7ZipMRU(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException {
1551  List<BlackboardArtifact> bbartifacts = new ArrayList<>();
1552  String line = reader.readLine();
1553  line = line.trim();
1554  if (!line.contains("PathHistory:")) {
1555  while (!line.contains("PathHistory:") && !line.isEmpty()) {
1556  // Columns are
1557  // <fileName>
1558  String fileName = line;
1559  Collection<BlackboardAttribute> attributes = new ArrayList<>();
1560  attributes.add(new BlackboardAttribute(TSK_PATH, getDisplayName(), fileName));
1561  attributes.add(new BlackboardAttribute(TSK_COMMENT, getDisplayName(), comment));
1562  try {
1563  BlackboardArtifact bba = createArtifactWithAttributes(BlackboardArtifact.Type.TSK_RECENT_OBJECT, regFile, attributes);
1564  bbartifacts.add(bba);
1565  bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba);
1566  if (bba != null) {
1567  bbartifacts.add(bba);
1568  }
1569 
1570  } catch (TskCoreException ex) {
1571  logger.log(Level.SEVERE, String.format("Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1572  }
1573  line = reader.readLine();
1574  line = line.trim();
1575  }
1576  }
1577  if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1578  postArtifacts(bbartifacts);
1579  }
1580  }
1581 
1594  private void parseOfficeDocs2010MRUList(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException {
1595  List<BlackboardArtifact> bbartifacts = new ArrayList<>();
1596  String line = reader.readLine();
1597  line = line.trim();
1598  // Reading to the SECTION DIVIDER to get next section of records to process. Dates appear to have
1599  // multiple spaces in them that makes it harder to parse so next section will be easier to parse
1600  while (!line.contains(SECTION_DIVIDER)) {
1601  line = reader.readLine();
1602  }
1603  line = reader.readLine();
1604  while (!line.contains(SECTION_DIVIDER)) {
1605  // record has the following format
1606  // 1294283922|REG|||OfficeDocs2010 - F:\Windows_time_Rules_xp.doc
1607  String tokens[] = line.split("\\|");
1608  Long docDate = Long.valueOf(tokens[0]);
1609  String fileNameTokens[] = tokens[4].split(" - ");
1610  String fileName = fileNameTokens[1];
1611  Collection<BlackboardAttribute> attributes = new ArrayList<>();
1612  attributes.add(new BlackboardAttribute(TSK_PATH, getDisplayName(), fileName));
1613  attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, getDisplayName(), docDate));
1614  attributes.add(new BlackboardAttribute(TSK_COMMENT, getDisplayName(), comment));
1615  try {
1616  BlackboardArtifact bba = createArtifactWithAttributes(BlackboardArtifact.Type.TSK_RECENT_OBJECT, regFile, attributes);
1617  bbartifacts.add(bba);
1618  bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba);
1619  if (bba != null) {
1620  bbartifacts.add(bba);
1621  }
1622  } catch (TskCoreException ex) {
1623  logger.log(Level.SEVERE, String.format("Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1624  }
1625  line = reader.readLine();
1626  line = line.trim();
1627  }
1628  if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1629  postArtifacts(bbartifacts);
1630  }
1631  }
1632 
1645  private void parseOfficeTrustRecords(AbstractFile regFile, BufferedReader reader, String comment) throws FileNotFoundException, IOException {
1646  String userProfile = regFile.getParentPath();
1647  userProfile = userProfile.substring(0, userProfile.length() - 1);
1648  List<BlackboardArtifact> bbartifacts = new ArrayList<>();
1649  SimpleDateFormat pluginDateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy", US);
1650  Long usedTime = Long.valueOf(0);
1651  String line = reader.readLine();
1652  while (!line.contains(SECTION_DIVIDER)) {
1653  line = reader.readLine();
1654  line = line.trim();
1655  usedTime = Long.valueOf(0);
1656  if (!line.contains("**") && !line.contains("----------") && !line.contains("LastWrite")
1657  && !line.contains(SECTION_DIVIDER) && !line.isEmpty() && !line.contains("TrustRecords")
1658  && !line.contains("VBAWarnings =")) {
1659  // Columns are
1660  // Date : <File Name>/<Website>
1661  // Split line on " : " which is the record delimiter between position and file
1662  String fileName = null;
1663  String tokens[] = line.split(" : ");
1664  fileName = tokens[1];
1665  fileName = fileName.replace("%USERPROFILE%", userProfile);
1666  // Time in the format of Wed May 31 14:33:03 2017 Z
1667  try {
1668  String fileUsedTime = tokens[0].replaceAll(" Z", "");
1669  Date usedDate = pluginDateFormat.parse(fileUsedTime);
1670  usedTime = usedDate.getTime() / 1000;
1671  } catch (ParseException ex) {
1672  // catching error and displaying date that could not be parsed
1673  // we set the timestamp to 0 and continue on processing
1674  logger.log(Level.WARNING, String.format("Failed to parse date/time %s for TrustRecords artifact.", tokens[0]), ex); //NON-NLS
1675  }
1676  Collection<BlackboardAttribute> attributes = new ArrayList<>();
1677  attributes.add(new BlackboardAttribute(TSK_PATH, getDisplayName(), fileName));
1678  attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, getDisplayName(), usedTime));
1679  attributes.add(new BlackboardAttribute(TSK_COMMENT, getDisplayName(), comment));
1680  try {
1681  BlackboardArtifact bba = createArtifactWithAttributes(BlackboardArtifact.Type.TSK_RECENT_OBJECT, regFile, attributes);
1682  bbartifacts.add(bba);
1683  bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba);
1684  if (bba != null) {
1685  bbartifacts.add(bba);
1686  }
1687  } catch (TskCoreException ex) {
1688  logger.log(Level.SEVERE, String.format("Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1689  }
1690  line = line.trim();
1691  }
1692  }
1693  if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1694  postArtifacts(bbartifacts);
1695  }
1696  }
1697 
1708  private BlackboardArtifact createAssociatedArtifact(String filePathName, BlackboardArtifact bba) {
1709  String fileName = FilenameUtils.getName(filePathName);
1710  String filePath = FilenameUtils.getPath(filePathName);
1711  List<AbstractFile> sourceFiles;
1712  try {
1713  sourceFiles = currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, fileName, filePath);
1714  if (!sourceFiles.isEmpty()) {
1715  return createAssociatedArtifact(sourceFiles.get(0), bba);
1716  }
1717  } catch (TskCoreException ex) {
1718  // only catching the error and displaying the message as the file may not exist on the
1719  // system anymore
1720  logger.log(Level.WARNING, String.format("Error finding actual file %s. file may not exist", filePathName)); //NON-NLS
1721  }
1722 
1723  return null;
1724  }
1725 
1736  private Map<String, String> makeUserNameMap(Content dataSource) throws TskCoreException {
1737  Map<String, String> map = new HashMap<>();
1738 
1739  for (OsAccount account : tskCase.getOsAccountManager().getOsAccounts(((DataSource) dataSource).getHost())) {
1740  Optional<String> userName = account.getLoginName();
1741  String address = account.getAddr().orElse("");
1742  if (!address.isEmpty()) {
1743  map.put(address, userName.isPresent() ? userName.get() : "");
1744  }
1745  }
1746 
1747  return map;
1748  }
1749 
1769  private String stripRelativeIdentifierFromSID(String osAccountSID) {
1770  if (osAccountSID.split("-").length > 4) {
1771  int index = osAccountSID.lastIndexOf('-');
1772  return index > 1 ? osAccountSID.substring(0, index) : "";
1773  }
1774  return "";
1775  }
1776 
1777  private final List<String> machineSIDs = new ArrayList<>();
1778 
1784  private Map<String, String> getUserNameMap() {
1785  if (userNameMap == null) {
1786  // Get a mapping of user sids to user names and save globally so it can be used for other areas
1787  // of the registry, ie: BAM key
1788  try {
1789  userNameMap = makeUserNameMap(dataSource);
1790  } catch (TskCoreException ex) {
1791  logger.log(Level.WARNING, "Unable to create OS Account user name map", ex);
1792  // This is not the end of the world we will just continue without
1793  // user names
1794  userNameMap = new HashMap<>();
1795  }
1796  }
1797 
1798  return userNameMap;
1799  }
1800 
1811  private BlackboardAttribute getAttributeForArtifact(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE type) throws TskCoreException {
1812  return artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.fromID(type.getTypeID())));
1813  }
1814 
1823  void createShellBagArtifacts(AbstractFile regFile, List<ShellBag> shellbags) throws TskCoreException {
1824  List<BlackboardArtifact> artifacts = new ArrayList<>();
1825  try {
1826  for (ShellBag bag : shellbags) {
1827  Collection<BlackboardAttribute> attributes = new ArrayList<>();
1828  attributes.add(new BlackboardAttribute(TSK_PATH, getDisplayName(), bag.getResource()));
1829  attributes.add(new BlackboardAttribute(getKeyAttribute(), getDisplayName(), bag.getKey()));
1830 
1831  long time;
1832  time = bag.getLastWrite();
1833  if (time != 0) {
1834  attributes.add(new BlackboardAttribute(getLastWriteAttribute(), getDisplayName(), time));
1835  }
1836 
1837  time = bag.getModified();
1838  if (time != 0) {
1839  attributes.add(new BlackboardAttribute(TSK_DATETIME_MODIFIED, getDisplayName(), time));
1840  }
1841 
1842  time = bag.getCreated();
1843  if (time != 0) {
1844  attributes.add(new BlackboardAttribute(TSK_DATETIME_CREATED, getDisplayName(), time));
1845  }
1846 
1847  time = bag.getAccessed();
1848  if (time != 0) {
1849  attributes.add(new BlackboardAttribute(TSK_DATETIME_ACCESSED, getDisplayName(), time));
1850  }
1851 
1852  BlackboardArtifact artifact = createArtifactWithAttributes(getShellBagArtifact(), regFile, attributes);
1853  artifacts.add(artifact);
1854  }
1855  } finally {
1856  if (!context.dataSourceIngestIsCancelled()) {
1857  postArtifacts(artifacts);
1858  }
1859  }
1860  }
1861 
1870  private BlackboardArtifact.Type getShellBagArtifact() throws TskCoreException {
1871  if (shellBagArtifactType == null) {
1872  try {
1873  shellBagArtifactType = tskCase.getBlackboard().getOrAddArtifactType(SHELLBAG_ARTIFACT_NAME, Bundle.Shellbag_Artifact_Display_Name());
1874  } catch (BlackboardException ex) {
1875  throw new TskCoreException(String.format("Failed to get shell bag artifact type", SHELLBAG_ARTIFACT_NAME), ex);
1876  }
1877  }
1878 
1879  return shellBagArtifactType;
1880  }
1881 
1890  private BlackboardAttribute.Type getLastWriteAttribute() throws TskCoreException {
1891  if (shellBagLastWriteAttributeType == null) {
1892  try {
1893  shellBagLastWriteAttributeType = tskCase.getBlackboard().getOrAddAttributeType(SHELLBAG_ATTRIBUTE_LAST_WRITE,
1894  BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME,
1895  Bundle.Shellbag_Last_Write_Attribute_Display_Name());
1896  } catch (BlackboardException ex) {
1897  // Attribute already exists get it from the case
1898  throw new TskCoreException(String.format("Failed to get custom attribute %s", SHELLBAG_ATTRIBUTE_LAST_WRITE), ex);
1899  }
1900  }
1901  return shellBagLastWriteAttributeType;
1902  }
1903 
1912  private BlackboardAttribute.Type getKeyAttribute() throws TskCoreException {
1913  if (shellBagKeyAttributeType == null) {
1914  try {
1915  shellBagKeyAttributeType = tskCase.getBlackboard().getOrAddAttributeType(SHELLBAG_ATTRIBUTE_KEY,
1916  BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING,
1917  Bundle.Shellbag_Key_Attribute_Display_Name());
1918  } catch (BlackboardException ex) {
1919  throw new TskCoreException(String.format("Failed to get key attribute %s", SHELLBAG_ATTRIBUTE_KEY), ex);
1920  }
1921  }
1922  return shellBagKeyAttributeType;
1923  }
1924 
1934  Map<String, List<String>> readGroups(BufferedReader bufferedReader) throws IOException {
1935  Map<String, List<String>> groupMap = new HashMap<>();
1936 
1937  String line = bufferedReader.readLine();
1938 
1939  int userCount = 0;
1940  String groupName = null;
1941 
1942  while (line != null && !line.contains(SECTION_DIVIDER)) {
1943 
1944  if (line.contains("Group Name")) {
1945  String value = line.replaceAll("Group Name\\s*?:", "").trim();
1946  groupName = (value.replaceAll("\\[\\d*?\\]", "")).trim();
1947  int startIndex = value.indexOf(" [") + 1;
1948  int endIndex = value.indexOf(']');
1949 
1950  if (startIndex != -1 && endIndex != -1) {
1951  String countStr = value.substring(startIndex + 1, endIndex);
1952  userCount = Integer.parseInt(countStr);
1953  }
1954  } else if (line.matches("Users\\s*?:")) {
1955  for (int i = 0; i < userCount; i++) {
1956  line = bufferedReader.readLine();
1957  if (line != null) {
1958  String sid = line.trim();
1959  List<String> groupList = groupMap.get(sid);
1960  if (groupList == null) {
1961  groupList = new ArrayList<>();
1962  groupMap.put(sid, groupList);
1963  }
1964  groupList.add(groupName);
1965  }
1966  }
1967  groupName = null;
1968  }
1969  line = bufferedReader.readLine();
1970  }
1971  return groupMap;
1972  }
1973 
1982  private Map.Entry<String, String> getSAMKeyValue(String line) {
1983  int index = line.indexOf(':');
1984  Map.Entry<String, String> returnValue = null;
1985  String key = null;
1986  String value = null;
1987 
1988  if (index != -1) {
1989  key = line.substring(0, index).trim();
1990  if (index + 1 < line.length()) {
1991  value = line.substring(index + 1).trim();
1992  } else {
1993  value = "";
1994  }
1995 
1996  } else if (line.contains("-->")) {
1997  key = line.replace("-->", "").trim();
1998  value = "true";
1999  }
2000 
2001  if (key != null) {
2002  returnValue = new AbstractMap.SimpleEntry<>(key, value);
2003  }
2004 
2005  return returnValue;
2006  }
2007 
2008  @Override
2009  public void process(Content dataSource, DataSourceIngestModuleProgress progressBar) {
2010  this.dataSource = dataSource;
2011 
2012  progressBar.progress(Bundle.Progress_Message_Analyze_Registry());
2013  analyzeRegistryFiles(context.getJobId());
2014 
2015  }
2016 
2020  private class RegOutputFiles {
2021 
2022  public String autopsyPlugins = "";
2023  public String fullPlugins = "";
2024  }
2025 
2038  private void createOrUpdateOsAccount(AbstractFile file, String sid, String userName, String homeDir, String domainName, OsAccountRealm.RealmScope realmScope) throws TskCoreException, TskDataException, NotUserSIDException {
2039  OsAccountManager accountMgr = tskCase.getOsAccountManager();
2040  HostManager hostMrg = tskCase.getHostManager();
2041  Host host = hostMrg.getHostByDataSource((DataSource) dataSource);
2042 
2043  Optional<OsAccount> optional = accountMgr.getWindowsOsAccount(sid, null, null, host);
2044  OsAccount osAccount;
2045  if (!optional.isPresent()) {
2046  osAccount = accountMgr.newWindowsOsAccount(sid, userName != null && userName.isEmpty() ? null : userName, domainName, host, realmScope);
2047  accountMgr.newOsAccountInstance(osAccount, (DataSource) dataSource, OsAccountInstance.OsAccountInstanceType.LAUNCHED);
2048  } else {
2049  osAccount = optional.get();
2050  addAccountInstance(accountMgr, osAccount, (DataSource) dataSource);
2051  if (userName != null && !userName.isEmpty()) {
2052  OsAccountUpdateResult updateResult = accountMgr.updateCoreWindowsOsAccountAttributes(osAccount, null, userName, (domainName == null || domainName.isEmpty()) ? null : domainName, host);
2053  osAccount = updateResult.getUpdatedAccount().orElse(osAccount);
2054  }
2055  }
2056 
2057  if (homeDir != null && !homeDir.isEmpty()) {
2058  List<OsAccountAttribute> attributes = new ArrayList<>();
2059  String dir = homeDir.replaceFirst("^(%\\w*%)", "");
2060  dir = dir.replace("\\", "/");
2061  attributes.add(createOsAccountAttribute(TSK_HOME_DIR, dir, osAccount, host, file));
2062  accountMgr.addExtendedOsAccountAttributes(osAccount, attributes);
2063  }
2064 
2065  }
2066 
2073  private void addEmailAccount(AbstractFile regFile, String emailAddress) {
2074  try {
2075  currentCase.getSleuthkitCase()
2076  .getCommunicationsManager()
2077  .createAccountFileInstance(Account.Type.EMAIL,
2078  emailAddress, getRAModuleName(), regFile);
2079  } catch (TskCoreException ex) {
2080  logger.log(Level.SEVERE,
2081  String.format("Error adding email account with value "
2082  + "%s, to the case database for file %s [objId=%d]",
2083  emailAddress, regFile.getName(), regFile.getId()), ex);
2084  }
2085  }
2086 
2095  private Long parseRegRipTime(String value) {
2096  try {
2097  return REG_RIPPER_TIME_FORMAT.parse(value).getTime() / MS_IN_SEC;
2098  } catch (ParseException ex) {
2099  logger.log(Level.SEVERE, String.format("Failed to parse reg rip time: %s", value));
2100  }
2101  return null;
2102  }
2103 
2115  private void updateOsAccount(OsAccount osAccount, Map<String, String> userInfo, List<String> groupList, AbstractFile regFile) throws TskDataException, TskCoreException, NotUserSIDException {
2116  Host host = ((DataSource) dataSource).getHost();
2117 
2118  SimpleDateFormat regRipperTimeFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy 'Z'", US);
2119  regRipperTimeFormat.setTimeZone(getTimeZone("GMT"));
2120 
2121  List<OsAccountAttribute> attributes = new ArrayList<>();
2122 
2123  Long creationTime = null;
2124 
2125  String value = userInfo.get(ACCOUNT_CREATED_KEY);
2126  if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
2127  creationTime = parseRegRipTime(value);
2128  }
2129 
2130  value = userInfo.get(LAST_LOGIN_KEY);
2131  if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
2132  Long time = parseRegRipTime(value);
2133  if (time != null) {
2134  attributes.add(createOsAccountAttribute(TSK_DATETIME_ACCESSED,
2135  parseRegRipTime(value),
2136  osAccount, host, regFile));
2137  }
2138  }
2139 
2140  String loginName = null;
2141  value = userInfo.get(USERNAME_KEY);
2142  if (value != null && !value.isEmpty()) {
2143  loginName = value;
2144  }
2145 
2146  value = userInfo.get(LOGIN_COUNT_KEY);
2147  if (value != null && !value.isEmpty()) {
2148  attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
2149  Integer.parseInt(value),
2150  osAccount, host, regFile));
2151  }
2152 
2153  // From regripper the possible values for this key are
2154  // "Default Admin User", "Custom Limited Acct"
2155  // and "Default Guest Acct"
2156  value = userInfo.get(ACCOUNT_TYPE_KEY);
2157  if (value != null && !value.isEmpty() && value.toLowerCase().contains("admin")) {
2158  attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_IS_ADMIN,
2159  1, osAccount, host, regFile));
2160  }
2161 
2162  value = userInfo.get(USER_COMMENT_KEY);
2163  if (value != null && !value.isEmpty()) {
2164  attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_DESCRIPTION,
2165  value, osAccount, host, regFile));
2166  }
2167 
2168  value = userInfo.get(INTERNET_NAME_KEY);
2169  if (value != null && !value.isEmpty()) {
2170  addEmailAccount(regFile, value);
2171 
2172  attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_EMAIL,
2173  value, osAccount, host, regFile));
2174  }
2175 
2176  // FULL_NAME_KEY and NAME_KEY appear to be the same value.
2177  String fullName = null;
2178  value = userInfo.get(FULL_NAME_KEY);
2179  if (value != null && !value.isEmpty()) {
2180  fullName = value;
2181  } else {
2182  value = userInfo.get(NAME_KEY);
2183  if (value != null && !value.isEmpty()) {
2184  fullName = value;
2185  }
2186  }
2187 
2188  value = userInfo.get(PWD_RESET_KEY);
2189  if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
2190  Long time = parseRegRipTime(value);
2191  if (time != null) {
2192  attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_PASSWORD_RESET,
2193  time, osAccount, host, regFile));
2194  }
2195  }
2196 
2197  value = userInfo.get(PASSWORD_HINT);
2198  if (value != null && !value.isEmpty()) {
2199  attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_HINT,
2200  value, osAccount, host, regFile));
2201  }
2202 
2203  value = userInfo.get(PWD_FAILE_KEY);
2204  if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
2205  Long time = parseRegRipTime(value);
2206  if (time != null) {
2207  attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_PASSWORD_FAIL,
2208  time, osAccount, host, regFile));
2209  }
2210  }
2211 
2212  String settingString = getSettingsFromMap(PASSWORD_SETTINGS_FLAGS, userInfo);
2213  if (!settingString.isEmpty()) {
2214  attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_SETTINGS,
2215  settingString, osAccount, host, regFile));
2216  }
2217 
2218  settingString = getSettingsFromMap(ACCOUNT_SETTINGS_FLAGS, userInfo);
2219  if (!settingString.isEmpty()) {
2220  attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_ACCOUNT_SETTINGS,
2221  settingString, osAccount, host, regFile));
2222  }
2223 
2224  settingString = getSettingsFromMap(ACCOUNT_TYPE_FLAGS, userInfo);
2225  if (!settingString.isEmpty()) {
2226  attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_FLAG,
2227  settingString, osAccount, host, regFile));
2228  }
2229 
2230  if (groupList != null && groupList.isEmpty()) {
2231  String groups = groupList.stream()
2232  .map(String::valueOf)
2233  .collect(Collectors.joining(", "));
2234 
2235  attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_GROUPS,
2236  groups, osAccount, host, regFile));
2237  }
2238 
2239  // add the attributes to account.
2240  OsAccountManager accountMgr = tskCase.getOsAccountManager();
2241  accountMgr.addExtendedOsAccountAttributes(osAccount, attributes);
2242 
2243  // update the loginname
2244  accountMgr.updateCoreWindowsOsAccountAttributes(osAccount, null, loginName, null, host);
2245 
2246  // update other standard attributes - fullname, creationdate
2247  accountMgr.updateStandardOsAccountAttributes(osAccount, fullName, null, null, creationTime);
2248 
2249  }
2250 
2259  private String getSettingsFromMap(String[] keys, Map<String, String> map) {
2260  List<String> settingsList = new ArrayList<>();
2261  for (String setting : keys) {
2262  if (map.containsKey(setting)) {
2263  settingsList.add(setting);
2264  }
2265  }
2266 
2267  if (!settingsList.isEmpty()) {
2268  return settingsList.stream()
2269  .map(String::valueOf)
2270  .collect(Collectors.joining(", "));
2271  }
2272 
2273  return "";
2274  }
2275 
2287  private OsAccountAttribute createOsAccountAttribute(BlackboardAttribute.ATTRIBUTE_TYPE type, String value, OsAccount osAccount, Host host, AbstractFile file) {
2288  return osAccount.new OsAccountAttribute(new BlackboardAttribute.Type(type), value, osAccount, host, file);
2289  }
2290 
2302  private OsAccountAttribute createOsAccountAttribute(BlackboardAttribute.ATTRIBUTE_TYPE type, Long value, OsAccount osAccount, Host host, AbstractFile file) {
2303  return osAccount.new OsAccountAttribute(new BlackboardAttribute.Type(type), value, osAccount, host, file);
2304  }
2305 
2317  private OsAccountAttribute createOsAccountAttribute(BlackboardAttribute.ATTRIBUTE_TYPE type, Integer value, OsAccount osAccount, Host host, AbstractFile file) {
2318  return osAccount.new OsAccountAttribute(new BlackboardAttribute.Type(type), value, osAccount, host, file);
2319  }
2320 
2331  private void addAccountInstance(OsAccountManager accountMgr, OsAccount osAccount, DataSource dataSource) throws TskCoreException {
2332  accountMgr.newOsAccountInstance(osAccount, dataSource, OsAccountInstance.OsAccountInstanceType.LAUNCHED);
2333  }
2334 
2340  private void addSIDToSAMList(String sid) {
2341  String relativeID = stripRelativeIdentifierFromSID(sid);
2342  if (!relativeID.isEmpty() && !samDomainIDsList.contains(relativeID)) {
2343  samDomainIDsList.add(relativeID);
2344  }
2345  }
2346 
2355  private boolean isDomainIdInSAMList(String osAccountSID) {
2356  String relativeID = stripRelativeIdentifierFromSID(osAccountSID);
2357  return samDomainIDsList.contains(relativeID);
2358  }
2359 
2360 }

Copyright © 2012-2021 Basis Technology. Generated on: Tue Feb 22 2022
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.