23 package org.sleuthkit.autopsy.recentactivity;
25 import java.io.BufferedReader;
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;
67 import java.util.Scanner;
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;
81 import org.
sleuthkit.datamodel.Blackboard.BlackboardException;
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;
99 import org.
sleuthkit.datamodel.OsAccount.OsAccountAttribute;
102 import org.
sleuthkit.datamodel.OsAccountManager.NotUserSIDException;
103 import org.
sleuthkit.datamodel.OsAccountManager.OsAccountUpdateResult;
105 import org.
sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
117 "RegRipperNotFound=Autopsy RegRipper executable not found.",
118 "RegRipperFullNotFound=Full version RegRipper executable not found.",
119 "Progress_Message_Analyze_Registry=Analyzing Registry Files",
120 "Shellbag_Artifact_Display_Name=Shell Bags",
121 "Shellbag_Key_Attribute_Display_Name=Key",
122 "Shellbag_Last_Write_Attribute_Display_Name=Last Write",
123 "Recently_Used_Artifacts_Office_Trustrecords=Stored in TrustRecords because Office security exception was granted",
124 "Recently_Used_Artifacts_ArcHistory=Recently opened by 7Zip",
125 "Recently_Used_Artifacts_Applets=Recently opened according to Applets registry key",
126 "Recently_Used_Artifacts_Mmc=Recently opened according to Windows Management Console MRU",
127 "Recently_Used_Artifacts_Winrar=Recently opened according to WinRAR MRU",
128 "Recently_Used_Artifacts_Officedocs=Recently opened according to Office MRU",
129 "Recently_Used_Artifacts_Adobe=Recently opened according to Adobe MRU",
130 "Recently_Used_Artifacts_Mediaplayer=Recently opened according to Media Player MRU",
131 "Registry_System_Bam=Recently Executed according to Background Activity Moderator (BAM)"
133 class ExtractRegistry extends Extract {
135 private static final String USERNAME_KEY =
"Username";
136 private static final String SID_KEY =
"SID";
137 private static final String RID_KEY =
"RID";
138 private static final String ACCOUNT_CREATED_KEY =
"Account Created";
139 private static final String LAST_LOGIN_KEY =
"Last Login Date";
140 private static final String LOGIN_COUNT_KEY =
"Login Count";
141 private static final String FULL_NAME_KEY =
"Full Name";
142 private static final String USER_COMMENT_KEY =
"User Comment";
143 private static final String ACCOUNT_TYPE_KEY =
"Account Type";
144 private static final String NAME_KEY =
"Name";
145 private static final String PWD_RESET_KEY =
"Pwd Rest Date";
146 private static final String PWD_FAILE_KEY =
"Pwd Fail Date";
147 private static final String INTERNET_NAME_KEY =
"InternetName";
148 private static final String PWD_DOES_NOT_EXPIRE_KEY =
"Password does not expire";
149 private static final String ACCOUNT_DISABLED_KEY =
"Account Disabled";
150 private static final String PWD_NOT_REQUIRED_KEY =
"Password not required";
151 private static final String NORMAL_ACCOUNT_KEY =
"Normal user account";
152 private static final String HOME_DIRECTORY_REQUIRED_KEY =
"Home directory required";
153 private static final String TEMPORARY_DUPLICATE_ACCOUNT =
"Temporary duplicate account";
154 private static final String MNS_LOGON_ACCOUNT_KEY =
"MNS logon user account";
155 private static final String INTERDOMAIN_TRUST_ACCOUNT_KEY =
"Interdomain trust account";
156 private static final String WORKSTATION_TRUST_ACCOUNT =
"Workstation trust account";
157 private static final String SERVER_TRUST_ACCOUNT =
"Server trust account";
158 private static final String ACCOUNT_AUTO_LOCKED =
"Account auto locked";
159 private static final String PASSWORD_HINT =
"Password Hint";
161 private static final String[] PASSWORD_SETTINGS_FLAGS = {PWD_DOES_NOT_EXPIRE_KEY, PWD_NOT_REQUIRED_KEY};
162 private static final String[] ACCOUNT_SETTINGS_FLAGS = {ACCOUNT_AUTO_LOCKED, HOME_DIRECTORY_REQUIRED_KEY, ACCOUNT_DISABLED_KEY};
163 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};
165 final private static UsbDeviceIdMapper USB_MAPPER =
new UsbDeviceIdMapper();
166 final private static String RIP_EXE =
"rip.exe";
167 final private static String RIP_PL =
"rip.pl";
168 final private static String RIP_PL_INCLUDE_FLAG =
"-I";
169 final private static int MS_IN_SEC = 1000;
170 final private static String NEVER_DATE =
"Never";
171 final private static String SECTION_DIVIDER =
"-------------------------";
172 final private static Logger logger = Logger.getLogger(ExtractRegistry.class.getName());
173 private final List<String> rrCmd =
new ArrayList<>();
174 private final List<String> rrFullCmd =
new ArrayList<>();
175 private final Path rrHome;
176 private final Path rrFullHome;
177 private Content dataSource;
178 private IngestJobContext context;
179 private Map<String, String> userNameMap;
181 private String compName =
"";
182 private String domainName =
"";
184 private static final String SHELLBAG_ARTIFACT_NAME =
"RA_SHELL_BAG";
185 private static final String SHELLBAG_ATTRIBUTE_LAST_WRITE =
"RA_SHELL_BAG_LAST_WRITE";
186 private static final String SHELLBAG_ATTRIBUTE_KEY =
"RA_SHELL_BAG_KEY";
188 private static final SimpleDateFormat REG_RIPPER_TIME_FORMAT =
new SimpleDateFormat(
"EEE MMM dd HH:mm:ss yyyy 'Z'", US);
190 private BlackboardArtifact.Type shellBagArtifactType = null;
191 private BlackboardAttribute.Type shellBagKeyAttributeType = null;
192 private BlackboardAttribute.Type shellBagLastWriteAttributeType = null;
195 REG_RIPPER_TIME_FORMAT.setTimeZone(getTimeZone(
"GMT"));
198 ExtractRegistry() throws IngestModuleException {
199 super(NbBundle.getMessage(ExtractIE.class,
"ExtractRegistry.moduleName.text"));
201 final File rrRoot = InstalledFileLocator.getDefault().locate(
"rr", ExtractRegistry.class.getPackage().getName(),
false);
202 if (rrRoot == null) {
203 throw new IngestModuleException(Bundle.RegRipperNotFound());
206 final File rrFullRoot = InstalledFileLocator.getDefault().locate(
"rr-full", ExtractRegistry.class.getPackage().getName(),
false);
207 if (rrFullRoot == null) {
208 throw new IngestModuleException(Bundle.RegRipperFullNotFound());
211 String executableToRun = RIP_EXE;
212 if (!PlatformUtil.isWindowsOS()) {
213 executableToRun = RIP_PL;
215 rrHome = rrRoot.toPath();
216 String rrPath = rrHome.resolve(executableToRun).toString();
217 rrFullHome = rrFullRoot.toPath();
219 if (!(
new File(rrPath).exists())) {
220 throw new IngestModuleException(Bundle.RegRipperNotFound());
222 String rrFullPath = rrFullHome.resolve(executableToRun).toString();
223 if (!(
new File(rrFullPath).exists())) {
224 throw new IngestModuleException(Bundle.RegRipperFullNotFound());
226 if (PlatformUtil.isWindowsOS()) {
228 rrFullCmd.add(rrFullPath);
231 File usrBin =
new File(
"/usr/bin/perl");
232 File usrLocalBin =
new File(
"/usr/local/bin/perl");
233 if (usrBin.canExecute() && usrBin.exists() && !usrBin.isDirectory()) {
234 perl =
"/usr/bin/perl";
235 }
else if (usrLocalBin.canExecute() && usrLocalBin.exists() && !usrLocalBin.isDirectory()) {
236 perl =
"/usr/local/bin/perl";
238 throw new IngestModuleException(
"perl not found in your system");
241 rrCmd.add(RIP_PL_INCLUDE_FLAG);
242 rrCmd.add(rrHome.toString());
245 rrFullCmd.add(RIP_PL_INCLUDE_FLAG);
246 rrFullCmd.add(rrFullHome.toString());
247 rrFullCmd.add(rrFullPath);
254 private List<AbstractFile> findRegistryFiles() {
255 List<AbstractFile> allRegistryFiles =
new ArrayList<>();
260 allRegistryFiles.addAll(fileManager.findFiles(dataSource,
"sam",
"/system32/config"));
261 }
catch (TskCoreException ex) {
262 String msg = NbBundle.getMessage(this.getClass(),
263 "ExtractRegistry.findRegFiles.errMsg.errReadingFile",
"sam");
264 logger.log(Level.WARNING, msg, ex);
265 this.addErrorMessage(this.getName() +
": " + msg);
270 allRegistryFiles.addAll(fileManager.findFiles(dataSource,
"ntuser.dat"));
271 }
catch (TskCoreException ex) {
272 logger.log(Level.WARNING,
"Error fetching 'ntuser.dat' file.");
277 allRegistryFiles.addAll(fileManager.findFiles(dataSource,
"usrclass.dat"));
278 }
catch (TskCoreException ex) {
279 logger.log(Level.WARNING, String.format(
"Error finding 'usrclass.dat' files."), ex);
283 String[] regFileNames =
new String[]{
"system",
"software",
"security"};
284 for (String regFileName : regFileNames) {
286 allRegistryFiles.addAll(fileManager.findFiles(dataSource, regFileName,
"/system32/config"));
287 }
catch (TskCoreException ex) {
288 String msg = NbBundle.getMessage(this.getClass(),
289 "ExtractRegistry.findRegFiles.errMsg.errReadingFile", regFileName);
290 logger.log(Level.WARNING, msg, ex);
291 this.addErrorMessage(this.getName() +
": " + msg);
294 return allRegistryFiles;
302 private void analyzeRegistryFiles(
long ingestJobId) {
303 List<AbstractFile> allRegistryFiles = findRegistryFiles();
306 FileWriter logFile = null;
308 logFile =
new FileWriter(RAImageIngestModule.getRAOutputPath(currentCase,
"reg", ingestJobId) + File.separator +
"regripper-info.txt");
309 }
catch (IOException ex) {
310 logger.log(Level.SEVERE, null, ex);
313 for (AbstractFile regFile : allRegistryFiles) {
314 if (context.dataSourceIngestIsCancelled()) {
318 String regFileName = regFile.getName();
319 long regFileId = regFile.getId();
320 String regFileNameLocal = RAImageIngestModule.getRATempPath(currentCase,
"reg", ingestJobId) + File.separator + regFileName;
321 String outputPathBase = RAImageIngestModule.getRAOutputPath(currentCase,
"reg", ingestJobId) + File.separator + regFileName +
"-regripper-" + Long.toString(regFileId);
322 File regFileNameLocalFile =
new File(regFileNameLocal);
324 ContentUtils.writeToFile(regFile, regFileNameLocalFile, context::dataSourceIngestIsCancelled);
325 }
catch (ReadContentInputStreamException ex) {
326 logger.log(Level.WARNING, String.format(
"Error reading registry file '%s' (id=%d).",
327 regFile.getName(), regFileId), ex);
328 this.addErrorMessage(
329 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
330 this.getName(), regFileName));
332 }
catch (IOException ex) {
333 logger.log(Level.SEVERE, String.format(
"Error writing temp registry file '%s' for registry file '%s' (id=%d).",
334 regFileNameLocal, regFile.getName(), regFileId), ex);
335 this.addErrorMessage(
336 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.errMsg.errWritingTemp",
337 this.getName(), regFileName));
341 if (context.dataSourceIngestIsCancelled()) {
346 if (logFile != null) {
347 logFile.write(Long.toString(regFileId) +
"\t" + regFile.getUniquePath() +
"\n");
349 }
catch (TskCoreException | IOException ex) {
350 logger.log(Level.SEVERE, null, ex);
353 logger.log(Level.INFO,
"{0}- Now getting registry information from {1}",
new Object[]{getName(), regFileNameLocal});
354 RegOutputFiles regOutputFiles = ripRegistryFile(regFileNameLocal, outputPathBase);
355 if (context.dataSourceIngestIsCancelled()) {
360 if (regOutputFiles.autopsyPlugins.isEmpty() ==
false && parseAutopsyPluginOutput(regOutputFiles.autopsyPlugins, regFile) ==
false) {
361 this.addErrorMessage(
362 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.failedParsingResults",
363 this.getName(), regFileName));
366 if (context.dataSourceIngestIsCancelled()) {
371 if (!regOutputFiles.fullPlugins.isEmpty()) {
373 if (regFileNameLocal.toLowerCase().contains(
"sam") && parseSamPluginOutput(regOutputFiles.fullPlugins, regFile, ingestJobId) ==
false) {
374 this.addErrorMessage(
375 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.failedParsingResults",
376 this.getName(), regFileName));
377 }
else if (regFileNameLocal.toLowerCase().contains(
"ntuser") || regFileNameLocal.toLowerCase().contains(
"usrclass")) {
379 List<ShellBag> shellbags = ShellBagParser.parseShellbagOutput(regOutputFiles.fullPlugins);
380 createShellBagArtifacts(regFile, shellbags);
381 createRecentlyUsedArtifacts(regOutputFiles.fullPlugins, regFile);
382 }
catch (IOException | TskCoreException ex) {
383 logger.log(Level.WARNING, String.format(
"Unable to get shell bags from file %s", regOutputFiles.fullPlugins), ex);
385 }
else if (regFileNameLocal.toLowerCase().contains(
"system") && parseSystemPluginOutput(regOutputFiles.fullPlugins, regFile) ==
false) {
386 this.addErrorMessage(
387 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.analyzeRegFiles.failedParsingResults",
388 this.getName(), regFileName));
391 if (context.dataSourceIngestIsCancelled()) {
396 Report report = currentCase.addReport(regOutputFiles.fullPlugins,
397 NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.parentModuleName.noSpace"),
398 "RegRipper " + regFile.getUniquePath(), regFile);
401 KeywordSearchService searchService = Lookup.getDefault().lookup(KeywordSearchService.class);
402 if (null == searchService) {
403 logger.log(Level.WARNING,
"Keyword search service not found. Report will not be indexed");
405 searchService.index(report);
408 }
catch (TskCoreException e) {
409 this.addErrorMessage(
"Error adding regripper output as Autopsy report: " + e.getLocalizedMessage());
413 regFileNameLocalFile.delete();
417 if (logFile != null) {
420 }
catch (IOException ex) {
421 logger.log(Level.SEVERE, null, ex);
432 private RegOutputFiles ripRegistryFile(String regFilePath, String outFilePathBase) {
433 String autopsyType =
"";
436 RegOutputFiles regOutputFiles =
new RegOutputFiles();
438 if (regFilePath.toLowerCase().contains(
"system")) {
439 autopsyType =
"autopsysystem";
441 }
else if (regFilePath.toLowerCase().contains(
"software")) {
442 autopsyType =
"autopsysoftware";
443 fullType =
"software";
444 }
else if (regFilePath.toLowerCase().contains(
"ntuser")) {
445 autopsyType =
"autopsyntuser";
447 }
else if (regFilePath.toLowerCase().contains(
"sam")) {
450 }
else if (regFilePath.toLowerCase().contains(
"security")) {
451 fullType =
"security";
452 }
else if (regFilePath.toLowerCase().contains(
"usrclass")) {
453 fullType =
"usrclass";
455 return regOutputFiles;
459 if (!autopsyType.isEmpty()) {
460 regOutputFiles.autopsyPlugins = outFilePathBase +
"-autopsy.txt";
461 String errFilePath = outFilePathBase +
"-autopsy.err.txt";
462 logger.log(Level.INFO,
"Writing RegRipper results to: {0}", regOutputFiles.autopsyPlugins);
463 executeRegRipper(rrCmd, rrHome, regFilePath, autopsyType, regOutputFiles.autopsyPlugins, errFilePath);
465 if (context.dataSourceIngestIsCancelled()) {
466 return regOutputFiles;
470 if (!fullType.isEmpty()) {
471 regOutputFiles.fullPlugins = outFilePathBase +
"-full.txt";
472 String errFilePath = outFilePathBase +
"-full.err.txt";
473 logger.log(Level.INFO,
"Writing Full RegRipper results to: {0}", regOutputFiles.fullPlugins);
474 executeRegRipper(rrFullCmd, rrFullHome, regFilePath, fullType, regOutputFiles.fullPlugins, errFilePath);
476 scanErrorLogs(errFilePath);
477 }
catch (IOException ex) {
478 logger.log(Level.SEVERE, String.format(
"Unable to run RegRipper on %s", regFilePath), ex);
479 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName(), regFilePath));
482 return regOutputFiles;
485 private void scanErrorLogs(String errFilePath)
throws IOException {
486 File regfile =
new File(errFilePath);
487 try (BufferedReader reader =
new BufferedReader(
new FileReader(regfile))) {
488 String line = reader.readLine();
489 while (line != null) {
491 if (line.toLowerCase().contains(
"error") || line.toLowerCase().contains(
"@inc")) {
492 logger.log(Level.WARNING,
"Regripper file {0} contains errors from run", errFilePath);
495 line = reader.readLine();
500 private void executeRegRipper(List<String> regRipperPath, Path regRipperHomeDir, String hiveFilePath, String hiveFileType, String outputFile, String errFile) {
502 List<String> commandLine =
new ArrayList<>();
503 for (String cmd : regRipperPath) {
504 commandLine.add(cmd);
506 commandLine.add(
"-r");
507 commandLine.add(hiveFilePath);
508 commandLine.add(
"-f");
509 commandLine.add(hiveFileType);
511 ProcessBuilder processBuilder =
new ProcessBuilder(commandLine);
512 processBuilder.directory(regRipperHomeDir.toFile());
513 processBuilder.redirectOutput(
new File(outputFile));
514 processBuilder.redirectError(
new File(errFile));
515 ExecUtil.execute(processBuilder,
new DataSourceIngestModuleProcessTerminator(context,
true));
516 }
catch (IOException ex) {
517 logger.log(Level.SEVERE, String.format(
"Error running RegRipper on %s", hiveFilePath), ex);
518 this.addErrorMessage(NbBundle.getMessage(
this.getClass(),
"ExtractRegistry.execRegRip.errMsg.failedAnalyzeRegFile", this.getName(), hiveFilePath));
531 private boolean parseAutopsyPluginOutput(String regFilePath, AbstractFile regFile) {
532 FileInputStream fstream = null;
533 List<BlackboardArtifact> newArtifacts =
new ArrayList<>();
536 File regfile =
new File(regFilePath);
537 fstream =
new FileInputStream(regfile);
538 String regString =
new Scanner(fstream,
"UTF-8").useDelimiter(
"\\Z").next();
539 String startdoc =
"<?xml version=\"1.0\"?><document>";
540 String result = regString.replaceAll(
"----------------------------------------",
"");
541 result = result.replaceAll(
"\\n",
"");
542 result = result.replaceAll(
"\\r",
"");
543 result = result.replaceAll(
"'",
"'");
544 result = result.replaceAll(
"&",
"&");
545 result = result.replace(
'\0',
' ');
546 String enddoc =
"</document>";
547 String stringdoc = startdoc + result + enddoc;
548 DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
549 Document doc = builder.parse(
new InputSource(
new StringReader(stringdoc)));
552 Element oroot = doc.getDocumentElement();
553 NodeList children = oroot.getChildNodes();
554 int len = children.getLength();
555 for (
int i = 0; i < len; i++) {
557 if (context.dataSourceIngestIsCancelled()) {
561 Element tempnode = (Element) children.item(i);
563 String dataType = tempnode.getNodeName();
564 NodeList timenodes = tempnode.getElementsByTagName(
"mtime");
566 if (timenodes.getLength() > 0) {
567 Element timenode = (Element) timenodes.item(0);
568 String etime = timenode.getTextContent();
570 if (etime != null && !etime.isEmpty()) {
572 mtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy", US).parse(etime).getTime();
573 String Tempdate = mtime.toString();
574 mtime = Long.valueOf(Tempdate) / MS_IN_SEC;
575 }
catch (ParseException ex) {
576 logger.log(Level.WARNING,
"Failed to parse epoch time when parsing the registry.", ex);
581 NodeList artroots = tempnode.getElementsByTagName(
"artifacts");
582 if (artroots.getLength() == 0) {
587 Element artroot = (Element) artroots.item(0);
588 NodeList myartlist = artroot.getChildNodes();
589 String parentModuleName = RecentActivityExtracterModuleFactory.getModuleName();
595 String systemRoot =
"";
596 String productId =
"";
597 String regOwner =
"";
599 Long installtime = null;
600 for (
int j = 0; j < myartlist.getLength(); j++) {
601 Node artchild = myartlist.item(j);
603 if (artchild.hasAttributes()) {
604 Element artnode = (Element) artchild;
606 String value = artnode.getTextContent();
608 value = value.trim();
610 String name = artnode.getAttribute(
"name");
620 version = version +
" " + value;
628 case "RegisteredOwner":
631 case "RegisteredOrganization":
635 if (value != null && !value.isEmpty()) {
637 installtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyyZ", US).parse(value+
"+0000").getTime();
638 String Tempdate = installtime.toString();
639 installtime = Long.valueOf(Tempdate) / MS_IN_SEC;
640 }
catch (ParseException e) {
641 logger.log(Level.WARNING,
"RegRipper::Conversion on DateTime -> ", e);
651 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
652 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, version));
653 if (installtime != null) {
654 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, installtime));
656 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, parentModuleName, systemRoot));
657 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PRODUCT_ID, parentModuleName, productId));
658 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_OWNER, parentModuleName, regOwner));
659 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ORGANIZATION, parentModuleName, regOrg));
662 ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
663 if (results.isEmpty()) {
664 newArtifacts.add(createArtifactWithAttributes(ARTIFACT_TYPE.TSK_OS_INFO, regFile, bbattributes));
666 results.get(0).addAttributes(bbattributes);
669 }
catch (TskCoreException ex) {
670 logger.log(Level.SEVERE, String.format(
"Error adding installed program artifact to blackboard for file %d.", regFile.getId()), ex);
675 String procArch =
"";
677 for (
int j = 0; j < myartlist.getLength(); j++) {
678 Node artchild = myartlist.item(j);
680 if (artchild.hasAttributes()) {
681 Element artnode = (Element) artchild;
683 String value = artnode.getTextContent().trim();
684 String name = artnode.getAttribute(
"name");
689 case "PROCESSOR_ARCHITECTURE":
692 case "PROCESSOR_IDENTIFIER":
703 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
704 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VERSION, parentModuleName, os));
705 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROCESSOR_ARCHITECTURE, parentModuleName, procArch));
706 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_TEMP_DIR, parentModuleName, tempDir));
709 ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
710 if (results.isEmpty()) {
711 newArtifacts.add(createArtifactWithAttributes(ARTIFACT_TYPE.TSK_OS_INFO, regFile, bbattributes));
713 results.get(0).addAttributes(bbattributes);
715 }
catch (TskCoreException ex) {
716 logger.log(Level.SEVERE, String.format(
"Error adding installed os_info to blackboard for file %d.", regFile.getId()), ex);
720 for (
int j = 0; j < myartlist.getLength(); j++) {
721 Node artchild = myartlist.item(j);
723 if (artchild.hasAttributes()) {
724 Element artnode = (Element) artchild;
726 String value = artnode.getTextContent().trim();
727 String name = artnode.getAttribute(
"name");
729 if (name.equals(
"ComputerName")) {
731 }
else if (name.equals(
"Domain")) {
737 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
738 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, compName));
739 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN, parentModuleName, domainName));
742 ArrayList<BlackboardArtifact> results = tskCase.getBlackboardArtifacts(ARTIFACT_TYPE.TSK_OS_INFO, regFile.getId());
743 if (results.isEmpty()) {
744 newArtifacts.add(createArtifactWithAttributes(ARTIFACT_TYPE.TSK_OS_INFO, regFile, bbattributes));
746 results.get(0).addAttributes(bbattributes);
748 for (Map.Entry<String, String> userMap : getUserNameMap().entrySet()) {
751 sid = userMap.getKey();
752 String userName = userMap.getValue();
753 createOrUpdateOsAccount(regFile, sid, userName, null);
754 }
catch(TskCoreException | TskDataException | NotUserSIDException ex) {
755 logger.log(Level.WARNING, String.format(
"Failed to update Domain for existing OsAccount: %s, sid: %s", regFile.getId(), sid), ex);
758 }
catch (TskCoreException ex) {
759 logger.log(Level.SEVERE, String.format(
"Error adding os_info artifact to blackboard for file %d.", regFile.getId()), ex);
763 for (
int j = 0; j < myartlist.getLength(); j++) {
764 Node artchild = myartlist.item(j);
766 if (artchild.hasAttributes()) {
767 Element artnode = (Element) artchild;
769 String value = artnode.getTextContent().trim();
770 Collection<BlackboardAttribute> bbattributes =
new ArrayList<>();
783 Long usbMtime = Long.parseLong(artnode.getAttribute(
"mtime"));
784 usbMtime = Long.valueOf(usbMtime.toString());
785 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, usbMtime));
786 String dev = artnode.getAttribute(
"dev");
789 if (dev.toLowerCase().contains(
"vid")) {
790 USBInfo info = USB_MAPPER.parseAndLookup(dev);
791 if (info.getVendor() != null) {
792 make = info.getVendor();
794 if (info.getProduct() != null) {
795 model = info.getProduct();
798 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, parentModuleName, make));
799 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, parentModuleName, model));
800 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, value));
801 newArtifacts.add(createArtifactWithAttributes(ARTIFACT_TYPE.TSK_DEVICE_ATTACHED, regFile, bbattributes));
802 }
catch (TskCoreException ex) {
803 logger.log(Level.SEVERE, String.format(
"Error adding device_attached artifact to blackboard for file %d.", regFile.getId()), ex);
807 Long itemMtime = null;
809 String mTimeAttr = artnode.getAttribute(
"mtime");
810 if (mTimeAttr != null && !mTimeAttr.isEmpty()) {
811 itemMtime =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy", US).parse(mTimeAttr).getTime();
812 itemMtime /= MS_IN_SEC;
814 }
catch (ParseException ex) {
815 logger.log(Level.SEVERE,
"Failed to parse epoch time for installed program artifact.", ex);
819 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, value));
820 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, itemMtime));
821 BlackboardArtifact bbart = regFile.newDataArtifact(
new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_INSTALLED_PROG), bbattributes);
822 newArtifacts.add(bbart);
823 }
catch (TskCoreException ex) {
824 logger.log(Level.SEVERE,
"Error adding installed program artifact to blackboard.", ex);
828 String officeName = artnode.getAttribute(
"name");
833 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, parentModuleName, mtime));
835 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, parentModuleName, officeName));
836 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE, parentModuleName, value));
837 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, parentModuleName, artnode.getNodeName()));
838 BlackboardArtifact bbart = regFile.newDataArtifact(
new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_RECENT_OBJECT), bbattributes);
840 newArtifacts.add(bbart);
841 }
catch (TskCoreException ex) {
842 logger.log(Level.SEVERE,
"Error adding recent object artifact to blackboard.", ex);
846 case "ProcessorArchitecture":
862 String homeDir = value;
863 String sid = artnode.getAttribute(
"sid");
864 String username = artnode.getAttribute(
"username");
867 createOrUpdateOsAccount(regFile, sid, username, homeDir);
868 }
catch(TskCoreException | TskDataException | NotUserSIDException ex) {
869 logger.log(Level.SEVERE, String.format(
"Failed to create OsAccount for file: %s, sid: %s", regFile.getId(), sid), ex);
873 case "NtuserNetwork":
875 String localPath = artnode.getAttribute(
"localPath");
876 String remoteName = value;
878 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LOCAL_PATH,
879 parentModuleName, localPath));
880 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REMOTE_PATH,
881 parentModuleName, remoteName));
882 BlackboardArtifact bbart = regFile.newDataArtifact(
new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_REMOTE_DRIVE), bbattributes);
883 newArtifacts.add(bbart);
884 }
catch (TskCoreException ex) {
885 logger.log(Level.SEVERE,
"Error adding network artifact to blackboard.", ex);
889 String adapter = artnode.getAttribute(
"adapter");
891 Long lastWriteTime = Long.parseLong(artnode.getAttribute(
"writeTime"));
892 lastWriteTime = Long.valueOf(lastWriteTime.toString());
893 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SSID, parentModuleName, value));
894 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, parentModuleName, lastWriteTime));
895 bbattributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_ID, parentModuleName, adapter));
896 BlackboardArtifact bbart = regFile.newDataArtifact(
new BlackboardArtifact.Type(ARTIFACT_TYPE.TSK_WIFI_NETWORK), bbattributes);
897 newArtifacts.add(bbart);
898 }
catch (TskCoreException ex) {
899 logger.log(Level.SEVERE,
"Error adding SSID artifact to blackboard.", ex);
909 logger.log(Level.SEVERE,
"Unrecognized node name: {0}", dataType);
918 }
catch (FileNotFoundException ex) {
919 logger.log(Level.WARNING, String.format(
"Error finding the registry file: %s", regFilePath), ex);
920 }
catch (SAXException ex) {
921 logger.log(Level.WARNING, String.format(
"Error parsing the registry XML: %s", regFilePath), ex);
922 }
catch (IOException ex) {
923 logger.log(Level.WARNING, String.format(
"Error building the document parser: %s", regFilePath), ex);
924 }
catch (ParserConfigurationException ex) {
925 logger.log(Level.WARNING, String.format(
"Error configuring the registry parser: %s", regFilePath), ex);
928 if (fstream != null) {
931 }
catch (IOException ex) {
934 if (!context.dataSourceIngestIsCancelled()) {
935 postArtifacts(newArtifacts);
941 private boolean parseSystemPluginOutput(String regfilePath, AbstractFile regAbstractFile) {
942 File regfile =
new File(regfilePath);
943 try (BufferedReader reader =
new BufferedReader(
new FileReader(regfile))) {
944 String line = reader.readLine();
945 while (line != null) {
948 if (line.toLowerCase().matches(
"^bam v.*")) {
949 parseBamKey(regAbstractFile, reader, Bundle.Registry_System_Bam());
950 }
else if (line.toLowerCase().matches(
"^bthport v..*")) {
951 parseBlueToothDevices(regAbstractFile, reader);
953 line = reader.readLine();
956 }
catch (FileNotFoundException ex) {
957 logger.log(Level.WARNING,
"Error finding the registry file.", ex);
958 }
catch (IOException ex) {
959 logger.log(Level.WARNING,
"Error reading the system hive: {0}", ex);
978 private void parseBlueToothDevices(AbstractFile regFile, BufferedReader reader)
throws FileNotFoundException, IOException {
979 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
980 String line = reader.readLine();
981 while ((line != null) && (!line.contains(SECTION_DIVIDER))) {
982 line = reader.readLine();
988 if ((line != null) && (line.toLowerCase().contains(
"device unique id"))) {
992 while (line != null && !line.contains(SECTION_DIVIDER) && !line.isEmpty() && !line.toLowerCase().contains(
"radio support not found")) {
993 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
994 addBlueToothAttribute(line, attributes, TSK_DEVICE_ID);
995 line = reader.readLine();
997 if ((line != null) && (line.toLowerCase().contains(
"name"))) {
998 addBlueToothAttribute(line, attributes, TSK_NAME);
999 line = reader.readLine();
1001 addBlueToothAttribute(line, attributes, TSK_DATETIME);
1002 line = reader.readLine();
1003 addBlueToothAttribute(line, attributes, TSK_DATETIME_ACCESSED);
1006 bbartifacts.add(createArtifactWithAttributes(ARTIFACT_TYPE.TSK_BLUETOOTH_PAIRING, regFile, attributes));
1007 }
catch (TskCoreException ex) {
1008 logger.log(Level.SEVERE, String.format(
"Failed to create bluetooth_pairing artifact for file %d", regFile.getId()), ex);
1012 line = reader.readLine();
1021 if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1022 postArtifacts(bbartifacts);
1026 private void addBlueToothAttribute(String line, Collection<BlackboardAttribute> attributes, ATTRIBUTE_TYPE attributeType) {
1031 String tokens[] = line.split(
": ");
1032 if (tokens.length > 1 && !tokens[1].isEmpty()) {
1033 String tokenString = tokens[1];
1034 if (attributeType.getDisplayName().toLowerCase().contains(
"date")) {
1035 String dateString = tokenString.toLowerCase().replace(
" z",
"");
1037 SimpleDateFormat dateFormat =
new SimpleDateFormat(
"EEE MMM d HH:mm:ss yyyy", US);
1038 Long dateLong = Long.valueOf(0);
1040 Date newDate = dateFormat.parse(dateString);
1041 dateLong = newDate.getTime() / 1000;
1042 }
catch (ParseException ex) {
1045 logger.log(Level.WARNING, String.format(
"Failed to parse date/time %s for Bluetooth Last Seen attribute.", dateString), ex);
1047 attributes.add(
new BlackboardAttribute(attributeType, getName(), dateLong));
1049 attributes.add(
new BlackboardAttribute(attributeType, getName(), tokenString));
1064 private boolean parseSamPluginOutput(String regFilePath, AbstractFile regAbstractFile,
long ingestJobId) {
1066 File regfile =
new File(regFilePath);
1067 List<BlackboardArtifact> newArtifacts =
new ArrayList<>();
1068 try (BufferedReader bufferedReader =
new BufferedReader(
new InputStreamReader(
new FileInputStream(regfile), StandardCharsets.UTF_8))) {
1070 String userInfoSection =
"User Information";
1071 String previousLine = null;
1072 String line = bufferedReader.readLine();
1073 Set<Map<String, String>> userSet =
new HashSet<>();
1074 Map<String, List<String>> groupMap = null;
1075 while (line != null) {
1076 if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains(userInfoSection)) {
1077 readUsers(bufferedReader, userSet);
1080 if (line.contains(SECTION_DIVIDER) && previousLine != null && previousLine.contains(
"Group Membership Information")) {
1081 groupMap = readGroups(bufferedReader);
1084 previousLine = line;
1085 line = bufferedReader.readLine();
1087 Map<String, Map<String, String>> userInfoMap =
new HashMap<>();
1089 for (Map<String, String> userInfo : userSet) {
1090 userInfoMap.put(userInfo.get(SID_KEY), userInfo);
1094 OsAccountManager accountMgr = tskCase.getOsAccountManager();
1095 HostManager hostMrg = tskCase.getHostManager();
1096 Host host = hostMrg.getHostByDataSource((DataSource)dataSource);
1098 List<OsAccount> existingAccounts = accountMgr.getOsAccounts(host);
1099 for(OsAccount osAccount: existingAccounts) {
1100 Optional<String> optional = osAccount.getAddr();
1101 if(!optional.isPresent()) {
1105 String sid = optional.get();
1106 Map<String, String> userInfo = userInfoMap.remove(sid);
1107 if(userInfo != null) {
1108 updateOsAccount(osAccount, userInfo, groupMap.get(sid), regAbstractFile);
1113 for (Map<String, String> userInfo : userInfoMap.values()) {
1114 OsAccount osAccount = accountMgr.newWindowsOsAccount(userInfo.get(SID_KEY), null, domainName, host, domainName != null && !domainName.isEmpty() ? OsAccountRealm.RealmScope.DOMAIN : OsAccountRealm.RealmScope.UNKNOWN);
1115 accountMgr.newOsAccountInstance(osAccount, (DataSource)dataSource, OsAccountInstance.OsAccountInstanceType.LAUNCHED);
1116 updateOsAccount(osAccount, userInfo, groupMap.get(userInfo.get(SID_KEY)), regAbstractFile);
1119 }
catch (FileNotFoundException ex) {
1120 logger.log(Level.WARNING,
"Error finding the registry file.", ex);
1121 }
catch (IOException ex) {
1122 logger.log(Level.WARNING,
"Error building the document parser: {0}", ex);
1123 }
catch (TskDataException | TskCoreException ex) {
1124 logger.log(Level.WARNING,
"Error updating TSK_OS_ACCOUNT artifacts to include newly parsed data.", ex);
1125 }
catch (OsAccountManager.NotUserSIDException ex) {
1126 logger.log(Level.WARNING,
"Error creating OS Account, input SID is not a user SID.", ex);
1129 if (!context.dataSourceIngestIsCancelled()) {
1130 postArtifacts(newArtifacts);
1147 private void readUsers(BufferedReader bufferedReader, Set<Map<String, String>> users) throws IOException {
1148 String line = bufferedReader.readLine();
1150 String userName =
"";
1151 String user_rid =
"";
1152 while (line != null && !line.contains(SECTION_DIVIDER)) {
1154 if (line.contains(USERNAME_KEY)) {
1155 String regx = USERNAME_KEY +
"\\s*?:";
1156 String userNameAndIdString = line.replaceAll(regx,
"");
1157 userName = userNameAndIdString.substring(0, userNameAndIdString.lastIndexOf(
'[')).trim();
1158 user_rid = userNameAndIdString.substring(userNameAndIdString.lastIndexOf(
'['), userNameAndIdString.lastIndexOf(
']'));
1159 }
else if (line.contains(SID_KEY) && !userName.isEmpty()) {
1160 Map.Entry<String, String> entry = getSAMKeyValue(line);
1162 HashMap<String, String> userInfo =
new HashMap<>();
1163 userInfo.put(USERNAME_KEY, userName);
1164 userInfo.put(RID_KEY, user_rid);
1165 userInfo.put(entry.getKey(), entry.getValue());
1168 line = bufferedReader.readLine();
1169 while (line != null && !line.isEmpty()) {
1170 entry = getSAMKeyValue(line);
1171 if (entry != null) {
1172 userInfo.put(entry.getKey(), entry.getValue());
1174 line = bufferedReader.readLine();
1176 users.add(userInfo);
1180 line = bufferedReader.readLine();
1193 private void createRecentlyUsedArtifacts(String regFileName, AbstractFile regFile)
throws FileNotFoundException, IOException {
1194 File regfile =
new File(regFileName);
1195 try (BufferedReader reader =
new BufferedReader(
new FileReader(regfile))) {
1196 String line = reader.readLine();
1197 while (line != null) {
1200 if (line.matches(
"^adoberdr v.*")) {
1201 parseAdobeMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Adobe());
1202 }
else if (line.matches(
"^mpmru v.*")) {
1203 parseMediaPlayerMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Mediaplayer());
1204 }
else if (line.matches(
"^trustrecords v.*")) {
1205 parseOfficeTrustRecords(regFile, reader, Bundle.Recently_Used_Artifacts_Office_Trustrecords());
1206 }
else if (line.matches(
"^ArcHistory:")) {
1207 parse7ZipMRU(regFile, reader, Bundle.Recently_Used_Artifacts_ArcHistory());
1208 }
else if (line.matches(
"^applets v.*")) {
1209 parseGenericMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Applets());
1210 }
else if (line.matches(
"^mmc v.*")) {
1211 parseGenericMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Mmc());
1212 }
else if (line.matches(
"^winrar v.*")) {
1213 parseWinRARMRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Winrar());
1214 }
else if (line.matches(
"^officedocs2010 v.*")) {
1215 parseOfficeDocs2010MRUList(regFile, reader, Bundle.Recently_Used_Artifacts_Officedocs());
1217 line = reader.readLine();
1233 private void parseBamKey(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1234 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1235 String line = reader.readLine();
1237 while (!line.contains(SECTION_DIVIDER)) {
1238 line = reader.readLine();
1241 line = reader.readLine();
1243 while (!line.contains(SECTION_DIVIDER)) {
1246 String tokens[] = line.split(
"\\|");
1247 Long progRunDateTime = Long.valueOf(tokens[0]);
1250 String fileNameSid[] = tokens[4].split(
"\\s+\\(S-");
1251 String userSid =
"S-" + fileNameSid[1].substring(0, fileNameSid[1].length() - 1);
1252 String userName = getUserNameMap().get(userSid);
1253 if (userName == null) {
1256 String fileName = fileNameSid[0];
1257 if (fileName.startsWith(
"\\Device\\HarddiskVolume")) {
1259 int fileNameStart = fileName.indexOf(
'\\', 16);
1260 fileName = fileName.substring(fileNameStart, fileName.length());
1263 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1264 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME, getName(), fileName));
1265 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USER_NAME, getName(), userName));
1266 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, getName(), progRunDateTime));
1267 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_COMMENT, getName(), comment));
1270 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_PROG_RUN, regFile, attributes);
1271 bbartifacts.add(bba);
1272 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1274 bbartifacts.add(bba);
1276 }
catch (TskCoreException ex) {
1277 logger.log(Level.SEVERE, String.format(
"Failed to create TSK_PROG_RUN artifact for file %d", regFile.getId()), ex);
1279 line = reader.readLine();
1281 if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1282 postArtifacts(bbartifacts);
1297 private void parseAdobeMRUList(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1298 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1299 String line = reader.readLine();
1300 SimpleDateFormat adobePluginDateFormat =
new SimpleDateFormat(
"yyyyMMddHHmmssZ", US);
1301 Long adobeUsedTime = Long.valueOf(0);
1302 while (!line.contains(SECTION_DIVIDER)) {
1303 line = reader.readLine();
1305 if (line.matches(
"^Key name,file name,sDate,uFileSize,uPageCount")) {
1306 line = reader.readLine();
1309 while (!line.contains(SECTION_DIVIDER)) {
1312 String tokens[] = line.split(
",(?=([^\"]*\"[^\"]*\")*[^\"]*$)");
1313 String fileName = tokens[1].substring(0, tokens[1].length() - 1);
1314 fileName = fileName.replace(
"\"",
"");
1315 if (fileName.charAt(0) ==
'/') {
1316 fileName = fileName.substring(1, fileName.length() - 1);
1317 fileName = fileName.replaceFirst(
"/",
":/");
1320 if (tokens.length > 2) {
1323 String fileUsedTime = tokens[2].replaceAll(
"'",
"");
1324 Date usedDate = adobePluginDateFormat.parse(fileUsedTime);
1325 adobeUsedTime = usedDate.getTime() / 1000;
1326 }
catch (ParseException ex) {
1329 logger.log(Level.WARNING, String.format(
"Failed to parse date/time %s for adobe file artifact.", tokens[2]), ex);
1332 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1333 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1334 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, getName(), adobeUsedTime));
1335 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1337 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1339 bbartifacts.add(bba);
1340 fileName = fileName.replace(
"\0",
"");
1341 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1343 bbartifacts.add(bba);
1346 }
catch(TskCoreException ex) {
1347 logger.log(Level.SEVERE, String.format(
"Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1349 line = reader.readLine();
1354 if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1355 postArtifacts(bbartifacts);
1371 private void parseMediaPlayerMRUList(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1372 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1373 String line = reader.readLine();
1374 while (!line.contains(SECTION_DIVIDER)) {
1375 line = reader.readLine();
1377 if (line.contains(
"LastWrite")) {
1378 line = reader.readLine();
1381 while (!line.contains(SECTION_DIVIDER) && !line.contains(
"RecentFileList has no values.")) {
1383 String tokens[] = line.split(
"> ");
1384 String fileName = tokens[1];
1385 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1386 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1387 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1389 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1391 bbartifacts.add(bba);
1392 bba = createAssociatedArtifact(fileName, bba);
1394 bbartifacts.add(bba);
1395 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1397 bbartifacts.add(bba);
1401 }
catch(TskCoreException ex) {
1402 logger.log(Level.SEVERE, String.format(
"Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1404 line = reader.readLine();
1409 if (!bbartifacts.isEmpty()&& !context.dataSourceIngestIsCancelled()) {
1410 postArtifacts(bbartifacts);
1426 private void parseGenericMRUList(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1427 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1428 String line = reader.readLine();
1429 while (!line.contains(SECTION_DIVIDER)) {
1430 line = reader.readLine();
1432 if (line.contains(
"LastWrite")) {
1433 line = reader.readLine();
1436 while (!line.contains(SECTION_DIVIDER) && !line.isEmpty() && !line.contains(
"Applets")
1437 && !line.contains((
"Recent File List"))) {
1439 String tokens[] = line.split(
"> ");
1440 if (tokens.length > 1) {
1441 String fileName = tokens[1];
1442 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1443 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1444 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1446 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1448 bbartifacts.add(bba);
1449 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1451 bbartifacts.add(bba);
1454 }
catch(TskCoreException ex) {
1455 logger.log(Level.SEVERE, String.format(
"Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1458 line = reader.readLine();
1463 if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1464 postArtifacts(bbartifacts);
1480 private void parseWinRARMRUList(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1481 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1482 String line = reader.readLine();
1483 while (!line.contains(SECTION_DIVIDER)) {
1484 line = reader.readLine();
1486 if (line.contains(
"LastWrite")) {
1487 line = reader.readLine();
1490 if (!line.isEmpty()) {
1491 while (!line.contains(SECTION_DIVIDER)) {
1493 String tokens[] = line.split(
"> ");
1494 String fileName = tokens[1];
1495 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1496 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1497 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1499 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1500 bbartifacts.add(bba);
1501 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1503 bbartifacts.add(bba);
1505 }
catch(TskCoreException ex) {
1506 logger.log(Level.SEVERE, String.format(
"Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1508 line = reader.readLine();
1514 if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1515 postArtifacts(bbartifacts);
1531 private void parse7ZipMRU(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1532 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1533 String line = reader.readLine();
1535 if (!line.contains(
"PathHistory:")) {
1536 while (!line.contains(
"PathHistory:") && !line.isEmpty()) {
1539 String fileName = line;
1540 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1541 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1542 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1544 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1545 bbartifacts.add(bba);
1546 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1548 bbartifacts.add(bba);
1551 }
catch(TskCoreException ex) {
1552 logger.log(Level.SEVERE, String.format(
"Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1554 line = reader.readLine();
1558 if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1559 postArtifacts(bbartifacts);
1575 private void parseOfficeDocs2010MRUList(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1576 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1577 String line = reader.readLine();
1581 while (!line.contains(SECTION_DIVIDER)) {
1582 line = reader.readLine();
1584 line = reader.readLine();
1585 while (!line.contains(SECTION_DIVIDER)) {
1588 String tokens[] = line.split(
"\\|");
1589 Long docDate = Long.valueOf(tokens[0]);
1590 String fileNameTokens[] = tokens[4].split(
" - ");
1591 String fileName = fileNameTokens[1];
1592 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1593 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1594 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, getName(), docDate));
1595 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1597 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1598 bbartifacts.add(bba);
1599 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1601 bbartifacts.add(bba);
1603 }
catch(TskCoreException ex) {
1604 logger.log(Level.SEVERE, String.format(
"Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1606 line = reader.readLine();
1609 if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1610 postArtifacts(bbartifacts);
1626 private void parseOfficeTrustRecords(AbstractFile regFile, BufferedReader reader, String comment)
throws FileNotFoundException, IOException {
1627 String userProfile = regFile.getParentPath();
1628 userProfile = userProfile.substring(0, userProfile.length() - 1);
1629 List<BlackboardArtifact> bbartifacts =
new ArrayList<>();
1630 SimpleDateFormat pluginDateFormat =
new SimpleDateFormat(
"EEE MMM dd HH:mm:ss yyyy", US);
1631 Long usedTime = Long.valueOf(0);
1632 String line = reader.readLine();
1633 while (!line.contains(SECTION_DIVIDER)) {
1634 line = reader.readLine();
1636 usedTime = Long.valueOf(0);
1637 if (!line.contains(
"**") && !line.contains(
"----------") && !line.contains(
"LastWrite")
1638 && !line.contains(SECTION_DIVIDER) && !line.isEmpty() && !line.contains(
"TrustRecords")
1639 && !line.contains(
"VBAWarnings =")) {
1643 String fileName = null;
1644 String tokens[] = line.split(
" : ");
1645 fileName = tokens[1];
1646 fileName = fileName.replace(
"%USERPROFILE%", userProfile);
1649 String fileUsedTime = tokens[0].replaceAll(
" Z",
"");
1650 Date usedDate = pluginDateFormat.parse(fileUsedTime);
1651 usedTime = usedDate.getTime() / 1000;
1652 }
catch (ParseException ex) {
1655 logger.log(Level.WARNING, String.format(
"Failed to parse date/time %s for TrustRecords artifact.", tokens[0]), ex);
1657 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1658 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), fileName));
1659 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED, getName(), usedTime));
1660 attributes.add(
new BlackboardAttribute(TSK_COMMENT, getName(), comment));
1662 BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes);
1663 bbartifacts.add(bba);
1664 bba = createAssociatedArtifact(FilenameUtils.normalize(fileName,
true), bba);
1666 bbartifacts.add(bba);
1668 }
catch(TskCoreException ex) {
1669 logger.log(Level.SEVERE, String.format(
"Failed to create TSK_RECENT_OBJECT artifact for file %d", regFile.getId()), ex);
1674 if (!bbartifacts.isEmpty() && !context.dataSourceIngestIsCancelled()) {
1675 postArtifacts(bbartifacts);
1689 private BlackboardArtifact createAssociatedArtifact(String filePathName, BlackboardArtifact bba) {
1690 String fileName = FilenameUtils.getName(filePathName);
1691 String filePath = FilenameUtils.getPath(filePathName);
1692 List<AbstractFile> sourceFiles;
1694 sourceFiles = currentCase.getSleuthkitCase().getFileManager().findFilesExactNameExactPath(dataSource, fileName, filePath);
1695 if (!sourceFiles.isEmpty()) {
1696 return createAssociatedArtifact(sourceFiles.get(0), bba);
1698 }
catch (TskCoreException ex) {
1701 logger.log(Level.WARNING, String.format(
"Error finding actual file %s. file may not exist", filePathName));
1716 private Map<String, String> makeUserNameMap(Content dataSource)
throws TskCoreException {
1717 Map<String, String> map =
new HashMap<>();
1719 for(OsAccount account: tskCase.getOsAccountManager().getOsAccounts(((DataSource)dataSource).getHost())) {
1720 Optional<String> userName = account.getLoginName();
1721 map.put(account.getName(), userName.isPresent() ? userName.get() :
"");
1732 private Map<String, String> getUserNameMap() {
1733 if(userNameMap == null) {
1737 userNameMap = makeUserNameMap(dataSource);
1738 }
catch (TskCoreException ex) {
1739 logger.log(Level.WARNING,
"Unable to create OS Account user name map", ex);
1742 userNameMap =
new HashMap<>();
1759 private BlackboardAttribute getAttributeForArtifact(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE type) throws TskCoreException {
1760 return artifact.getAttribute(
new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.fromID(type.getTypeID())));
1771 void createShellBagArtifacts(AbstractFile regFile, List<ShellBag> shellbags)
throws TskCoreException {
1772 List<BlackboardArtifact> artifacts =
new ArrayList<>();
1773 List<DataArtifact> dataArtifacts =
new ArrayList<>();
1775 for (ShellBag bag : shellbags) {
1776 Collection<BlackboardAttribute> attributes =
new ArrayList<>();
1777 attributes.add(
new BlackboardAttribute(TSK_PATH, getName(), bag.getResource()));
1778 attributes.add(
new BlackboardAttribute(getKeyAttribute(), getName(), bag.getKey()));
1781 time = bag.getLastWrite();
1783 attributes.add(
new BlackboardAttribute(getLastWriteAttribute(), getName(), time));
1786 time = bag.getModified();
1788 attributes.add(
new BlackboardAttribute(TSK_DATETIME_MODIFIED, getName(), time));
1791 time = bag.getCreated();
1793 attributes.add(
new BlackboardAttribute(TSK_DATETIME_CREATED, getName(), time));
1796 time = bag.getAccessed();
1798 attributes.add(
new BlackboardAttribute(TSK_DATETIME_ACCESSED, getName(), time));
1801 BlackboardArtifact artifact = createArtifactWithAttributes(getShellBagArtifact(), regFile, attributes);
1802 artifacts.add(artifact);
1803 dataArtifacts.add((DataArtifact)artifact);
1806 if(!context.dataSourceIngestIsCancelled()) {
1807 postArtifacts(artifacts);
1808 context.addDataArtifactsToJob(dataArtifacts);
1821 private BlackboardArtifact.Type getShellBagArtifact() throws TskCoreException {
1822 if (shellBagArtifactType == null) {
1824 shellBagArtifactType = tskCase.getBlackboard().getOrAddArtifactType(SHELLBAG_ARTIFACT_NAME, Bundle.Shellbag_Artifact_Display_Name());
1825 }
catch (BlackboardException ex) {
1826 throw new TskCoreException(String.format(
"Failed to get shell bag artifact type", SHELLBAG_ARTIFACT_NAME), ex);
1830 return shellBagArtifactType;
1841 private BlackboardAttribute.Type getLastWriteAttribute() throws TskCoreException {
1842 if (shellBagLastWriteAttributeType == null) {
1844 shellBagLastWriteAttributeType = tskCase.getBlackboard().getOrAddAttributeType(SHELLBAG_ATTRIBUTE_LAST_WRITE,
1845 BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME,
1846 Bundle.Shellbag_Last_Write_Attribute_Display_Name());
1847 }
catch (BlackboardException ex) {
1849 throw new TskCoreException(String.format(
"Failed to get custom attribute %s", SHELLBAG_ATTRIBUTE_LAST_WRITE), ex);
1852 return shellBagLastWriteAttributeType;
1863 private BlackboardAttribute.Type getKeyAttribute() throws TskCoreException {
1864 if (shellBagKeyAttributeType == null) {
1866 shellBagKeyAttributeType = tskCase.getBlackboard().getOrAddAttributeType(SHELLBAG_ATTRIBUTE_KEY,
1867 BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING,
1868 Bundle.Shellbag_Key_Attribute_Display_Name());
1869 }
catch (BlackboardException ex) {
1870 throw new TskCoreException(String.format(
"Failed to get key attribute %s", SHELLBAG_ATTRIBUTE_KEY), ex);
1873 return shellBagKeyAttributeType;
1885 Map<String, List<String>> readGroups(BufferedReader bufferedReader)
throws IOException {
1886 Map<String, List<String>> groupMap =
new HashMap<>();
1888 String line = bufferedReader.readLine();
1891 String groupName = null;
1893 while (line != null && !line.contains(SECTION_DIVIDER)) {
1895 if (line.contains(
"Group Name")) {
1896 String value = line.replaceAll(
"Group Name\\s*?:",
"").trim();
1897 groupName = (value.replaceAll(
"\\[\\d*?\\]",
"")).trim();
1898 int startIndex = value.indexOf(
" [") + 1;
1899 int endIndex = value.indexOf(
']');
1901 if (startIndex != -1 && endIndex != -1) {
1902 String countStr = value.substring(startIndex + 1, endIndex);
1903 userCount = Integer.parseInt(countStr);
1905 }
else if (line.matches(
"Users\\s*?:")) {
1906 for (
int i = 0; i < userCount; i++) {
1907 line = bufferedReader.readLine();
1909 String sid = line.trim();
1910 List<String> groupList = groupMap.get(sid);
1911 if (groupList == null) {
1912 groupList =
new ArrayList<>();
1913 groupMap.put(sid, groupList);
1915 groupList.add(groupName);
1920 line = bufferedReader.readLine();
1933 private Map.Entry<String, String> getSAMKeyValue(String line) {
1934 int index = line.indexOf(
':');
1935 Map.Entry<String, String> returnValue = null;
1937 String value = null;
1940 key = line.substring(0, index).trim();
1941 if (index + 1 < line.length()) {
1942 value = line.substring(index + 1).trim();
1947 }
else if (line.contains(
"-->")) {
1948 key = line.replace(
"-->",
"").trim();
1953 returnValue =
new AbstractMap.SimpleEntry<>(key, value);
1960 public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) {
1961 this.dataSource = dataSource;
1962 this.context = context;
1964 progressBar.progress(Bundle.Progress_Message_Analyze_Registry());
1965 analyzeRegistryFiles(context.getJobId());
1974 public String autopsyPlugins =
"";
1975 public String fullPlugins =
"";
1990 private void createOrUpdateOsAccount(AbstractFile file, String sid, String userName, String homeDir)
throws TskCoreException, TskDataException, NotUserSIDException {
1991 OsAccountManager accountMgr = tskCase.getOsAccountManager();
1992 HostManager hostMrg = tskCase.getHostManager();
1993 Host host = hostMrg.getHostByDataSource((DataSource)dataSource);
1995 Optional<OsAccount> optional = accountMgr.getWindowsOsAccount(sid, null, null, host);
1996 OsAccount osAccount;
1997 if (!optional.isPresent()) {
1998 osAccount = accountMgr.newWindowsOsAccount(sid, userName != null && userName.isEmpty() ? null : userName, domainName, host, domainName != null && !domainName.isEmpty()? OsAccountRealm.RealmScope.DOMAIN : OsAccountRealm.RealmScope.UNKNOWN);
1999 accountMgr.newOsAccountInstance(osAccount, (DataSource)dataSource, OsAccountInstance.OsAccountInstanceType.LAUNCHED);
2001 osAccount = optional.get();
2002 if (userName != null && !userName.isEmpty()) {
2003 OsAccountUpdateResult updateResult= accountMgr.updateCoreWindowsOsAccountAttributes(osAccount, null, userName, domainName.isEmpty() ? null : domainName, host);
2004 osAccount = updateResult.getUpdatedAccount().orElse(osAccount);
2008 if (homeDir != null && !homeDir.isEmpty()) {
2009 List<OsAccountAttribute> attributes =
new ArrayList<>();
2010 String dir = homeDir.replaceFirst(
"^(%\\w*%)",
"");
2011 dir = dir.replace(
"\\",
"/");
2012 attributes.add(createOsAccountAttribute(TSK_HOME_DIR, dir, osAccount, host, file));
2013 accountMgr.addExtendedOsAccountAttributes(osAccount, attributes);
2024 private void addEmailAccount(AbstractFile regFile, String emailAddress) {
2026 currentCase.getSleuthkitCase()
2027 .getCommunicationsManager()
2028 .createAccountFileInstance(Account.Type.EMAIL,
2029 emailAddress, getRAModuleName(), regFile);
2030 }
catch (TskCoreException ex) {
2031 logger.log(Level.SEVERE,
2032 String.format(
"Error adding email account with value "
2033 +
"%s, to the case database for file %s [objId=%d]",
2034 emailAddress, regFile.getName(), regFile.getId()), ex);
2046 private Long parseRegRipTime(String value) {
2048 return REG_RIPPER_TIME_FORMAT.parse(value).getTime() / MS_IN_SEC;
2049 }
catch (ParseException ex) {
2050 logger.log(Level.SEVERE, String.format(
"Failed to parse reg rip time: %s", value));
2066 private void updateOsAccount(OsAccount osAccount, Map<String, String> userInfo, List<String> groupList, AbstractFile regFile)
throws TskDataException, TskCoreException, NotUserSIDException {
2067 Host host = ((DataSource)dataSource).getHost();
2069 SimpleDateFormat regRipperTimeFormat =
new SimpleDateFormat(
"EEE MMM dd HH:mm:ss yyyy 'Z'", US);
2070 regRipperTimeFormat.setTimeZone(getTimeZone(
"GMT"));
2072 List<OsAccountAttribute> attributes =
new ArrayList<>();
2074 Long creationTime = null;
2076 String value = userInfo.get(ACCOUNT_CREATED_KEY);
2077 if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
2078 creationTime = parseRegRipTime(value);
2081 value = userInfo.get(LAST_LOGIN_KEY);
2082 if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
2083 Long time = parseRegRipTime(value);
2085 attributes.add(createOsAccountAttribute(TSK_DATETIME_ACCESSED,
2086 parseRegRipTime(value),
2087 osAccount, host, regFile));
2091 String loginName = null;
2092 value = userInfo.get(USERNAME_KEY);
2093 if (value != null && !value.isEmpty()) {
2097 value = userInfo.get(LOGIN_COUNT_KEY);
2098 if (value != null && !value.isEmpty()) {
2099 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_COUNT,
2100 Integer.parseInt(value),
2101 osAccount, host, regFile));
2107 value = userInfo.get(ACCOUNT_TYPE_KEY);
2108 if (value != null && !value.isEmpty() && value.toLowerCase().contains(
"admin")) {
2109 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_IS_ADMIN,
2110 1, osAccount, host, regFile));
2113 value = userInfo.get(USER_COMMENT_KEY);
2114 if (value != null && !value.isEmpty()) {
2115 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_DESCRIPTION,
2116 value, osAccount, host, regFile));
2119 value = userInfo.get(INTERNET_NAME_KEY);
2120 if (value != null && !value.isEmpty()) {
2121 addEmailAccount(regFile, value);
2123 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_EMAIL,
2124 value, osAccount, host, regFile));
2128 String fullName = null;
2129 value = userInfo.get(FULL_NAME_KEY);
2130 if (value != null && !value.isEmpty()) {
2133 value = userInfo.get(NAME_KEY);
2134 if (value != null && !value.isEmpty()) {
2139 value = userInfo.get(PWD_RESET_KEY);
2140 if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
2141 Long time = parseRegRipTime(value);
2143 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_PASSWORD_RESET,
2144 time, osAccount, host, regFile));
2148 value = userInfo.get(PASSWORD_HINT);
2149 if (value != null && !value.isEmpty()) {
2150 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_HINT,
2151 value, osAccount, host, regFile));
2154 value = userInfo.get(PWD_FAILE_KEY);
2155 if (value != null && !value.isEmpty() && !value.equals(NEVER_DATE)) {
2156 Long time = parseRegRipTime(value);
2158 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_PASSWORD_FAIL,
2159 time, osAccount, host, regFile));
2163 String settingString = getSettingsFromMap(PASSWORD_SETTINGS_FLAGS, userInfo);
2164 if (!settingString.isEmpty()) {
2165 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_PASSWORD_SETTINGS,
2166 settingString, osAccount, host, regFile));
2169 settingString = getSettingsFromMap(ACCOUNT_SETTINGS_FLAGS, userInfo);
2170 if (!settingString.isEmpty()) {
2171 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_ACCOUNT_SETTINGS,
2172 settingString, osAccount, host, regFile));
2175 settingString = getSettingsFromMap(ACCOUNT_TYPE_FLAGS, userInfo);
2176 if (!settingString.isEmpty()) {
2177 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_FLAG,
2178 settingString, osAccount, host, regFile));
2181 if (groupList != null && groupList.isEmpty()) {
2182 String groups = groupList.stream()
2183 .map(String::valueOf)
2184 .collect(Collectors.joining(
", "));
2186 attributes.add(createOsAccountAttribute(ATTRIBUTE_TYPE.TSK_GROUPS,
2187 groups, osAccount, host, regFile));
2191 OsAccountManager accountMgr = tskCase.getOsAccountManager();
2192 accountMgr.addExtendedOsAccountAttributes(osAccount, attributes);
2195 accountMgr.updateCoreWindowsOsAccountAttributes(osAccount, null, loginName, domainName.isEmpty() ? null : domainName, host);
2198 accountMgr.updateStandardOsAccountAttributes(osAccount, fullName, null, null, creationTime);
2211 private String getSettingsFromMap(String[] keys, Map<String, String> map) {
2212 List<String> settingsList =
new ArrayList<>();
2213 for (String setting : keys) {
2214 if (map.containsKey(setting)) {
2215 settingsList.add(setting);
2219 if (!settingsList.isEmpty()) {
2220 return settingsList.stream()
2221 .map(String::valueOf)
2222 .collect(Collectors.joining(
", "));
2239 private OsAccountAttribute createOsAccountAttribute(BlackboardAttribute.ATTRIBUTE_TYPE type, String value, OsAccount osAccount, Host host, AbstractFile file) {
2240 return osAccount.new OsAccountAttribute(
new BlackboardAttribute.Type(type), value, osAccount, host, file);
2254 private OsAccountAttribute createOsAccountAttribute(BlackboardAttribute.ATTRIBUTE_TYPE type, Long value, OsAccount osAccount, Host host, AbstractFile file) {
2255 return osAccount.new OsAccountAttribute(
new BlackboardAttribute.Type(type), value, osAccount, host, file);
2269 private OsAccountAttribute createOsAccountAttribute(BlackboardAttribute.ATTRIBUTE_TYPE type, Integer value, OsAccount osAccount, Host host, AbstractFile file) {
2270 return osAccount.new OsAccountAttribute(
new BlackboardAttribute.Type(type), value, osAccount, host, file);